diff --git a/README.md b/README.md index 2b93a579..f63e92f5 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ - **Source code to provide the LWJGL keyboard, mouse, and OpenGL APIs in a browser** - **Patch files to mod the Minecraft 1.8 source code to make it browser compatible** - **Browser-modified portions of Minecraft 1.8's open-source dependencies** - - **Plugins for Minecraft servers to allow the eagler client to connect to them** ### This repository does NOT contain: @@ -85,57 +84,7 @@ If you are creating a resource pack and want to disable the blur filter on the m ## Making a Server -To make a server for EaglercraftX 1.8 the recommended software to use is EaglercraftXBungee ("EaglerXBungee") which is included in this repository in the `gateway/EaglercraftXBungee` folder. This is a plugin designed to be used with BungeeCord to allow Eaglercraft players to join your BungeeCord server. It is assumed that the reader already knows what BungeeCord is and has a working server set up that is joinable via java edition. If you don't know what BungeeCord is, please research the topic yourself first before continuing. Waterfall and FlameCord have also been tested, but EaglerXBungee was natively compiled against BungeeCord. - -There is an experimental velocity plugin available in `gateway/EaglercraftXVelocity` but it is still in development and not recommended for public servers, so be sure to check for updates regularly if you use it. Configuration files are basically identical to EaglercraftXBungee so its safe to just directy copy in your old EaglercraftXBungee config files to the `plugins/eaglerxvelocity` folder and they should work with a minimal number of edits if you are migrating your network from BungeeCord to Velocity. - -**Warning:** Both EaglerXBungee and EaglerXVelocity perform a lot of reflection that will inevitably break after a while when BungeeCord or Velocity is updated upstream. Both plugins will display the precise build number of BungeeCord and Velocity that has been tested by the developers and known to be compatible with EaglerXBungee and EaglerXVelocity when the proxy first starts up. If you are experiencing issues, try checking the BungeeCord or Velocity website for old versions and find the closest version number to whatever the current compatible version number is that is printed by EaglerXBungee/EaglerXVelocity, it will probably fix whatever missing functions the error messages are complaining about. - -### Detailed READMEs - -- [**EaglerXBungee README**](README_EAGLERXBUNGEE.md) -- [**EaglerXVelocity README**](README_EAGLERXVELOCITY.md) -- [**EaglerXBukkitAPI README**](README_EAGLERXBUKKITAPI.md) - -### Installation - -Obtain the latest version of the EaglerXBungee JAR file (it can be downloaded in the client from the "Multiplayer" screen) and place it in the "plugins" folder of your BungeeCord server. It's recommended to only join native Minecraft 1.8 servers through an EaglerXBungee server but plugins like ProtocolSupport have allowed some people to join newer servers too. - -Configuration files and other plugin data will be written in `plugins/EaglercraftXBungee` - -### Online Mode Instructions - -1. Enable `online_mode` in BungeeCord's `config.yml` file and make sure it works -2. Join the BungeeCord server using Minecraft Java Edition while logged into your Microsoft account -3. Run the `/eagler` command, it will give you a temporary login code -4. Disconnect from the server, close java edition, launch EaglercraftX 1.8 -5. Set your profile username to the username of your Microsoft account -6. Go to the "Multiplayer" menu, press "Direct Connect", press "Connect to Server", then enter "ws://localhost:8081/" -7. If you are using a VPS, replace "localhost" with the IP address of the VPS when you connect -8. Press "Join Server", a login screen will be displayed, enter the temporary login code into the password field -9. EaglerXBungee will log you into the server as the Microsoft account you generated the login code with - -Players using EaglercraftX will be able to see the vanilla skins of players on the server using vanilla Minecraft, but players on the server using vanilla Minecraft won't be able to see the skins of players using Eaglercraft. Instead they will see the skin of the Minecraft account that was used when the Eaglercraft player originally ran the `/eagler` command. - -To disable this vanilla player skin feature and stop the plugin from downloading the textures of any player heads spawned with commands, edit the EaglercraftXBungee `settings.yml` file in the `plugins/EaglercraftXBungee` folder and change `download_vanilla_skins_to_clients` to `false`. Ratelimits configured in `settings.yml` define the maximum number of times per minute a single player is allowed to trigger profile/skin lookups and also define the maximum number of times per minute the entire server is allowed to actually perform profile/skin lookups. - -By default, EaglercraftXBungee will use a local SQLite database in the server's working directory to store player skins and authentication codes. SQLite will be downloaded automatically if it is not already present. If you would like to use MySQL or something else instead, EaglercraftXBungee is JDBC-based and supports any database type that you can find a driver for. You can set the path of the database, path of the driver JAR, and the name of the driver class (example: `org.sqlite.JDBC`) for storing player skins in `settings.yml` and for storing login codes and profiles in `authservice.yml`. - -### Offline Mode Instructions - -By setting `online_mode` to `false` in the BungeeCord `config.yml` the authentication system will be disabled and players will no longer be required to first generate a code to log in. This should only be used for testing or if you can't get the authentication system to work. EaglercraftXBungee's skin system is supposed to be able to display SkinsRestorer skins if you plan to have vanilla players on the server but it's not guaranteed. - -### Built-in HTTP server - -When configuring the EaglercraftXBungee `listeners.yml` file, every listener includes an `http_server` section that can be used to configure the listener to also behave like a regular HTTP server when the websocket address is entered into a browser. If this is disabled people will get the normal "404 Websocket Upgrade Failure" instead when they accidentally type your server address into their browser. `root` defines the path to the folder containing index.html and the other files you want to host, relative to the `plugins/EaglercraftXBungee` folder. This can be useful for hosting the client if the offline download doesn't work for some reason but might slow your BungeeCord server down if lots of people are loading it all the time. - -### Enabling Voice Chat - -Voice chat is disabled by default in EaglercraftXBungee because it is not recommended for use on public servers. To enable it, add or change `allow_voice: true` to your EaglercraftXBungee `listeners.yml` file. The main difference between Eaglercraft 1.5.2 and EaglercraftX 1.8's voice chat feature is that the "Global" channel now only includes other players on the same server as you instead of every single player connected to the same bungeecord proxy. If you would like to disable voice chat on certain servers, add the names of the servers to the `disable_voice_chat_on_servers` list in the EaglercraftXBungee `settings.yml` file. You may have to add this property to the YML file manually if you've upgraded your server from an older version of EaglercraftXBungee. - -### Disabling FNAW Skins - -Players are known to complain about the high-poly Five Nights At Winstons character skins making PVP harder because of the belief that they change a player's hitbox. If you would like to disable those skins in your PVP worlds you can either set `disable_fnaw_skins_everywhere: true` in your EaglercraftXBungee `settings.yml` file to disable them for all players on your whole BungeeCord proxy, or you can disable them on specific servers by adding the names of the servers to the `disable_fnaw_skins_on_servers` list also in `settings.yml` like with disabling voice chat. +To make a server for EaglercraftX 1.8 the recommended software to use is EaglercraftXServer ("EaglerXServer"), which you can get from lax1dude here: [https://lax1dude.net/eaglerxserver/](https://lax1dude.net/eaglerxserver/) ## Launch Options diff --git a/README_EAGLERXBUKKITAPI.md b/README_EAGLERXBUKKITAPI.md deleted file mode 100644 index e6f137bd..00000000 --- a/README_EAGLERXBUKKITAPI.md +++ /dev/null @@ -1,87 +0,0 @@ -# EaglercraftXBukkitAPI - -### [`gateway/EaglercraftXBukkitAPI/EaglercraftXBukkitAPI-Latest.jar`](gateway/EaglercraftXBukkitAPI/EaglercraftXBukkitAPI-Latest.jar) - -### "EaglerXBukkitAPI" is a Bukkit plugin and protocol to allow Bukkit plugins to easily communicate with an EaglerXBungee or EaglerXVelocity instance, its purpose is to provide a standardized interface for creating complex Bukkit plugins that tightly integrate with EaglercraftX features, that would otherwise require developers to also create a BungeeCord/Velocity plugin to act as a "middle man" for sending certain packets or listening for certain events. - -## Compiling EaglerXBukkitAPI - -Minimum JDK version is 8, since what we are doing here is actually fully within the limitations of the official Bukkit API, we have actually set up Gradle correctly for once. No dependencies have to be downloaded manually, just run `gradlew jar` and you are done. - -## Configuration Files - -EaglerXBukkitAPI has no configuration files, however you must to edit `settings.yml` on EaglerXBungee/EaglerXVelocity to add or change `enable_backend_rpc_api` to `true` first in order to enable it. - -## Initializing Connections - -EaglerXBukkitAPI uses Google Commons (Guava) futures in order to implement a system that is similar to JavaScript promises to asynchronously complete tasks without blocking any threads. You should never block and wait for a task to complete synchronously, use the `addCallback` function with an anonymous inner class instead. Here is an example of how to correctly initialize an EaglerXBukkitAPI connection: - -```java -// import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; -@EventHander -public void onPlayerJoinEvent(PlayerJoinEvent evt) { - IEaglerXBukkitAPI.createAPI(evt.getPlayer()) - .addCallback(new FutureCallback() { - @Override - public void onSuccess(IEaglerXBukkitAPI result) { - // Do stuff with result - } - @Override - public void onFailure(Throwable t) { - // Something went wrong - } - }); -} -``` - -You can call `createAPI` as many times as you want, subsequent calls will return the existing `IEaglerXBukkitAPI` handle instead of creating a new one. - -## Making a Request - -Here is a very simple example of using EaglerXBukkitAPI to determine the name of the website (origin) a player is using, assuming you've already used `createAPI` to initialize a new connection: - -```java -// ... -public void onSuccess(IEaglerXBukkitAPI apiObj) { - apiObj.requestPlayerOrigin().addCallback(new FutureCallback() { - @Override - public void onSuccess(ResponseString result) { - System.out.println("Player's origin is: " + result.string); - } - @Override - public void onFailure(Throwable t) { - // Something went wrong - } - }); -} -``` - -## Event Listeners - -Here is an example of how to use EaglerXBukkitAPI to remotely listen for server info webview events on an EaglerXBungee/EaglerXVelocity instance from a Bukkit plugin: - -```java -// ... -public void onSuccess(IEaglerXBukkitAPI apiObj) { - apiObj.addEventListener(EnumSubscribeEvents.EVENT_WEBVIEW_OPEN_CLOSE, - new IEaglerRPCEventListener() { - public void handleEvent(IEaglerXBukkitAPI api, EnumSubscribeEvents eventType, - EventWebViewOpenClose eventData) { - // Handle open/close events - } - }); - apiObj.addEventListener(EnumSubscribeEvents.EVENT_WEBVIEW_MESSAGE, - new IEaglerRPCEventListener() { - public void handleEvent(IEaglerXBukkitAPI api, EnumSubscribeEvents eventType, - EventWebViewMessage eventData) { - // Handle messages - } - }); - apiObj.subscribeEvents( - EnumSubscribeEvents.EVENT_WEBVIEW_OPEN_CLOSE, - EnumSubscribeEvents.EVENT_WEBVIEW_MESSAGE - ); -} -``` - -The rest of EaglerXBukkitAPI should be self explanatory, its just another EaglerXBungeeAPIHelper/EaglerXVelocityAPIHelper. diff --git a/README_EAGLERXBUNGEE.md b/README_EAGLERXBUNGEE.md deleted file mode 100644 index 466b855f..00000000 --- a/README_EAGLERXBUNGEE.md +++ /dev/null @@ -1,209 +0,0 @@ -# EaglercraftXBungee - -### [`gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar`](gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar) - -### "EaglerXBungee" is a plugin that allows the EaglercraftX 1.8 client to join BungeeCord servers, with an optional authentication system if online-mode is enabled. This is not a setup guide, this document is intended to be used as reference for EaglerXBungee's configuration files and provide some surface-level information meant for plugin developers. - -**Warning:** Both EaglerXBungee and EaglerXVelocity perform a lot of reflection that will inevitably break after a while when BungeeCord or Velocity is updated upstream. Both plugins will display the precise build number of BungeeCord and Velocity that has been tested by the developers and known to be compatible with EaglerXBungee and EaglerXVelocity when the proxy first starts up. If you are experiencing issues, try checking the BungeeCord or Velocity website for old versions and find the closest version number to whatever the current compatible version number is that is printed by EaglerXBungee/EaglerXVelocity, it will probably fix whatever missing functions the error messages are complaining about. - -## Compiling EaglerXBungee - -Minimum JDK version is 8, as of 1.3.0 we are finally using Gradle to compile EaglerXBungee instead of compiling it all manually, however you still need to manually download the latest version of BungeeCord and name it "BungeeCord.jar" and place it in the `deps` folder first before you continue. We just don't care enough to actually use Gradle correctly to download all the dependencies automatically when they are all subject to change at any time as BungeeCord recieves updates upstream. Use the "jar" task to automatically compile the EaglerXBungee JAR file. - -## Configuration Files - -### NOTE: Currently, the plugin does NOT automatically update config files, if you can't find an option in one of the configuration files documented here, you most likely need to add it to the file yourself! - -**The default contents of the config files for EaglerXBungee are stored in [`gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config`](gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config)** - -### `settings.yml` - -The settings.yml file is primarily used for configuring the built-in skin and cape service and certain connection options. - -- **`server_name:`** String, default value is `'EaglercraftXBungee Server'`, sets the name of this EaglercraftX server that is sent with query responses and used for the default "404 websocket upgrade failure" page. -- **`server_uuid:`** String, default value is randomized, sets the UUID of this EaglercraftX server to send with query responses, has no official uses outside of server lists. -- **`websocket_connection_timeout:`** Number, default value is `15000` milliseconds, sets how long a WebSocket connection can last without a ping before being disconnected. -- **`websocket_handshake_timeout:`** Number, default value is `5000` milliseconds, sets how long a connection can sit in the handshake phase before being disconnected. -- **`builtin_http_server_timeout:`** Number, default value is `10000` milliseconds, sets how long an HTTP request to the built-in HTTP server can remain open before being forcefully disconnected. -- **`http_websocket_compression_level:`** Number, default value is `6`, sets the ZLIB compression level (0-9) to use for compressing websocket frames, set to 0 to disable if HTTP compression is already handled through a reverse proxy. You almost definitely need some level of compression for the game to be playable on WiFi networks. -- **`download_vanilla_skins_to_clients:`** Boolean, default value is `true`, sets if the server should download the textures of custom skulls and skins of vanilla online-mode players from Mojang's servers to cache locally and send to all EaglercraftX clients on the server that attempt to render them. -- **`valid_skin_download_urls:`** List of strings, default includes only `'textures.minecraft.net'`, sets the allowed domains to download custom skulls and skins from that are requested by EaglercraftX clients, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`uuid_lookup_ratelimit_player:`** Integer, default value is `50`, limit of how many Mojang API UUID-to-profile lookups a single player is allowed to trigger per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`uuid_lookup_ratelimit_global:`** Integer, default value is `175`, limit of how many Mojang API UUID-to-profile lookups the entire server is allowed to perform per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_download_ratelimit_player:`** Integer, default value is `1000`, limit of how many texture downloads a single player is allowed to trigger per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_download_ratelimit_global:`** Integer, default value is `30000`, limit of how many texture downloads the entire server is allowed to perform per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_db_uri:`** String, default value is `'jdbc:sqlite:eaglercraft_skins_cache.db'`, can be used to change the location of the SQLite database used as a cache for skins and profiles, or to make the server use an entirely different SQL database like MySQL to store the data instead, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_keep_objects_days:`** Integer, default value is `45`, sets the max age for textures (skin files) stored in the skin cache database, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_keep_profiles_days:`** Integer, default value is `7`, sets the max age for player profiles stored in the skin cache database, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_max_objects:`** Integer, default value is `32768`, sets the max number of textures (skin files) stored in the skin cache database before the oldest textures begin to be deleted, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_max_profiles:`** Integer, default value is `32768`, sets the max number of player profiles stored in the skin cache database before the oldest profiles begin to be deleted, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_antagonists_ratelimit:`** Integer, default value is `15`, sets the lockout limit for failing skin lookup requests, intended to reduce the effectiveness of some of the more simplistic types denial of service attacks that skids may attempt to perform on the skin download system, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`sql_driver_class:`** String, default value is `'internal'`, which is currently evaluated to `'org.sqlite.JDBC'`, can be used to set the name of the JDBC driver class to use for connecting to the `skin_cache_db_uri` database -- **`sql_driver_path:`** String, default value is `'internal'`, can be used to set the name of the external JAR file where the JDBC driver class to use for connecting to the `skin_cache_db_uri` database can be found, the default `'internal'` value downloads the sqlite-jdbc JAR from maven and loads it automatically, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`eagler_players_vanilla_skin:`** String, default value is `''` but was originally `'lax1dude'`, can be used to set the skin to apply to EaglercraftX players when a player on Minecraft Java Edition sees them in game. The value is the username of a premium Minecraft account to use the skin from. You cannot use a local PNG file due to the profile signature requirements in vanilla Minecraft clients. -- **`enable_is_eagler_player_property:`** Boolean, default value is `true`, can be used to control if the `isEaglerPlayer` GameProfile property should be added to EaglercraftX players, this property is used to ensure that EaglercraftX players always only display their custom skins when viewed by another EaglercraftX players on the server instead of showing the skin attached to their Java Edition username, but this property also cause plugins like ViaVersion to crash. -- **`disable_voice_chat_on_servers:`** List of strings, default value is nothing (`[]`), contains a list of names of registered servers on your BungeeCord proxy that voice chat should show up as "disabled" on. Note that to disable voice globally you should modify `listeners.yml` instead. -- **`disable_fnaw_skins_everywhere:`** Boolean, default value is `false`, can be used to globally disable FNAW skins if your players bitch about them a lot and are too lazy to just disable the FNAW skins locally on their clients. -- **`disable_fnaw_skins_on_servers:`** List of strings, default value is nothing (`[]`), contains a list of names of registered servers on your BungeeCord proxy that the FNAW skins should be disabled on. Good for explicitly disabling them for PVP but allowing them everywhere else. -- **`enable_backend_rpc_api:`** Boolean, default value is `false`, if support for servers running the EaglerXBukkitAPI plugin should be enabled or not. -- **`use_modernized_channel_names:`** Boolean, default value is `false`, if "modernized" plugin channel names compatible with Minecraft 1.13+ should be used for EaglerXBukkitAPI plugin message packets - -### `listeners.yml` - -Defines one or more "listeners" (open ports) for EaglercraftX players to use to join the server. Each listener supports the following configuration options, a lot of which you will already be familiar with if you've ever set up a BungeeCord for a Java Edition server before: - -- **`address:`** String, default value is `0.0.0.0:8081`, sets the primary IPv4/port for EaglerXBungee to listen on. -- **`address_v6:`** String, default value is `'null'`, sets the primary IPv6/port for EaglerXBungee to listen on. -- **`max_players:`** Integer, default value is `60`, sets the maximum number of players that can join the server through this listener, set to `-1` to disable the limit. -- **`tab_list:`** String, default value is `GLOBAL_PING`, sets the option with the same name on the underlying BungeeCord listener, currently not used by EaglercraftX in any way. -- **`default_server:`** String, default value is `lobby`, sets the name of the default server for players to be sent to when they first connect to this listener. -- **`force_default_server:`** Boolean, default value is `false`, sets if players should always be connected to `default_server` when they connect to this listener. -- **`forward_ip:`** Boolean, default value is `false`, sets if connections to this listener will use an HTTP header to forward the player's real IP address from a reverse proxy (or CloudFlare) to the BungeeCord server. This is required for EaglerXBungee's rate limiting and a lot of plugins to work correctly if they are used behind a reverse HTTP proxy or CloudFlare. -- **`forward_ip_header:`** String, default value is `X-Real-IP`, sets the name of the request header that contains the player's real IP address if the `forward_ip` option is enabled. This option is commonly set to `X-Forwarded-For` or `CF-Connecting-IP` for a lot of server setups. -- **`redirect_legacy_clients_to:`** String, default value is `'null'`, sets the WebSocket address to redirect legacy Eaglercraft 1.5.2 clients to if they mistakenly try to join the server through this listener. -- **`server_icon:`** String, default value is `server-icon.png`, sets the name of the 64x64 PNG file to display as this listener's server icon, relative to the working directory of the BungeeCord proxy server. -- **`server_motd:`** List of up to 2 strings, default value is `'&6An EaglercraftX server'`, sets the contents of the listener's MOTD, which is the text displayed along with the `server_icon` when players add this server's listener address to their client's Multiplayer menu server list. -- **`allow_motd:`** Boolean, default value is `true`, if this listener should respond to MOTD queries or not. -- **`allow_query:`** Boolean, default value is `true`, if this listener should respond to all other types of queries or not. -- **`min_minecraft_protocol:`** Integer, default value is `47`, sets the minimum Minecraft [protocol version](https://wiki.vg/Protocol_version_numbers) that EaglercraftX-based clients are allowed to connect with (`47` = 1.8) -- **`max_minecraft_protocol:`** Integer, default value is `340`, sets the maximum Minecraft protocol version that EaglercraftX-based clients are allowed to connect with (`340` = 1.12.2) -- **`allow_protocol_v3:`** Boolean, default value is `true`, if this listener should allow clients using the v1/v2/v3 protocols to join (pre-u37 clients). -- **`allow_protocol_v4:`** Boolean, default value is `true`, if this listener should allow clients using the v4 protocol to join (post-u37 clients). -- **`protocol_v4_defrag_send_delay:`** Integer, default value is `10`, the number of milliseconds to wait before flushing all pending EaglercraftX plugin message packets, saves bandwidth by combining multiple messages into a single plugin message packet. Setting this to `0` has the same effect on clientbound packets as setting `eaglerNoDelay` to `true` does on a post-u37 client for all serverbound packets. -- **`use_haproxy_protocol:`** Boolean, default value is `false`, can be used to enable support for the HAProxy proxy protocol. Make sure to also add the `check`, `check-send-proxy`, and `send-proxy-v2` parameters to your `server` directives in the HAProxy config file. -- **`allow_cookie_revoke_query:`** Boolean, default value is `true`, If this listener should accept queries from post-u37 clients to revoke session tokens, you need to create your own BungeeCord plugin to go with EaglerXBungee that handles the `EaglercraftRevokeSessionQueryEvent` event it fires in order for this feature to work correctly. -- **`request_motd_cache:`** Section that defines caching hints for server lists that cache the MOTD via the `MOTD.cache` query. As far as we know, not even the official Eaglercraft Server List on eaglercraft.com currently pays attention to these hints or attempts to cache MOTDs, so they can be ignored for now. - - **`cache_ttl:`** Integer, default value is `7200`, sets how many seconds for the server list to store the MOTD in cache. - - **`online_server_list_animation:`** Boolean, default is `false`, if the MOTD should be cached in an "animated format" that is yet to be standardized. - - **`online_server_list_results:`** Boolean, default is `true`, if the MOTD should be cached when shown in search results. - - **`online_server_list_trending:`** Boolean, default is `true`, if the MOTD should be cached if the server makes it to the top of the homepage. - - **`online_server_list_portfolios:`** Boolean, default is `false`, if the MOTD should be cached when viewing more details about the specific server. -- **`http_server:`** Section that defines settings for the integrated HTTP server, used to make the listener behave as a normal HTTP server when a non-WebSocket request is recieved (like when the listener address is entered into a browser's address bar). These options can be used to replace the "404 WebSocket Upgrade Failure" message with a custom HTML file instead. - - **`enabled:`** Boolean, default value is `false`, if this is set to true then the default "404 WebSocket Upgrade Failure" page will be disabled and replaced with the integrated file-based HTTP server, perfect for hosting a copy of the EaglercraftX client. - - **`root:`** String, default value is `web`, sets the folder that contains the HTTP server's document root, this is relative to the `plugins/EaglercraftXBungee` folder where the config files are stored. - - **`page_404_not_found:`** String, default value is `'default'`, can be used to replace the HTTP server's 404 page. - - **`page_index_name:`** List of strings, default values are `'index.html'` and `'index.htm'`, can be used to specify the name of index.html. -- **`allow_voice:`** Boolean, default is `false`, sets if voice should show up as "disabled" for players using this listener. Voice is not recommended for public servers since little to no consideration was given to actually validating the contents of signaling packets sent between clients. -- **`ratelimit:`** Section containing rate limiting configurations for several different connection types. - - **`ip:`** Global ratelimit imposed on all connection types. - - **`login:`** Sets ratelimit on login (server join) attempts. - - **`motd:`** Sets ratelimit on MOTD query types. - - **`query:`** Sets ratelimit on all other query types. - - **`enable:`** If the rate limit (ip/login/motd/query) should be enabled. - - **`period:`** Sets the period in the number of seconds. - - **`limit:`** Sets the number of requests a single IP address can send in `period` seconds before being limited. - - **`limit_lockout:`** Sets the number of requests a single IP address can send in `period` seconds before being locked out. - - **`lockout_duration:`** Sets the total number of seconds a "lock out" should last on this limiter. - -### `authservice.yml` - -The authservice.yml file is used for configuring the built-in online mode authentication service included with the plugin or to integrate with a 3rd party authentication system provided by another plugin. - -- **`enable_authentication_system:`** Boolean, default is `true`, if the events for the authentication protocol should be enabled. -- **`use_onboard_eaglerx_system:`** Boolean, default is `true`, if the built-in online mode authentication system should be enabled. -- **`auth_db_uri:`** String, default value is `'jdbc:sqlite:eaglercraft_auths.db'`, can be used to change the location of the SQLite database used for the built-in online mode authentication system, or to make the server use an entirely different SQL database like MySQL to store the data instead. -- **`sql_driver_class:`** String, default value is `'internal'`, see the description of the `settings.yml` option with the same name. -- **`sql_driver_path:`** String, default value is `'internal'`, see the description of the `settings.yml` option with the same name. -- **`password_prompt_screen_text:`** String, default value is `'Enter your password to join:'`, text displayed on the EaglercraftX client's password screen when joining the server with the built-in online mode authentication system. -- **`wrong_password_screen_text:`** String, default value is `'Password Incorrect!'`, text displayed if the wrong password is entered on the EaglercraftX client's password screen when joining the server with the built-in online mode authentication system. -- **`not_registered_screen_text:`** String, default value is `'You are not registered on this server!'`, text displayed when joining the server with the built-in online mode authentication system when using an account that has not been registered. -- **`eagler_command_name:`** String, default value is `'eagler'`, the name of the command to use for registering and/or logging in when joining the server with the built-in online mode authentication system. -- **`use_register_command_text:`** String, default value is `'&aUse /eagler to set an Eaglercraft password on this account'`, localization for when players use the `/eagler` command on the server. -- **`use_change_command_text:`** String, default value is `'&bUse /eagler to change your Eaglercraft password'`, localization for when players use the `/eagler` command on the server. -- **`command_success_text:`** String, default value is `'&bYour eagler password was changed successfully.'`, localization for when players use the `/eagler` command on the server. -- **`last_eagler_login_message:`** String, default value is `'Your last Eaglercraft login was on $date from $ip'`, localization for when players join the server with the built-in online mode authentication system. -- **`too_many_registrations_message:`** String, default value is `'&cThe maximum number of registrations has been reached for your IP address'`, localization for when players use the `/eagler` command on the server. -- **`need_vanilla_to_register_message:`** String, default value is `'&cYou need to log in with a vanilla account to use this command'`, localization for when players use the `/eagler` command on the server. -- **`override_eagler_to_vanilla_skins:`** Boolean, default value is `false`, if players who join the server after registering with an online mode account should show the same skin as the online-mode account they registered with. -- **`max_registration_per_ip:`** Integer, default value is `-1`, if greater than 0 it specifies the max number of accounts that can be created per IP address on the server with the built-in online mode authentication system. - -### `ice_servers.yml` - -The ice_servers.yml file is used for configuring the set of STUN/TURN servers that clients on this server should use for voice chat. Beware the default "openrelayproject" TURN servers are no longer active as of 2024, most likely as a result of being the default ond only TURN servers shipped with every copy of Eaglercraft to ever use WebRTC in some way. - -- **`voice_servers_no_passwd:`** List of strings, defines a set of STUN/TURN server URIs to use that don't require a username and password. -- **`voice_servers_passwd:`** Section of sections, defines a set of STUN/TURN server URIs to use that do require a username and password, along with the username and password to use with each one. - -### `updates.yml` - -The updates.yml file is used for configuring the decentralized and totally legal update system used by EaglercraftX clients. - -- **`block_all_client_updates:`** Boolean, default value is `false`, can be used to completely disable the update system. -- **`discard_login_packet_certs:`** Boolean, default value is `false`, can be used to prevent the server from relaying random crowdsourced update certificates that were recieved from players who joined the server using signed clients. -- **`cert_packet_data_rate_limit:`** Integer, default value is `524288`, can be used to set the global rate limit for how many bytes per second of certificates the server should send to all players. -- **`enable_eagcert_folder:`** Boolean, default value is `true`, can be used to enable or disable the "eagcert" folder used for distributing specific certificates as locally provided .cert files -- **`download_latest_certs:`** Boolean, default value is `true`, can be used to automaticlly download the latest certificates to the "eagcert" folder -- **`download_certs_from:`** List of strings, defines the URLs to download the certificates from if `download_latest_certs` is enabled -- **`check_for_update_every:`** Integer, default value is `28800` seconds, defines how often to check the URL list for updated certificates - -### `pause_menu/pause_menu.yml` - -For EaglercraftX u37 and up, can be used for changing the appearance of the pause menu and a few other screens with custom icons and strings, also used for enabling the "Server Info" webview and configuring its contents. - -- **`enable_custom_pause_menu:`** Boolean, default value is `false`, if pause menu customization should be enabled on supported clients or not -- **`server_info_button:`** Section, defines properties of the "Server Info" button, which is always hidden unless pause menu customization is enabled - - **`enable_button:`** Boolean, default value is `true`, if the button should be shown or not - - **`button_text:`** String, default value is `'Server Info'`, the text to display on the button, useful if you want to use this feature for something other than a "Server Info" button - - **`button_mode_open_new_tab:`** Boolean, default value is `false`, can be used to make the "Server Info" button act as a hyperlink that opens a URL in a new tab instead of displaying content in an embedded webview iframe in the client. - - **`server_info_embed_url:`** String, default value is `''`, sets the URL for the "Server Info" button to use if it should open a URL in a new tab or the webview instead of directly downloading the markup to display from the EaglerXBungee server itself over the WebSocket. - - **`button_mode_embed_file:`** Boolean, default value is `true`, determines if the "Server Info" button should download the webview markup directly from the EaglerXBungee server over WebSocket instead of loading an external URL. Cannot be used with `button_mode_open_new_tab`! - - **`server_info_embed_file:`** String, default value is `'server_info.html'`, sets the name of the local file/template containing the markup to display in the "Server Info" webview if it is not in URL mode. - - **`server_info_embed_screen_title:`** String, default value is `'Server Info'`, sets the title string of the screen that displays the webview. - - **`server_info_embed_send_chunk_rate:`** Integer, default value is `1`, defines how many chunks of server info data to send per 250ms when downloading the server info markup to a client. - - **`server_info_embed_send_chunk_size:`** Integer, default value is `24576`, defines the size of each chunk of server info data when it is being downloaded to a client. - - **`enable_template_macros:`** Boolean, default value is `true`, if the server info markup should be processed for any eagler template macros (defined like `` {% arg1 `arg2` ... %} ``) - - **`server_info_embed_template_globals:`** Section, defines a list of additional global variables to use with the template processor - - **`allow_embed_template_eval_macro:`** Boolean, default value is `false`, if the template processor should allow the "eval" macro to be used in the server info markup file (not to be confused with the JavaScript function, although there is never a good reason to use JavaScript's eval function in your code either) - - **`enable_webview_javascript:`** Boolean, default value is `false`, if the server info webview should allow JavaScript to be executed or not. This will display an "allow JavaScript" screen to your players the first time they attempt to view it. - - **`enable_webview_message_api:`** Boolean, default value is `false`, if the server info webview has JavaScript enabled and should be permitted to open a message channel back to your EaglerXBungee server to exchange arbitrary message packets. This can be used, for example, to implement a dynamic menu on your server using JavaScript and HTML that players can access through the server info webview that integrates directly with your gamemodes. - - **`enable_webview_strict_csp:`** Boolean, default value is `true`, if the `csp` attribute on the webview iframe should be set or not for added security, beware this is not supported on all browsers and will be silently disabled when the client detects it as unsupported. -- **`discord_button:`** Section, can be used to turn the "Invite" (formerly "Open to LAN") button on the pause menu into a "Discord" button that players can click to join your discord server - - **`enable_button:`** Boolean, default value is `true`, sets if the discord button should be enabled or not - - **`button_text:`** String, default value is `'Discord'`, sets the text that should be displayed on the button - - **`button_url:`** String, default value is `'https://invite url here'`, defines the URL to open when the button is pressed -- **`custom_images:`** Section, can be used to add icons to certain buttons, change the backgrounds of some screens, and add watermarks of your server to the inventory and pause menu and such if you're into that. For the best GPU compatibility, use only textures with powers of 2 as dimensions (such as 32x32 pixels), the width and height do not need to match, they just both need to be a power of 2. There is also a limit on the maximum size, icons can be no larger than 255x255 pixels (Effective max power-of-2 is 128x128). Color values will be downsampled to 16bpp and use a magic value to represent transparent pixels when the pause menu customization packet is sent to a client. - - **`icon_title_L:`** String, default value is `''`, sets the icon to show on the left side of the pause menu screen's title - - **`icon_title_R:`** String, default value is `''`, sets the icon to show on the right side of the pause menu screen's title - - **`icon_backToGame_L:`** String, default value is `''`, sets the icon to show on the left side of the "Back to Game" button - - **`icon_backToGame_R:`** String, default value is `''`, sets the icon to show on the right side of the "Back to Game" button - - **`icon_achievements_L:`** String, default value is `''`, sets the icon to show on the left side of the "Achievements" button - - **`icon_achievements_R:`** String, default value is `''`, sets the icon to show on the right side of the "Achievements" button - - **`icon_statistics_L:`** String, default value is `''`, sets the icon to show on the left side of the "Statistics" button - - **`icon_statistics_R:`** String, default value is `''`, sets the icon to show on the right side of the "Statistics" button - - **`icon_serverInfo_L:`** String, default value is `''`, sets the icon to show on the left side of the server info button - - **`icon_serverInfo_R:`** String, default value is `''`, sets the icon to show on the right side of the server info button - - **`icon_options_L:`** String, default value is `''`, sets the icon to show on the left side of the "Options" button - - **`icon_options_R:`** String, default value is `''`, sets the icon to show on the right side of the "Options" button - - **`icon_discord_L:`** String, default value is `''`, sets the icon to show on the left side of the discord button - - **`icon_discord_R:`** String, default value is `''`, sets the icon to show on the right side of the discord button - - **`icon_disconnect_L:`** String, default value is `''`, sets the icon to show on the left side of the "Disconnect" button - - **`icon_disconnect_R:`** String, default value is `''`, sets the icon to show on the right side of the "Disconnect" button - - **`icon_background_pause:`** String, default value is `'test_image.png'`, sets the icon to show as a repeating pattern in the background of the pause menu and related screens. It is especially important for GPU compatibility for this one to be a power-of-2 sized texture. - - **`icon_background_all:`** String, default value is `'test_image.png'`, sets the icon to show as a repeating pattern in the background of all other screens in the game. It is especially important for GPU compatibility for this one to be a power-of-2 sized texture. - - **`icon_watermark_pause:`** String, default value is `''`, sets a watermark to show in the bottom-left corner of the pause menu - - **`icon_watermark_all:`** String, default value is `''`, sets a watermark to show in the bottom-left corner of all other screens in the game - -## Event Types - -The events added by EaglerXBungee are located in the [`net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event`](gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event) package and can be listened for the same way as you would for a regular BungeeCord event. When an EaglercraftX 1.8 player joins your server, all the regular BungeeCord login events are fired by EaglerXBungee to maintain compatibility with other existing BungeeCord plugins, however EaglerXBungee also adds several of its own event types to allow additional Eaglercraft specific features to be accessible through the main BungeeCord event bus as well. - -- **`EaglercraftWebSocketOpenEvent`** Event that is fired when a new WebSocket connection is first opened to the server (regardless if its a query or actual player login attempt) useful for quickly filtering out new connections based on a specific origin or user agent header. -- **`EaglercraftClientBrandEvent`** Event that is fired when an EaglercraftX player joins, it contains the Eaglercraft client's "brand" and "version" strings along with the origin and user agent headers that can be used to detect 90% of the currently existing skid clients thanks to lax1dude making the base client self-snitch these commonly modified strings. -- **`EaglercraftIsAuthRequiredEvent`** Event that is fired when an EaglercraftX player attempts to join the server while the authentication system is enabled and `use_onboard_eaglerx_system` is `false`, used for implementing custom authentication systems. -- **`EaglercraftHandleAuthPasswordEvent`** Event that is fired when an EaglercraftX player enters a password into the "Authentication Required" screen while the authentication system is enabled and `use_onboard_eaglerx_system` is `false`, used for implementing custom authentication systems. -- **`EaglercraftHandleAuthCookieEvent`** Event that is fired when an EaglercraftX player joins the server with cookies set and while authentication system is enabled and `use_onboard_eaglerx_system` is `false`, you must set cookie auth as allowed while handling "EaglercraftIsAuthRequiredEvent" first for this event to actually be fired, used for implementing custom authentication systems that use cookies to store a session token for auto login. -- **`EaglercraftRevokeSessionQueryEvent`** Event that is fired when a player uses the "Revoke Session Token" feature in a u37 client to invalidate a cookie that was set on their client with the "revoke query supported" bit. Make sure to enable session revoke queries in listeners.yml! -- **`EaglercraftRegisterSkinEvent`** Event that is fired when an EaglercraftX player's skin is recieved, can be used to analyze or modify or replace the skin with a different texture or preset ID if needed. Note that players using pre-u37 clients may not see the modified/replaced skin. -- **`EaglercraftRegisterCapeEvent`** Event that is fired when an EaglercraftX player's cape is recieved, can be used to analyze or modify or replace the cape with a different texture or preset ID if needed. Use preset ID 0 to disable their cape entirely. Note that players using pre-u37 clients may not see the modified/replaced cape. -- **`EaglercraftMOTDEvent`** Event that is fired when a MOTD query request is recieved, used for implement a custom server MOTD handler, or implementing an animated MOTD like the EaglerMOTD plugin. -- **`EaglercraftVoiceStatusChangeEvent`** Event that is fired when `allow_voice` is enabled and a player transitions between voice states (SERVER_DISABLE, DISABLED, ENABLED) cannot be cancelled so it is mostly just useful for logging or displaying some "Rules" in chat. -- **`EaglercraftWebViewChannelEvent`** Event that is fired when the server info webview is open and JavaScript is enabled and the webview opens/closes a new message channel to EaglerXBungee. -- **`EaglercraftWebViewMessageEvent`** Event that is fired when the server info webview is open and JavaScript is enabled and the webview has already opened a channel to EaglerXBungee and a new message is recieved on that open channel. - -## Registering Queries - -If you would like to add your own custom `Accept:` query handlers to the proxy (along with MOTD, version, and session revoke) you can register them at startup using the register functions provided by the [`EaglerQueryHandler`](gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQueryHandler.java) class. - -## EaglerXBungeeAPIHelper - -To help make plugin development easier, a class called [`EaglerXBungeeAPIHelper`](gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EaglerXBungeeAPIHelper.java) is included that defines dozens of helper functions for easily and safely interacting with EaglercraftX clients. This is to enable developers to program plugins for EaglerXBungee servers with minimal knowledge of the actual underlying protocol used by the client for skins and capes and voice and other exclusive features. Its recommended to convert all your existing code to use the `EaglerXBungeeAPIHelper` instead of whatever packet hacks you were doing before it was added when you migrate your network to EaglerXBungee 1.3.0+. All your existing packet hacks will be broken anyway unless you configure the server to force all u37+ clients to use protocol V3 instead. diff --git a/README_EAGLERXVELOCITY.md b/README_EAGLERXVELOCITY.md deleted file mode 100644 index cb72ba53..00000000 --- a/README_EAGLERXVELOCITY.md +++ /dev/null @@ -1,206 +0,0 @@ -# EaglercraftXVelocity - -### [`gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar`](gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar) - -### "EaglerXVelocity" is a plugin that allows the EaglercraftX 1.8 client to join Velocity servers, with an optional authentication system if online-mode is enabled. This is not a setup guide, this document is intended to be used as reference for EaglerXVelocity's configuration files and provide some surface-level information meant for plugin developers. - -**Warning:** Both EaglerXBungee and EaglerXVelocity perform a lot of reflection that will inevitably break after a while when BungeeCord or Velocity is updated upstream. Both plugins will display the precise build number of BungeeCord and Velocity that has been tested by the developers and known to be compatible with EaglerXBungee and EaglerXVelocity when the proxy first starts up. If you are experiencing issues, try checking the BungeeCord or Velocity website for old versions and find the closest version number to whatever the current compatible version number is that is printed by EaglerXBungee/EaglerXVelocity, it will probably fix whatever missing functions the error messages are complaining about. - -## Compiling EaglerXVelocity - -Minimum JDK version is 17, as of 1.1.0 we are finally using Gradle to compile EaglerXVelocity instead of compiling it all manually, however you still need to manually download the latest version of Velocity and name it "Velocity.jar" and place it in the `deps` folder first before you continue. We just don't care enough to actually use Gradle correctly to download all the dependencies automatically when they are all subject to change at any time as Velocity recieves updates upstream. Use the "jar" task to automatically compile the EaglerXVelocity JAR file. - -## Configuration Files - -### NOTE: Currently, the plugin does NOT automatically update config files, if you can't find an option in one of the configuration files documented here, you most likely need to add it to the file yourself! - -**The default contents of the config files for EaglerXVelocity are stored in [`gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config`](gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config)** - -### `settings.yml` - -The settings.yml file is primarily used for configuring the built-in skin and cape service and certain connection options. - -- **`server_name:`** String, default value is `'EaglercraftXVelocity Server'`, sets the name of this EaglercraftX server that is sent with query responses and used for the default "404 websocket upgrade failure" page. -- **`server_uuid:`** String, default value is randomized, sets the UUID of this EaglercraftX server to send with query responses, has no official uses outside of server lists. -- **`websocket_connection_timeout:`** Number, default value is `15000` milliseconds, sets how long a WebSocket connection can last without a ping before being disconnected. -- **`websocket_handshake_timeout:`** Number, default value is `5000` milliseconds, sets how long a connection can sit in the handshake phase before being disconnected. -- **`builtin_http_server_timeout:`** Number, default value is `10000` milliseconds, sets how long an HTTP request to the built-in HTTP server can remain open before being forcefully disconnected. -- **`http_websocket_compression_level:`** Number, default value is `6`, sets the ZLIB compression level (0-9) to use for compressing websocket frames, set to 0 to disable if HTTP compression is already handled through a reverse proxy. You almost definitely need some level of compression for the game to be playable on WiFi networks. -- **`download_vanilla_skins_to_clients:`** Boolean, default value is `true`, sets if the server should download the textures of custom skulls and skins of vanilla online-mode players from Mojang's servers to cache locally and send to all EaglercraftX clients on the server that attempt to render them. -- **`valid_skin_download_urls:`** List of strings, default includes only `'textures.minecraft.net'`, sets the allowed domains to download custom skulls and skins from that are requested by EaglercraftX clients, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`uuid_lookup_ratelimit_player:`** Integer, default value is `50`, limit of how many Mojang API UUID-to-profile lookups a single player is allowed to trigger per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`uuid_lookup_ratelimit_global:`** Integer, default value is `175`, limit of how many Mojang API UUID-to-profile lookups the entire server is allowed to perform per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_download_ratelimit_player:`** Integer, default value is `1000`, limit of how many texture downloads a single player is allowed to trigger per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_download_ratelimit_global:`** Integer, default value is `30000`, limit of how many texture downloads the entire server is allowed to perform per minute, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_db_uri:`** String, default value is `'jdbc:sqlite:eaglercraft_skins_cache.db'`, can be used to change the location of the SQLite database used as a cache for skins and profiles, or to make the server use an entirely different SQL database like MySQL to store the data instead, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_keep_objects_days:`** Integer, default value is `45`, sets the max age for textures (skin files) stored in the skin cache database, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_keep_profiles_days:`** Integer, default value is `7`, sets the max age for player profiles stored in the skin cache database, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_max_objects:`** Integer, default value is `32768`, sets the max number of textures (skin files) stored in the skin cache database before the oldest textures begin to be deleted, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_max_profiles:`** Integer, default value is `32768`, sets the max number of player profiles stored in the skin cache database before the oldest profiles begin to be deleted, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`skin_cache_antagonists_ratelimit:`** Integer, default value is `15`, sets the lockout limit for failing skin lookup requests, intended to reduce the effectiveness of some of the more simplistic types denial of service attacks that skids may attempt to perform on the skin download system, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`sql_driver_class:`** String, default value is `'internal'`, which is currently evaluated to `'org.sqlite.JDBC'`, can be used to set the name of the JDBC driver class to use for connecting to the `skin_cache_db_uri` database -- **`sql_driver_path:`** String, default value is `'internal'`, can be used to set the name of the external JAR file where the JDBC driver class to use for connecting to the `skin_cache_db_uri` database can be found, the default `'internal'` value downloads the sqlite-jdbc JAR from maven and loads it automatically, only relevant if `download_vanilla_skins_to_clients` is enabled. -- **`eagler_players_vanilla_skin:`** String, default value is `''` but was originally `'lax1dude'`, can be used to set the skin to apply to EaglercraftX players when a player on Minecraft Java Edition sees them in game. The value is the username of a premium Minecraft account to use the skin from. You cannot use a local PNG file due to the profile signature requirements in vanilla Minecraft clients. -- **`enable_is_eagler_player_property:`** Boolean, default value is `true`, can be used to control if the `isEaglerPlayer` GameProfile property should be added to EaglercraftX players, this property is used to ensure that EaglercraftX players always only display their custom skins when viewed by another EaglercraftX players on the server instead of showing the skin attached to their Java Edition username, but this property also cause plugins like ViaVersion to crash. -- **`disable_voice_chat_on_servers:`** List of strings, default value is nothing (`[]`), contains a list of names of registered servers on your Velocity proxy that voice chat should show up as "disabled" on. Note that to disable voice globally you should modify `listeners.yml` instead. -- **`disable_fnaw_skins_everywhere:`** Boolean, default value is `false`, can be used to globally disable FNAW skins if your players bitch about them a lot and are too lazy to just disable the FNAW skins locally on their clients. -- **`disable_fnaw_skins_on_servers:`** List of strings, default value is nothing (`[]`), contains a list of names of registered servers on your Velocity proxy that the FNAW skins should be disabled on. Good for explicitly disabling them for PVP but allowing them everywhere else. -- **`enable_backend_rpc_api:`** Boolean, default value is `false`, if support for servers running the EaglerXBukkitAPI plugin should be enabled or not. -- **`use_modernized_channel_names:`** Boolean, default value is `false`, if "modernized" plugin channel names compatible with Minecraft 1.13+ should be used for EaglerXBukkitAPI plugin message packets - -### `listeners.yml` - -Defines one or more "listeners" (open ports) for EaglercraftX players to use to join the server. Each listener supports the following configuration options, a lot of which you will already be familiar with if you've ever set up a Velocity for a Java Edition server before: - -- **`address:`** String, default value is `0.0.0.0:8081`, sets the primary IPv4/port for EaglerXVelocity to listen on. -- **`address_v6:`** String, default value is `'null'`, sets the primary IPv6/port for EaglerXVelocity to listen on. -- **`max_players:`** Integer, default value is `60`, sets the maximum number of players that can join the server through this listener, set to `-1` to disable the limit. -- **`forward_ip:`** Boolean, default value is `false`, sets if connections to this listener will use an HTTP header to forward the player's real IP address from a reverse proxy (or CloudFlare) to the Velocity server. This is required for EaglerXVelocity's rate limiting and a lot of plugins to work correctly if they are used behind a reverse HTTP proxy or CloudFlare. -- **`forward_ip_header:`** String, default value is `X-Real-IP`, sets the name of the request header that contains the player's real IP address if the `forward_ip` option is enabled. This option is commonly set to `X-Forwarded-For` or `CF-Connecting-IP` for a lot of server setups. -- **`redirect_legacy_clients_to:`** String, default value is `'null'`, sets the WebSocket address to redirect legacy Eaglercraft 1.5.2 clients to if they mistakenly try to join the server through this listener. -- **`server_icon:`** String, default value is `server-icon.png`, sets the name of the 64x64 PNG file to display as this listener's server icon, relative to the working directory of the Velocity proxy server. -- **`server_motd:`** List of up to 2 strings, default value is `'&6An EaglercraftX server'`, sets the contents of the listener's MOTD, which is the text displayed along with the `server_icon` when players add this server's listener address to their client's Multiplayer menu server list. -- **`allow_motd:`** Boolean, default value is `true`, if this listener should respond to MOTD queries or not. -- **`allow_query:`** Boolean, default value is `true`, if this listener should respond to all other types of queries or not. -- **`min_minecraft_protocol:`** Integer, default value is `47`, sets the minimum Minecraft [protocol version](https://wiki.vg/Protocol_version_numbers) that EaglercraftX-based clients are allowed to connect with (`47` = 1.8) -- **`max_minecraft_protocol:`** Integer, default value is `340`, sets the maximum Minecraft protocol version that EaglercraftX-based clients are allowed to connect with (`340` = 1.12.2) -- **`allow_protocol_v3:`** Boolean, default value is `true`, if this listener should allow clients using the v1/v2/v3 protocols to join (pre-u37 clients). -- **`allow_protocol_v4:`** Boolean, default value is `true`, if this listener should allow clients using the v4 protocol to join (post-u37 clients). -- **`protocol_v4_defrag_send_delay:`** Integer, default value is `10`, the number of milliseconds to wait before flushing all pending EaglercraftX plugin message packets, saves bandwidth by combining multiple messages into a single plugin message packet. Setting this to `0` has the same effect on clientbound packets as setting `eaglerNoDelay` to `true` does on a post-u37 client for all serverbound packets. -- **`use_haproxy_protocol:`** Boolean, default value is `false`, can be used to enable support for the HAProxy proxy protocol. Make sure to also add the `check`, `check-send-proxy`, and `send-proxy-v2` parameters to your `server` directives in the HAProxy config file. -- **`allow_cookie_revoke_query:`** Boolean, default value is `true`, If this listener should accept queries from post-u37 clients to revoke session tokens, you need to create your own Velocity plugin to go with EaglerXVelocity that handles the `EaglercraftRevokeSessionQueryEvent` event it fires in order for this feature to work correctly. -- **`request_motd_cache:`** Section that defines caching hints for server lists that cache the MOTD via the `MOTD.cache` query. As far as we know, not even the official Eaglercraft Server List on eaglercraft.com currently pays attention to these hints or attempts to cache MOTDs, so they can be ignored for now. - - **`cache_ttl:`** Integer, default value is `7200`, sets how many seconds for the server list to store the MOTD in cache. - - **`online_server_list_animation:`** Boolean, default is `false`, if the MOTD should be cached in an "animated format" that is yet to be standardized. - - **`online_server_list_results:`** Boolean, default is `true`, if the MOTD should be cached when shown in search results. - - **`online_server_list_trending:`** Boolean, default is `true`, if the MOTD should be cached if the server makes it to the top of the homepage. - - **`online_server_list_portfolios:`** Boolean, default is `false`, if the MOTD should be cached when viewing more details about the specific server. -- **`http_server:`** Section that defines settings for the integrated HTTP server, used to make the listener behave as a normal HTTP server when a non-WebSocket request is recieved (like when the listener address is entered into a browser's address bar). These options can be used to replace the "404 WebSocket Upgrade Failure" message with a custom HTML file instead. - - **`enabled:`** Boolean, default value is `false`, if this is set to true then the default "404 WebSocket Upgrade Failure" page will be disabled and replaced with the integrated file-based HTTP server, perfect for hosting a copy of the EaglercraftX client. - - **`root:`** String, default value is `web`, sets the folder that contains the HTTP server's document root, this is relative to the `plugins/EaglercraftXVelocity` folder where the config files are stored. - - **`page_404_not_found:`** String, default value is `'default'`, can be used to replace the HTTP server's 404 page. - - **`page_index_name:`** List of strings, default values are `'index.html'` and `'index.htm'`, can be used to specify the name of index.html. -- **`allow_voice:`** Boolean, default is `false`, sets if voice should show up as "disabled" for players using this listener. Voice is not recommended for public servers since little to no consideration was given to actually validating the contents of signaling packets sent between clients. -- **`ratelimit:`** Section containing rate limiting configurations for several different connection types. - - **`ip:`** Global ratelimit imposed on all connection types. - - **`login:`** Sets ratelimit on login (server join) attempts. - - **`motd:`** Sets ratelimit on MOTD query types. - - **`query:`** Sets ratelimit on all other query types. - - **`enable:`** If the rate limit (ip/login/motd/query) should be enabled. - - **`period:`** Sets the period in the number of seconds. - - **`limit:`** Sets the number of requests a single IP address can send in `period` seconds before being limited. - - **`limit_lockout:`** Sets the number of requests a single IP address can send in `period` seconds before being locked out. - - **`lockout_duration:`** Sets the total number of seconds a "lock out" should last on this limiter. - -### `authservice.yml` - -The authservice.yml file is used for configuring the built-in online mode authentication service included with the plugin or to integrate with a 3rd party authentication system provided by another plugin. - -- **`enable_authentication_system:`** Boolean, default is `true`, if the events for the authentication protocol should be enabled. -- **`use_onboard_eaglerx_system:`** Boolean, default is `true`, if the built-in online mode authentication system should be enabled. -- **`auth_db_uri:`** String, default value is `'jdbc:sqlite:eaglercraft_auths.db'`, can be used to change the location of the SQLite database used for the built-in online mode authentication system, or to make the server use an entirely different SQL database like MySQL to store the data instead. -- **`sql_driver_class:`** String, default value is `'internal'`, see the description of the `settings.yml` option with the same name. -- **`sql_driver_path:`** String, default value is `'internal'`, see the description of the `settings.yml` option with the same name. -- **`password_prompt_screen_text:`** String, default value is `'Enter your password to join:'`, text displayed on the EaglercraftX client's password screen when joining the server with the built-in online mode authentication system. -- **`wrong_password_screen_text:`** String, default value is `'Password Incorrect!'`, text displayed if the wrong password is entered on the EaglercraftX client's password screen when joining the server with the built-in online mode authentication system. -- **`not_registered_screen_text:`** String, default value is `'You are not registered on this server!'`, text displayed when joining the server with the built-in online mode authentication system when using an account that has not been registered. -- **`eagler_command_name:`** String, default value is `'eagler'`, the name of the command to use for registering and/or logging in when joining the server with the built-in online mode authentication system. -- **`use_register_command_text:`** String, default value is `'&aUse /eagler to set an Eaglercraft password on this account'`, localization for when players use the `/eagler` command on the server. -- **`use_change_command_text:`** String, default value is `'&bUse /eagler to change your Eaglercraft password'`, localization for when players use the `/eagler` command on the server. -- **`command_success_text:`** String, default value is `'&bYour eagler password was changed successfully.'`, localization for when players use the `/eagler` command on the server. -- **`last_eagler_login_message:`** String, default value is `'Your last Eaglercraft login was on $date from $ip'`, localization for when players join the server with the built-in online mode authentication system. -- **`too_many_registrations_message:`** String, default value is `'&cThe maximum number of registrations has been reached for your IP address'`, localization for when players use the `/eagler` command on the server. -- **`need_vanilla_to_register_message:`** String, default value is `'&cYou need to log in with a vanilla account to use this command'`, localization for when players use the `/eagler` command on the server. -- **`override_eagler_to_vanilla_skins:`** Boolean, default value is `false`, if players who join the server after registering with an online mode account should show the same skin as the online-mode account they registered with. -- **`max_registration_per_ip:`** Integer, default value is `-1`, if greater than 0 it specifies the max number of accounts that can be created per IP address on the server with the built-in online mode authentication system. - -### `ice_servers.yml` - -The ice_servers.yml file is used for configuring the set of STUN/TURN servers that clients on this server should use for voice chat. Beware the default "openrelayproject" TURN servers are no longer active as of 2024, most likely as a result of being the default ond only TURN servers shipped with every copy of Eaglercraft to ever use WebRTC in some way. - -- **`voice_servers_no_passwd:`** List of strings, defines a set of STUN/TURN server URIs to use that don't require a username and password. -- **`voice_servers_passwd:`** Section of sections, defines a set of STUN/TURN server URIs to use that do require a username and password, along with the username and password to use with each one. - -### `updates.yml` - -The updates.yml file is used for configuring the decentralized and totally legal update system used by EaglercraftX clients. - -- **`block_all_client_updates:`** Boolean, default value is `false`, can be used to completely disable the update system. -- **`discard_login_packet_certs:`** Boolean, default value is `false`, can be used to prevent the server from relaying random crowdsourced update certificates that were recieved from players who joined the server using signed clients. -- **`cert_packet_data_rate_limit:`** Integer, default value is `524288`, can be used to set the global rate limit for how many bytes per second of certificates the server should send to all players. -- **`enable_eagcert_folder:`** Boolean, default value is `true`, can be used to enable or disable the "eagcert" folder used for distributing specific certificates as locally provided .cert files -- **`download_latest_certs:`** Boolean, default value is `true`, can be used to automaticlly download the latest certificates to the "eagcert" folder -- **`download_certs_from:`** List of strings, defines the URLs to download the certificates from if `download_latest_certs` is enabled -- **`check_for_update_every:`** Integer, default value is `28800` seconds, defines how often to check the URL list for updated certificates - -### `pause_menu/pause_menu.yml` - -For EaglercraftX u37 and up, can be used for changing the appearance of the pause menu and a few other screens with custom icons and strings, also used for enabling the "Server Info" webview and configuring its contents. - -- **`enable_custom_pause_menu:`** Boolean, default value is `false`, if pause menu customization should be enabled on supported clients or not -- **`server_info_button:`** Section, defines properties of the "Server Info" button, which is always hidden unless pause menu customization is enabled - - **`enable_button:`** Boolean, default value is `true`, if the button should be shown or not - - **`button_text:`** String, default value is `'Server Info'`, the text to display on the button, useful if you want to use this feature for something other than a "Server Info" button - - **`button_mode_open_new_tab:`** Boolean, default value is `false`, can be used to make the "Server Info" button act as a hyperlink that opens a URL in a new tab instead of displaying content in an embedded webview iframe in the client. - - **`server_info_embed_url:`** String, default value is `''`, sets the URL for the "Server Info" button to use if it should open a URL in a new tab or the webview instead of directly downloading the markup to display from the EaglerXVelocity server itself over the WebSocket. - - **`button_mode_embed_file:`** Boolean, default value is `true`, determines if the "Server Info" button should download the webview markup directly from the EaglerXVelocity server over WebSocket instead of loading an external URL. Cannot be used with `button_mode_open_new_tab`! - - **`server_info_embed_file:`** String, default value is `'server_info.html'`, sets the name of the local file/template containing the markup to display in the "Server Info" webview if it is not in URL mode. - - **`server_info_embed_screen_title:`** String, default value is `'Server Info'`, sets the title string of the screen that displays the webview. - - **`server_info_embed_send_chunk_rate:`** Integer, default value is `1`, defines how many chunks of server info data to send per 250ms when downloading the server info markup to a client. - - **`server_info_embed_send_chunk_size:`** Integer, default value is `24576`, defines the size of each chunk of server info data when it is being downloaded to a client. - - **`enable_template_macros:`** Boolean, default value is `true`, if the server info markup should be processed for any eagler template macros (defined like `` {% arg1 `arg2` ... %} ``) - - **`server_info_embed_template_globals:`** Section, defines a list of additional global variables to use with the template processor - - **`allow_embed_template_eval_macro:`** Boolean, default value is `false`, if the template processor should allow the "eval" macro to be used in the server info markup file (not to be confused with the JavaScript function, although there is never a good reason to use JavaScript's eval function in your code either) - - **`enable_webview_javascript:`** Boolean, default value is `false`, if the server info webview should allow JavaScript to be executed or not. This will display an "allow JavaScript" screen to your players the first time they attempt to view it. - - **`enable_webview_message_api:`** Boolean, default value is `false`, if the server info webview has JavaScript enabled and should be permitted to open a message channel back to your EaglerXVelocity server to exchange arbitrary message packets. This can be used, for example, to implement a dynamic menu on your server using JavaScript and HTML that players can access through the server info webview that integrates directly with your gamemodes. - - **`enable_webview_strict_csp:`** Boolean, default value is `true`, if the `csp` attribute on the webview iframe should be set or not for added security, beware this is not supported on all browsers and will be silently disabled when the client detects it as unsupported. -- **`discord_button:`** Section, can be used to turn the "Invite" (formerly "Open to LAN") button on the pause menu into a "Discord" button that players can click to join your discord server - - **`enable_button:`** Boolean, default value is `true`, sets if the discord button should be enabled or not - - **`button_text:`** String, default value is `'Discord'`, sets the text that should be displayed on the button - - **`button_url:`** String, default value is `'https://invite url here'`, defines the URL to open when the button is pressed -- **`custom_images:`** Section, can be used to add icons to certain buttons, change the backgrounds of some screens, and add watermarks of your server to the inventory and pause menu and such if you're into that. For the best GPU compatibility, use only textures with powers of 2 as dimensions (such as 32x32 pixels), the width and height do not need to match, they just both need to be a power of 2. There is also a limit on the maximum size, icons can be no larger than 255x255 pixels (Effective max power-of-2 is 128x128). Color values will be downsampled to 16bpp and use a magic value to represent transparent pixels when the pause menu customization packet is sent to a client. - - **`icon_title_L:`** String, default value is `''`, sets the icon to show on the left side of the pause menu screen's title - - **`icon_title_R:`** String, default value is `''`, sets the icon to show on the right side of the pause menu screen's title - - **`icon_backToGame_L:`** String, default value is `''`, sets the icon to show on the left side of the "Back to Game" button - - **`icon_backToGame_R:`** String, default value is `''`, sets the icon to show on the right side of the "Back to Game" button - - **`icon_achievements_L:`** String, default value is `''`, sets the icon to show on the left side of the "Achievements" button - - **`icon_achievements_R:`** String, default value is `''`, sets the icon to show on the right side of the "Achievements" button - - **`icon_statistics_L:`** String, default value is `''`, sets the icon to show on the left side of the "Statistics" button - - **`icon_statistics_R:`** String, default value is `''`, sets the icon to show on the right side of the "Statistics" button - - **`icon_serverInfo_L:`** String, default value is `''`, sets the icon to show on the left side of the server info button - - **`icon_serverInfo_R:`** String, default value is `''`, sets the icon to show on the right side of the server info button - - **`icon_options_L:`** String, default value is `''`, sets the icon to show on the left side of the "Options" button - - **`icon_options_R:`** String, default value is `''`, sets the icon to show on the right side of the "Options" button - - **`icon_discord_L:`** String, default value is `''`, sets the icon to show on the left side of the discord button - - **`icon_discord_R:`** String, default value is `''`, sets the icon to show on the right side of the discord button - - **`icon_disconnect_L:`** String, default value is `''`, sets the icon to show on the left side of the "Disconnect" button - - **`icon_disconnect_R:`** String, default value is `''`, sets the icon to show on the right side of the "Disconnect" button - - **`icon_background_pause:`** String, default value is `'test_image.png'`, sets the icon to show as a repeating pattern in the background of the pause menu and related screens. It is especially important for GPU compatibility for this one to be a power-of-2 sized texture. - - **`icon_background_all:`** String, default value is `'test_image.png'`, sets the icon to show as a repeating pattern in the background of all other screens in the game. It is especially important for GPU compatibility for this one to be a power-of-2 sized texture. - - **`icon_watermark_pause:`** String, default value is `''`, sets a watermark to show in the bottom-left corner of the pause menu - - **`icon_watermark_all:`** String, default value is `''`, sets a watermark to show in the bottom-left corner of all other screens in the game - -## Event Types - -The events added by EaglerXVelocity are located in the [`net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event`](gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event) package and can be listened for the same way as you would for a regular Velocity event. When an EaglercraftX 1.8 player joins your server, all the regular Velocity login events are fired by EaglerXVelocity to maintain compatibility with other existing Velocity plugins, however EaglerXVelocity also adds several of its own event types to allow additional Eaglercraft specific features to be accessible through the main Velocity event bus as well. - -- **`EaglercraftWebSocketOpenEvent`** Event that is fired when a new WebSocket connection is first opened to the server (regardless if its a query or actual player login attempt) useful for quickly filtering out new connections based on a specific origin or user agent header. -- **`EaglercraftClientBrandEvent`** Event that is fired when an EaglercraftX player joins, it contains the Eaglercraft client's "brand" and "version" strings along with the origin and user agent headers that can be used to detect 90% of the currently existing skid clients thanks to lax1dude making the base client self-snitch these commonly modified strings. -- **`EaglercraftIsAuthRequiredEvent`** Event that is fired when an EaglercraftX player attempts to join the server while the authentication system is enabled and `use_onboard_eaglerx_system` is `false`, used for implementing custom authentication systems. -- **`EaglercraftHandleAuthPasswordEvent`** Event that is fired when an EaglercraftX player enters a password into the "Authentication Required" screen while the authentication system is enabled and `use_onboard_eaglerx_system` is `false`, used for implementing custom authentication systems. -- **`EaglercraftHandleAuthCookieEvent`** Event that is fired when an EaglercraftX player joins the server with cookies set and while authentication system is enabled and `use_onboard_eaglerx_system` is `false`, you must set cookie auth as allowed while handling "EaglercraftIsAuthRequiredEvent" first for this event to actually be fired, used for implementing custom authentication systems that use cookies to store a session token for auto login. -- **`EaglercraftRevokeSessionQueryEvent`** Event that is fired when a player uses the "Revoke Session Token" feature in a u37 client to invalidate a cookie that was set on their client with the "revoke query supported" bit. Make sure to enable session revoke queries in listeners.yml! -- **`EaglercraftRegisterSkinEvent`** Event that is fired when an EaglercraftX player's skin is recieved, can be used to analyze or modify or replace the skin with a different texture or preset ID if needed. Note that players using pre-u37 clients may not see the modified/replaced skin. -- **`EaglercraftRegisterCapeEvent`** Event that is fired when an EaglercraftX player's cape is recieved, can be used to analyze or modify or replace the cape with a different texture or preset ID if needed. Use preset ID 0 to disable their cape entirely. Note that players using pre-u37 clients may not see the modified/replaced cape. -- **`EaglercraftMOTDEvent`** Event that is fired when a MOTD query request is recieved, used for implement a custom server MOTD handler, or implementing an animated MOTD like the EaglerMOTD plugin. -- **`EaglercraftVoiceStatusChangeEvent`** Event that is fired when `allow_voice` is enabled and a player transitions between voice states (SERVER_DISABLE, DISABLED, ENABLED) cannot be cancelled so it is mostly just useful for logging or displaying some "Rules" in chat. -- **`EaglercraftWebViewChannelEvent`** Event that is fired when the server info webview is open and JavaScript is enabled and the webview opens/closes a new message channel to EaglerXVelocity. -- **`EaglercraftWebViewMessageEvent`** Event that is fired when the server info webview is open and JavaScript is enabled and the webview has already opened a channel to EaglerXVelocity and a new message is recieved on that open channel. - -## Registering Queries - -If you would like to add your own custom `Accept:` query handlers to the proxy (along with MOTD, version, and session revoke) you can register them at startup using the register functions provided by the [`EaglerQueryHandler`](gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQueryHandler.java) class. - -## EaglerXVelocityAPIHelper - -To help make plugin development easier, a class called [`EaglerXVelocityAPIHelper`](gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EaglerXVelocityAPIHelper.java) is included that defines dozens of helper functions for easily and safely interacting with EaglercraftX clients. This is to enable developers to program plugins for EaglerXVelocity servers with minimal knowledge of the actual underlying protocol used by the client for skins and capes and voice and other exclusive features. Its recommended to convert all your existing code to use the `EaglerXVelocityAPIHelper` instead of whatever packet hacks you were doing before it was added when you migrate your network to EaglerXVelocity 1.1.0+. All your existing packet hacks will be broken anyway unless you configure the server to force all u37+ clients to use protocol V3 instead. diff --git a/gateway/EaglercraftXBukkitAPI/.gitignore b/gateway/EaglercraftXBukkitAPI/.gitignore deleted file mode 100644 index e30d0dbd..00000000 --- a/gateway/EaglercraftXBukkitAPI/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -lib/* -.idea/* -*.iml -out/* -/.gradle/ -/.settings/ -.classpath -.project -/build/ -/bin/ diff --git a/gateway/EaglercraftXBukkitAPI/EaglercraftXBukkitAPI-Latest.jar b/gateway/EaglercraftXBukkitAPI/EaglercraftXBukkitAPI-Latest.jar deleted file mode 100644 index 640488b1..00000000 Binary files a/gateway/EaglercraftXBukkitAPI/EaglercraftXBukkitAPI-Latest.jar and /dev/null differ diff --git a/gateway/EaglercraftXBukkitAPI/build.gradle b/gateway/EaglercraftXBukkitAPI/build.gradle deleted file mode 100644 index bf7f42cf..00000000 --- a/gateway/EaglercraftXBukkitAPI/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -plugins { - id 'java' - id 'eclipse' -} - -group = 'net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper' -version = '' - -repositories { - mavenCentral() - maven { - url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' - } - maven { - url = "https://oss.sonatype.org/content/repositories/snapshots/" - } -} - -sourceSets { - main { - java { - srcDirs 'src/main/java' - srcDirs '../backend-rpc-protocol/src/backend-rpc-protocol/java' - srcDirs '../backend-rpc-protocol/src/notif-builder-bungee/java' - } - } -} - -dependencies { - compileOnly 'org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT' -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -jar { - compileJava.options.encoding = 'UTF-8' - javadoc.options.encoding = 'UTF-8' -} diff --git a/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.jar b/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e5832..00000000 Binary files a/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.properties b/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index eb7f6f99..00000000 --- a/gateway/EaglercraftXBukkitAPI/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Jun 20 10:14:47 CDT 2024 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gateway/EaglercraftXBukkitAPI/gradlew b/gateway/EaglercraftXBukkitAPI/gradlew deleted file mode 100644 index 1b6c7873..00000000 --- a/gateway/EaglercraftXBukkitAPI/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gateway/EaglercraftXBukkitAPI/gradlew.bat b/gateway/EaglercraftXBukkitAPI/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/gateway/EaglercraftXBukkitAPI/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/gateway/EaglercraftXBukkitAPI/settings.gradle b/gateway/EaglercraftXBukkitAPI/settings.gradle deleted file mode 100644 index 6c86aaf1..00000000 --- a/gateway/EaglercraftXBukkitAPI/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'EaglercraftXBukkitAPI' - diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIListener.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIListener.java deleted file mode 100644 index 7edc6513..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIListener.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper; - -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.plugin.messaging.PluginMessageListener; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.PlayerDataObj; - -public class EaglerXBukkitAPIListener implements Listener, PluginMessageListener { - - @EventHandler - public void onLoginEvent(PlayerLoginEvent evt) { - PlayerDataObj.setupPlayer(evt.getPlayer()); - } - - @Override - public void onPluginMessageReceived(String channel, Player player, byte[] data) { - PlayerDataObj dataObj; - switch(channel) { - case EaglerBackendRPCProtocol.CHANNEL_NAME: - case EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN: - dataObj = PlayerDataObj.getForPlayer(player); - if(dataObj != null) { - dataObj.firePluginMsgRecievedInternal(data); - } - break; - case EaglerBackendRPCProtocol.CHANNEL_NAME_READY: - dataObj = PlayerDataObj.getForPlayer(player); - if(dataObj != null) { - dataObj.firePluginReadyMsgRecieved(false); - } - break; - case EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN: - dataObj = PlayerDataObj.getForPlayer(player); - if(dataObj != null) { - dataObj.firePluginReadyMsgRecieved(true); - } - default: - break; - } - } - - @EventHandler - public void onQuitEvent(PlayerQuitEvent evt) { - PlayerDataObj dataObj = PlayerDataObj.getForPlayer(evt.getPlayer()); - if(dataObj != null) { - dataObj.firePlayerQuitEventInternal(); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIPlugin.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIPlugin.java deleted file mode 100644 index 4f7319ce..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/EaglerXBukkitAPIPlugin.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper; - -import java.util.Collection; -import java.util.Timer; -import java.util.TimerTask; -import java.util.logging.Logger; - -import org.bukkit.Server; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.plugin.messaging.Messenger; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.PlayerDataObj; - -public class EaglerXBukkitAPIPlugin extends JavaPlugin { - - private static EaglerXBukkitAPIPlugin instance = null; - - private Timer timeoutHandler; - - public EaglerXBukkitAPIPlugin() { - instance = this; - } - - @Override - public void onLoad() { - - } - - @Override - public void onEnable() { - EaglerXBukkitAPIListener ls = new EaglerXBukkitAPIListener(); - Server svr = getServer(); - svr.getPluginManager().registerEvents(ls, this); - Messenger msgr = svr.getMessenger(); - boolean registerLegacy = !isPost_v1_13(); - if(registerLegacy) { - try { - msgr.registerOutgoingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME); - }catch(Throwable t) { - registerLegacy = false; - } - } - if(!registerLegacy) { - getLogger().warning("Note: Only the modernized plugin channel names can be used for this server!"); - getLogger().warning("Make sure to set \"use_modernized_channel_names: true\" in bungee/velocity plugin settings.yml"); - } - msgr.registerOutgoingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN); - if(registerLegacy) { - msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME, ls); - } - msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN, ls); - if(registerLegacy) { - msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_READY, ls); - } - msgr.registerIncomingPluginChannel(this, EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN, ls); - if(timeoutHandler == null) { - timeoutHandler = new Timer("EaglerXBukkitAPI: Timeout cleanup thread"); - timeoutHandler.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - Collection pp = EaglerXBukkitAPIPlugin.this.getServer().getOnlinePlayers(); - if(!pp.isEmpty()) { - long now = System.nanoTime() / 1000000l; - for(Player p : pp) { - PlayerDataObj.getForPlayer(p).fireCheckRequestTimeoutsInternal(now); - } - } - } - }, 0l, 5000l); - } - } - - @Override - public void onDisable() { - getServer().getMessenger().unregisterOutgoingPluginChannel(this); - getServer().getMessenger().unregisterIncomingPluginChannel(this); - if(timeoutHandler != null) { - timeoutHandler.cancel(); - timeoutHandler = null; - } - } - - public static EaglerXBukkitAPIPlugin getEagler() { - return instance; - } - - public static Logger logger() { - return instance.getLogger(); - } - - private boolean isPost_v1_13() { - String[] ver = getServer().getVersion().split("[\\.\\-]"); - if(ver.length >= 2) { - try { - return Integer.parseInt(ver[0]) >= 1 || Integer.parseInt(ver[1]) >= 13; - }catch(NumberFormatException ex) { - } - } - return false; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ClientBrandUUIDs.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ClientBrandUUIDs.java deleted file mode 100644 index e8660dc2..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ClientBrandUUIDs.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -public class ClientBrandUUIDs { - - public static final UUID BRAND_NULL_UUID = new UUID(0l, 0l); - public static final UUID BRAND_VANILLA_UUID = new UUID(0x1DCE015CD384374El, 0x85030A4DE95E5736l); - - public static final UUID BRAND_EAGLERCRAFTX_V4_UUID = makeClientBrandUUID("EaglercraftX"); - public static final UUID BRAND_EAGLERCRAFTX_LEGACY_UUID = makeClientBrandUUIDLegacy("EaglercraftX"); - - public static UUID makeClientBrandUUID(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClient:" + name).getBytes(StandardCharsets.UTF_8)); - } - - public static UUID makeClientBrandUUIDLegacy(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8)); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCException.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCException.java deleted file mode 100644 index 4cd44cd5..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -public class EaglerRPCException extends RuntimeException { - - public EaglerRPCException() { - } - - public EaglerRPCException(String message, Throwable cause) { - super(message, cause); - } - - public EaglerRPCException(String message) { - super(message); - } - - public EaglerRPCException(Throwable cause) { - super(cause); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCInitException.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCInitException.java deleted file mode 100644 index df2ad05b..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EaglerRPCInitException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -public class EaglerRPCInitException extends EaglerRPCException { - - private int code; - - public EaglerRPCInitException(int code) { - this.code = code; - } - - public EaglerRPCInitException(int code, String message, Throwable cause) { - super(message, cause); - this.code = code; - } - - public EaglerRPCInitException(int code, String message) { - super(message); - this.code = code; - } - - public EaglerRPCInitException(int code, Throwable cause) { - super(cause); - this.code = code; - } - - public int getFailureCodeEagler() { - return code; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EnumSubscribeEvents.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EnumSubscribeEvents.java deleted file mode 100644 index fa11f21a..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/EnumSubscribeEvents.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCSubscribeEvents; - -public enum EnumSubscribeEvents { - - /** @see net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.EventWebViewOpenClose */ - EVENT_WEBVIEW_OPEN_CLOSE(CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE), - - /** @see net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.EventWebViewMessage */ - EVENT_WEBVIEW_MESSAGE(CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_MESSAGE), - - /** @see net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.EventToggledVoice */ - EVENT_TOGGLE_VOICE(CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE); - - protected static final EnumSubscribeEvents[] _VALUES = values(); - - public final int bit; - - private EnumSubscribeEvents(int bit) { - this.bit = bit; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCCloseHandler.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCCloseHandler.java deleted file mode 100644 index 18af0ec8..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCCloseHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -public interface IEaglerRPCCloseHandler { - - void handleEvent(IEaglerXBukkitAPI api); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCEventHandler.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCEventHandler.java deleted file mode 100644 index 4376c900..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCEventHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.IEaglerRPCEvent; - -public interface IEaglerRPCEventHandler { - - void handleEvent(IEaglerXBukkitAPI api, EnumSubscribeEvents event, T data); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCFuture.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCFuture.java deleted file mode 100644 index d3519d5f..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerRPCFuture.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import java.util.concurrent.Executor; - -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.SameThreadExecutor; - -public interface IEaglerRPCFuture extends ListenableFuture { - - /** - * Warning: Futures.addCallback is recommended! - */ - default void addListener(Runnable runnable) { - addListener(runnable, SameThreadExecutor.SAME_THREAD_EXECUTOR); - } - - default void addCallback(FutureCallback runnable, Executor executor) { - Futures.addCallback(this, runnable, executor); - } - - default void addCallback(FutureCallback runnable) { - Futures.addCallback(this, runnable, SameThreadExecutor.SAME_THREAD_EXECUTOR); - } - - void setExpiresMSFromNow(int millis); - - boolean hasExpired(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerXBukkitAPI.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerXBukkitAPI.java deleted file mode 100644 index e23b337c..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/IEaglerXBukkitAPI.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.bukkit.entity.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCNotifBadgeShow; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCSetPauseMenuCustom; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.NotificationBadgeBuilder; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.SkinPacketHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.IEaglerRPCEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseBytes; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseCookie; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseString; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseUUID; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseVoiceStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.ResponseWebViewStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl.EaglerXBukkitImpl; - -public interface IEaglerXBukkitAPI { - - public static IEaglerRPCFuture getAPI(Player player) { - IEaglerRPCFuture futureRet = EaglerXBukkitImpl.getAPI(player); - futureRet.setExpiresMSFromNow(EaglerXBukkitImpl.DEFAULT_TIMEOUT); - return futureRet; - } - - public static IEaglerRPCFuture getAPI(Player player, int timeoutMS) { - IEaglerRPCFuture futureRet = EaglerXBukkitImpl.getAPI(player); - futureRet.setExpiresMSFromNow(timeoutMS); - return futureRet; - } - - EaglerBackendRPCProtocol getRPCProtocolVersion(); - - int getEaglerProtocolVersion(); - - boolean isOpen(); - - void closeAPI(); - - Player getPlayer(); - - void sendRPCPacket(EaglerBackendRPCPacket packet); - - default void subscribeEvents(EnumSubscribeEvents...events) { - int bits = 0; - for(int i = 0; i < events.length; ++i) { - bits |= events[i].bit; - } - subscribeEvents(bits); - } - - void subscribeEvents(int events); - - default void unsubscribeEvents(EnumSubscribeEvents...events) { - int bits = 0; - for(int i = 0; i < events.length; ++i) { - bits |= events[i].bit; - } - unsubscribeEvents(bits); - } - - void unsubscribeEvents(int events); - - void unsubscribeAllEvents(); - - int getSubscribedEventsBits(); - - default Set getSubscribedEvents() { - Set ret = new HashSet<>(4); - int bits = getSubscribedEventsBits(); - EnumSubscribeEvents[] enums = EnumSubscribeEvents._VALUES; - for(int i = 0; i < enums.length; ++i) { - if((bits & enums[i].bit) != 0) { - ret.add(enums[i]); - } - } - return ret; - } - - void addEventListener(EnumSubscribeEvents eventType, IEaglerRPCEventHandler handler); - - void removeEventListener(EnumSubscribeEvents eventType, IEaglerRPCEventHandler handler); - - void removeEventListeners(EnumSubscribeEvents eventType); - - void addCloseListener(IEaglerRPCCloseHandler handler); - - void removeCloseListener(IEaglerRPCCloseHandler handler); - - void removeCloseListeners(); - - boolean redirectPlayerSupported(); - - void redirectPlayerToWebSocket(String webSocketURI); - - void setBaseRequestTimeout(int seconds); - - IEaglerRPCFuture requestPlayerProfileUUID(); - - IEaglerRPCFuture requestPlayerRealIP(); - - IEaglerRPCFuture requestPlayerOrigin(); - - IEaglerRPCFuture requestPlayerUserAgent(); - - IEaglerRPCFuture requestPlayerSkinData(); - - IEaglerRPCFuture requestPlayerCapeData(); - - IEaglerRPCFuture requestPlayerCookieData(); - - IEaglerRPCFuture requestPlayerClientBrandStr(); - - IEaglerRPCFuture requestPlayerClientVersionStr(); - - IEaglerRPCFuture requestPlayerClientBrandAndVersionStr(); - - IEaglerRPCFuture requestPlayerClientBrandUUID(); - - IEaglerRPCFuture requestPlayerVoiceStatus(); - - IEaglerRPCFuture requestPlayerWebViewStatus(); - - void sendRawCustomPayloadPacket(String channel, byte[] data); - - default void sendRawEaglerPacketV4(byte[] data) { - sendRawCustomPayloadPacket("EAG|1.8", data); - } - - boolean pauseMenuCustomizationSupported(); - - void setPauseMenuCustomizationState(CPacketRPCSetPauseMenuCustom packet); - - void sendWebViewMessageString(String channelName, String data); - - void sendWebViewMessageBytes(String channelName, byte[] data); - - void forcePlayerSkin(byte[] skinData, boolean notifyOthers); - - default void forcePlayerSkinPreset(int presetID, boolean notifyOthers) { - forcePlayerSkin(SkinPacketHelper.writePresetSkinPacket(presetID), notifyOthers); - } - - default void forcePlayerSkinCustom(int modelId, byte[] texture64x64, boolean notifyOthers) { - forcePlayerSkin(SkinPacketHelper.writeCustomSkinPacket(modelId, texture64x64), notifyOthers); - } - - void forcePlayerCape(byte[] capeData, boolean notifyOthers); - - default void forcePlayerCapePreset(int presetID, boolean notifyOthers) { - forcePlayerCape(SkinPacketHelper.writePresetCapePacket(presetID), notifyOthers); - } - - default void forcePlayerCapeCustom(byte[] texture32x32, boolean notifyOthers) { - forcePlayerCape(SkinPacketHelper.writeCustomCapePacket(texture32x32), notifyOthers); - } - - void setCookieData(byte[] cookieData, int expiresAfterSec, boolean revokeQuerySupported, boolean saveToDisk); - - default void setCookieData(byte[] cookieData, int expiresAfter, TimeUnit expiresTimeUnit, boolean revokeQuerySupported, boolean saveToDisk) { - setCookieData(cookieData, (int)expiresTimeUnit.toSeconds(expiresAfter), revokeQuerySupported, saveToDisk); - } - - default void setCookieData(byte[] cookieData, int expiresAfterSec, boolean revokeQuerySupported) { - setCookieData(cookieData, expiresAfterSec, revokeQuerySupported, true); - } - - default void setCookieData(byte[] cookieData, int expiresAfter, TimeUnit expiresTimeUnit, boolean revokeQuerySupported) { - setCookieData(cookieData, (int)expiresTimeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - default void setCookieData(byte[] cookieData, int expiresAfterSec) { - setCookieData(cookieData, expiresAfterSec, false, true); - } - - default void setCookieData(byte[] cookieData, int expiresAfter, TimeUnit expiresTimeUnit) { - setCookieData(cookieData, (int)expiresTimeUnit.toSeconds(expiresAfter), false, true); - } - - default void clearCookieData() { - setCookieData(null, 0, false, false); - } - - void setFNAWSkinsEnabled(boolean enabled, boolean force); - - void setFNAWSkinsEnabled(boolean enabled); - - void resetForcedMulti(boolean resetSkin, boolean resetCape, boolean resetFNAWForce, boolean notifyOtherPlayers); - - void resetForcedSkin(boolean notifyOtherPlayers); - - void resetForcedCape(boolean notifyOtherPlayers); - - void resetForcedFNAW(); - - boolean notifSupported(); - - void notifIconRegister(Map iconsToRegister); - - void notifIconRegister(UUID iconUUID, PacketImageData imageData); - - void notifIconRelease(Collection iconsToRelease); - - void notifIconRelease(UUID iconUUID); - - void notifBadgeShow(CPacketRPCNotifBadgeShow packet); - - default void notifBadgeShow(NotificationBadgeBuilder packet) { - notifBadgeShow(packet.buildPacket()); - } - - void notifBadgeHide(UUID badgeUUID); - - void setMeta(String key, T value); - - T getMeta(String key); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ImageDataLoader.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ImageDataLoader.java deleted file mode 100644 index da293656..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/ImageDataLoader.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.SkinPacketHelper; - -public class ImageDataLoader { - - public static PacketImageData loadPacketImageData(File img) throws IOException { - return loadPacketImageData(ImageIO.read(img), 255, 255); - } - - public static PacketImageData loadPacketImageData(File img, int maxWidth, int maxHeight) throws IOException { - return loadPacketImageData(ImageIO.read(img), maxWidth, maxHeight); - } - - public static PacketImageData loadPacketImageData(BufferedImage img) { - return loadPacketImageData(img, 255, 255); - } - - public static PacketImageData loadPacketImageData(BufferedImage img, int maxWidth, int maxHeight) { - int w = img.getWidth(); - int h = img.getHeight(); - if(w > maxWidth || h > maxHeight) { - float aspectRatio = (float)w / (float)h; - int nw, nh; - if(aspectRatio >= 1.0f) { - nw = (int)(maxWidth / aspectRatio); - nh = maxHeight; - }else { - nw = maxWidth; - nh = (int)(maxHeight * aspectRatio); - } - BufferedImage resized = new BufferedImage(nw, nh, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) resized.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, nw, nh); - g.drawImage(img, 0, 0, nw, nh, 0, 0, w, h, null); - g.dispose(); - img = resized; - } - int[] pixels = new int[w * h]; - img.getRGB(0, 0, w, h, pixels, 0, w); - return new PacketImageData(w, h, pixels); - } - - public static byte[] loadCustomSkin(File texture64x64) throws IOException { - return SkinPacketHelper.loadCustomSkin(texture64x64); - } - - public static byte[] loadCustomSkin(InputStream texture64x64) throws IOException { - return SkinPacketHelper.loadCustomSkin(texture64x64); - } - - public static byte[] loadCustomSkin(BufferedImage texture64x64) { - return SkinPacketHelper.loadCustomSkin(texture64x64); - } - - public static byte[] loadCustomCape(File textureNx64) throws IOException { - return SkinPacketHelper.loadCustomCape(textureNx64); - } - - public static byte[] loadCustomCape(InputStream textureNx64) throws IOException { - return SkinPacketHelper.loadCustomCape(textureNx64); - } - - public static byte[] loadCustomCape(BufferedImage textureNx64) { - return SkinPacketHelper.loadCustomCape(textureNx64); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventToggledVoice.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventToggledVoice.java deleted file mode 100644 index 9644515c..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventToggledVoice.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EnumSubscribeEvents; - -public class EventToggledVoice implements IEaglerRPCEvent { - - public static enum VoiceState { - SERVER_DISABLE, DISABLED, ENABLED; - } - - public final VoiceState oldVoiceState; - public final VoiceState newVoiceState; - - public EventToggledVoice(VoiceState oldVoiceState, VoiceState newVoiceState) { - this.oldVoiceState = oldVoiceState; - this.newVoiceState = newVoiceState; - } - - @Override - public EnumSubscribeEvents getType() { - return EnumSubscribeEvents.EVENT_TOGGLE_VOICE; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewMessage.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewMessage.java deleted file mode 100644 index 35bd5017..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewMessage.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event; - -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EnumSubscribeEvents; - -public class EventWebViewMessage implements IEaglerRPCEvent { - - public static enum MessageType { - STRING, BINARY; - } - - public final String channelName; - public final MessageType messageType; - protected final byte[] messageContent; - protected String asString = null; - - public EventWebViewMessage(String channelName, MessageType messageType, byte[] messageContent) { - this.channelName = channelName; - this.messageType = messageType; - this.messageContent = messageContent; - } - - public String getContentStr() { - if(messageType == MessageType.STRING) { - if(asString == null) { - asString = new String(messageContent, StandardCharsets.UTF_8); - } - return asString; - }else { - return null; - } - } - - public byte[] getContentBytes() { - return messageType == MessageType.BINARY ? messageContent : null; - } - - @Override - public EnumSubscribeEvents getType() { - return EnumSubscribeEvents.EVENT_WEBVIEW_MESSAGE; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewOpenClose.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewOpenClose.java deleted file mode 100644 index 1fb8bf7b..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/EventWebViewOpenClose.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EnumSubscribeEvents; - -public class EventWebViewOpenClose implements IEaglerRPCEvent { - - public final String channelName; - public final boolean opened; - - public EventWebViewOpenClose(String channelName, boolean opened) { - this.channelName = channelName; - this.opened = opened; - } - - @Override - public EnumSubscribeEvents getType() { - return EnumSubscribeEvents.EVENT_WEBVIEW_OPEN_CLOSE; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/IEaglerRPCEvent.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/IEaglerRPCEvent.java deleted file mode 100644 index 34cdd95d..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/event/IEaglerRPCEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EnumSubscribeEvents; - -public interface IEaglerRPCEvent { - - EnumSubscribeEvents getType(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCResponseException.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCResponseException.java deleted file mode 100644 index a6774aa4..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCResponseException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EaglerRPCException; - -public class EaglerRPCResponseException extends EaglerRPCException { - - public EaglerRPCResponseException() { - } - - public EaglerRPCResponseException(String message, Throwable cause) { - super(message, cause); - } - - public EaglerRPCResponseException(String message) { - super(message); - } - - public EaglerRPCResponseException(Throwable cause) { - super(cause); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCTimeoutException.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCTimeoutException.java deleted file mode 100644 index 661d3353..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/EaglerRPCTimeoutException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EaglerRPCException; - -public class EaglerRPCTimeoutException extends EaglerRPCException { - - public EaglerRPCTimeoutException() { - } - - public EaglerRPCTimeoutException(String message) { - super(message); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/IEaglerRPCResponse.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/IEaglerRPCResponse.java deleted file mode 100644 index a61fe8bb..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/IEaglerRPCResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public interface IEaglerRPCResponse { - - IEaglerXBukkitAPI getSource(); - - int getRequestID(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseBytes.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseBytes.java deleted file mode 100644 index 2ed51b61..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseBytes.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseBytes implements IEaglerRPCResponse { - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final byte[] bytes; - - public ResponseBytes(IEaglerXBukkitAPI source, int requestID, byte[] bytes) { - this.source = source; - this.requestID = requestID; - this.bytes = bytes; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseCookie.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseCookie.java deleted file mode 100644 index c0fd9bd5..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseCookie.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseCookie implements IEaglerRPCResponse { - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final boolean cookieEnabled; - public final byte[] cookieBytes; - - public ResponseCookie(IEaglerXBukkitAPI source, int requestID, boolean cookieEnabled, byte[] cookieBytes) { - this.source = source; - this.requestID = requestID; - this.cookieEnabled = cookieEnabled; - this.cookieBytes = cookieBytes; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseString.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseString.java deleted file mode 100644 index 316ea31e..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseString.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseString implements IEaglerRPCResponse { - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final String string; - - public ResponseString(IEaglerXBukkitAPI source, int requestID, String string) { - this.source = source; - this.requestID = requestID; - this.string = string; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseUUID.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseUUID.java deleted file mode 100644 index 699cf326..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseUUID.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseUUID implements IEaglerRPCResponse { - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final UUID uuid; - - public ResponseUUID(IEaglerXBukkitAPI source, int requestID, UUID uuid) { - this.source = source; - this.requestID = requestID; - this.uuid = uuid; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseVoiceStatus.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseVoiceStatus.java deleted file mode 100644 index a98f852c..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseVoiceStatus.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseVoiceStatus implements IEaglerRPCResponse { - - public static enum VoiceState { - SERVER_DISABLE, DISABLED, ENABLED; - } - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final VoiceState voiceState; - - public ResponseVoiceStatus(IEaglerXBukkitAPI source, int requestID, VoiceState voiceState) { - this.source = source; - this.requestID = requestID; - this.voiceState = voiceState; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseWebViewStatus.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseWebViewStatus.java deleted file mode 100644 index c99550fc..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/api/response/ResponseWebViewStatus.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; - -public class ResponseWebViewStatus implements IEaglerRPCResponse { - - public static enum WebViewState { - NOT_SUPPORTED, SERVER_DISABLE, CHANNEL_CLOSED, CHANNEL_OPEN; - } - - protected final IEaglerXBukkitAPI source; - protected final int requestID; - public final WebViewState webviewState; - public final String channelName; - - public ResponseWebViewStatus(IEaglerXBukkitAPI source, int requestID, WebViewState webviewState, String channelName) { - this.source = source; - this.requestID = requestID; - this.webviewState = webviewState; - this.channelName = channelName; - } - - @Override - public IEaglerXBukkitAPI getSource() { - return source; - } - - @Override - public int getRequestID() { - return requestID; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerRPCFutureImpl.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerRPCFutureImpl.java deleted file mode 100644 index 601d3a77..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerRPCFutureImpl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import com.google.common.util.concurrent.AbstractFuture; - -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerRPCFuture; - -public class EaglerRPCFutureImpl extends AbstractFuture implements IEaglerRPCFuture { - - private volatile long timeStart = -1l; - private volatile int timeoutAfter = -1; - - @Override - public void setExpiresMSFromNow(int millis) { - if(millis > 0) { - timeStart = System.nanoTime() / 1000000l; - timeoutAfter = millis; - }else { - timeStart = -1l; - timeoutAfter = -1; - } - } - - @Override - public boolean hasExpired() { - return (timeStart > 0l && timeoutAfter > 0) ? ((System.nanoTime() / 1000000l) - timeStart) > timeoutAfter : false; - } - - public boolean hasExpiredBetter(long now) { - return (timeStart > 0l && timeoutAfter > 0) ? (now - timeStart) > timeoutAfter : false; - } - - public void fireCompleteInternal(V value) { - this.set(value); - } - - public void fireExceptionInternal(Throwable value) { - this.setException(value); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerXBukkitImpl.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerXBukkitImpl.java deleted file mode 100644 index 78ecfe06..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/EaglerXBukkitImpl.java +++ /dev/null @@ -1,789 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; - -import org.bukkit.entity.Player; - -import com.google.common.collect.ListMultimap; -import com.google.common.collect.MultimapBuilder.ListMultimapBuilder; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.EaglerXBukkitAPIPlugin; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EaglerRPCException; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EnumSubscribeEvents; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerRPCCloseHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerRPCEventHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerRPCFuture; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.event.*; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.*; - -public class EaglerXBukkitImpl implements IEaglerXBukkitAPI { - - public static final int DEFAULT_TIMEOUT = 10000; - - public static EaglerRPCFutureImpl getAPI(Player player) { - if(player == null) { - throw new NullPointerException("Player cannot be null!"); - } - PlayerDataObj data = PlayerDataObj.getForPlayer(player); - if(data == null) { - throw new IllegalStateException("Player object is not ready yet for EaglerXBukkitAPI.createAPI()! (Try hooking PlayerJoinEvent instead of PlayerLoginEvent you hooker)"); - } - boolean sendHello; - synchronized(data) { - if(data.openFuture != null) { - return data.openFuture; - } - if(data.currentAPI != null) { - EaglerRPCFutureImpl completeImmedately = new EaglerRPCFutureImpl(); - completeImmedately.fireCompleteInternal(data.currentAPI); - return completeImmedately; - } - data.openFuture = new EaglerRPCFutureImpl(); - sendHello = data.hasRecievedReady; - } - if(sendHello) { - sendHelloPacket(data.pluginChName, player); - } - return data.openFuture; - } - - protected static void sendHelloPacket(String channel, Player player) { - player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), channel, HelloPacketFactory.BASE_HELLO_PACKET); - } - - protected static EaglerXBukkitImpl createFromHandshakeInternal(PlayerDataObj playerDataObj, SPacketRPCEnabledSuccess pkt) { - return new EaglerXBukkitImpl(playerDataObj, EaglerBackendRPCProtocol.getByID(pkt.selectedRPCProtocol), pkt.playerClientProtocol); - } - - protected final PlayerDataObj playerDataObj; - protected final Player playerObj; - protected final EaglerBackendRPCProtocol protocol; - protected final int gameProtocol; - protected boolean open; - protected final Map metadata = new ConcurrentHashMap<>(4); - protected final EaglerXBukkitAPIHandler packetHandler; - protected int subscribedEvents = 0; - protected final ListMultimap> eventHandlers = ListMultimapBuilder - .hashKeys().arrayListValues().build(); - protected final List closeHandlers = new ArrayList<>(4); - protected final Map> waitingRequests = new ConcurrentHashMap<>(); - protected int baseTimeout = DEFAULT_TIMEOUT; - protected final AtomicInteger requestIDGenerator = new AtomicInteger(); - private final ReentrantLock inputStreamLock = new ReentrantLock(); - private final ReentrantLock outputStreamLock = new ReentrantLock(); - private final ReusableByteArrayInputStream reusableInputStream = new ReusableByteArrayInputStream(); - private final ReusableByteArrayOutputStream reusableOutputStream = new ReusableByteArrayOutputStream(); - private final DataInputStream dataInputStream = new DataInputStream(reusableInputStream); - private final DataOutputStream dataOutputStream = new DataOutputStream(reusableOutputStream); - - protected EaglerXBukkitImpl(PlayerDataObj playerDataObj, EaglerBackendRPCProtocol protocol, int gameProtocol) { - this.playerDataObj = playerDataObj; - this.playerObj = playerDataObj.player; - this.protocol = protocol; - this.gameProtocol = gameProtocol; - this.open = true; - this.packetHandler = new EaglerXBukkitAPIHandler(); - } - - @Override - public EaglerBackendRPCProtocol getRPCProtocolVersion() { - return protocol; - } - - @Override - public int getEaglerProtocolVersion() { - return gameProtocol; - } - - @Override - public boolean isOpen() { - return open; - } - - @Override - public void closeAPI() { - if(open) { - try { - sendRPCPacket(new CPacketRPCDisabled()); - }finally { - fireAPIClosedEventInternal(); - } - } - } - - protected void fireAPIClosedEventInternal() { - if(!open) return; - open = false; - synchronized(closeHandlers) { - for(int i = 0, l = closeHandlers.size(); i < l; ++i) { - IEaglerRPCCloseHandler hd = closeHandlers.get(i); - try { - hd.handleEvent(this); - }catch(Throwable t) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, - "[" + playerObj.getName() + "] caught exception while firing close handler " + hd, t); - } - } - } - } - - protected void fireAPIPacketRecievedInternal(EaglerBackendRPCPacket ret) { - ret.handlePacket(packetHandler); - } - - protected void fireEventHandlers(T eventObj) { - EnumSubscribeEvents type = eventObj.getType(); - List> lst; - synchronized(eventHandlers) { - lst = eventHandlers.get(type); - } - for(int i = 0, l = lst.size(); i < l; ++i) { - IEaglerRPCEventHandler handler = (IEaglerRPCEventHandler) lst.get(i); - try { - handler.handleEvent(this, type, eventObj); - }catch(Throwable t) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, - "[" + playerObj.getName() + "] caught exception while processing event type " - + type + " using handler " + handler, t); - } - } - } - - protected class EaglerXBukkitAPIHandler implements EaglerBackendRPCHandler { - - public void handleServer(SPacketRPCResponseTypeNull packet) { - EaglerRPCFutureImpl future = waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(null); - } - } - - public void handleServer(SPacketRPCResponseTypeBytes packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseBytes(EaglerXBukkitImpl.this, packet.requestID, packet.response)); - } - } - - public void handleServer(SPacketRPCResponseTypeString packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseString(EaglerXBukkitImpl.this, packet.requestID, packet.response)); - } - } - - public void handleServer(SPacketRPCResponseTypeUUID packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseUUID(EaglerXBukkitImpl.this, packet.requestID, packet.uuid)); - } - } - - public void handleServer(SPacketRPCResponseTypeCookie packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseCookie(EaglerXBukkitImpl.this, packet.requestID, packet.cookiesEnabled, packet.cookieData)); - } - } - - public void handleServer(SPacketRPCResponseTypeVoiceStatus packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseVoiceStatus(EaglerXBukkitImpl.this, packet.requestID, translateVoiceState2(packet.voiceState))); - } - } - - public void handleServer(SPacketRPCResponseTypeWebViewStatus packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireCompleteInternal(new ResponseWebViewStatus(EaglerXBukkitImpl.this, packet.requestID, translateWebViewState(packet.webviewState), packet.channelName)); - } - } - - public void handleServer(SPacketRPCResponseTypeError packet) { - EaglerRPCFutureImpl future = (EaglerRPCFutureImpl)waitingRequests.remove(packet.requestID); - if(future != null) { - future.fireExceptionInternal(new EaglerRPCResponseException(packet.errorMessage)); - } - } - - public void handleServer(SPacketRPCEventWebViewOpenClose packet) { - if((subscribedEvents & EnumSubscribeEvents.EVENT_WEBVIEW_OPEN_CLOSE.bit) != 0) { - fireEventHandlers(new EventWebViewOpenClose(packet.channelName, packet.channelOpen)); - } - } - - public void handleServer(SPacketRPCEventWebViewMessage packet) { - if((subscribedEvents & EnumSubscribeEvents.EVENT_WEBVIEW_MESSAGE.bit) != 0) { - EventWebViewMessage.MessageType mt; - switch(packet.messageType) { - case SPacketRPCEventWebViewMessage.MESSAGE_TYPE_STRING: - mt = EventWebViewMessage.MessageType.STRING; - break; - case SPacketRPCEventWebViewMessage.MESSAGE_TYPE_BINARY: - mt = EventWebViewMessage.MessageType.BINARY; - break; - default: - return; - } - fireEventHandlers(new EventWebViewMessage(packet.channelName, mt, packet.messageContent)); - } - } - - public void handleServer(SPacketRPCEventToggledVoice packet) { - if((subscribedEvents & EnumSubscribeEvents.EVENT_TOGGLE_VOICE.bit) != 0) { - EventToggledVoice.VoiceState vsOld = translateVoiceState(packet.oldVoiceState); - EventToggledVoice.VoiceState vsNew = translateVoiceState(packet.newVoiceState); - if(vsOld == null || vsNew == null) { - return; - } - fireEventHandlers(new EventToggledVoice(vsOld, vsNew)); - } - } - - } - - private static EventToggledVoice.VoiceState translateVoiceState(int vs) { - switch(vs) { - case SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_SERVER_DISABLE: - return EventToggledVoice.VoiceState.SERVER_DISABLE; - case SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_DISABLED: - return EventToggledVoice.VoiceState.DISABLED; - case SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_ENABLED: - return EventToggledVoice.VoiceState.ENABLED; - default: - return null; - } - } - - private static ResponseVoiceStatus.VoiceState translateVoiceState2(int vs) { - switch(vs) { - case SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE: - default: - return ResponseVoiceStatus.VoiceState.SERVER_DISABLE; - case SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED: - return ResponseVoiceStatus.VoiceState.DISABLED; - case SPacketRPCEventToggledVoice.VOICE_STATE_ENABLED: - return ResponseVoiceStatus.VoiceState.ENABLED; - } - } - - private static ResponseWebViewStatus.WebViewState translateWebViewState(int vs) { - switch(vs) { - case SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_NOT_SUPPORTED: - default: - return ResponseWebViewStatus.WebViewState.NOT_SUPPORTED; - case SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_SERVER_DISABLE: - return ResponseWebViewStatus.WebViewState.SERVER_DISABLE; - case SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_CLOSED: - return ResponseWebViewStatus.WebViewState.CHANNEL_CLOSED; - case SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_OPEN: - return ResponseWebViewStatus.WebViewState.CHANNEL_OPEN; - } - } - - @Override - public Player getPlayer() { - return playerObj; - } - - @Override - public void sendRPCPacket(EaglerBackendRPCPacket packet) { - if(!open) { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() + "] Sent " + packet.getClass().getSimpleName() + " on a dead connection!"); - return; - } - if(packet == null) { - throw new NullPointerException("Packet cannot be null!"); - } - byte[] ret; - int len = packet.length() + 1; - if(outputStreamLock.tryLock()) { - try { - reusableOutputStream.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(dataOutputStream, EaglerBackendRPCProtocol.CLIENT_TO_SERVER, packet); - }catch(IOException ex) { - throw new EaglerRPCException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = reusableOutputStream.returnBuffer(); - }finally { - outputStreamLock.unlock(); - } - }else { - ReusableByteArrayOutputStream bao = new ReusableByteArrayOutputStream(); - bao.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(new DataOutputStream(bao), EaglerBackendRPCProtocol.CLIENT_TO_SERVER, packet); - }catch(IOException ex) { - throw new EaglerRPCException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = bao.returnBuffer(); - } - if(len > 0 && len != ret.length) { - EaglerXBukkitAPIPlugin.logger() - .warning("[" + playerObj.getName() + "] Packet type " + packet.getClass().getSimpleName() - + " was the wrong length after serialization: " + ret.length + " != " + len); - } - playerObj.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), playerDataObj.pluginChName, ret); - } - - protected EaglerBackendRPCPacket decodePacket(byte[] data) throws IOException { - EaglerBackendRPCPacket ret; - if(inputStreamLock.tryLock()) { - try { - reusableInputStream.feedBuffer(data); - ret = protocol.readPacket(dataInputStream, EaglerBackendRPCProtocol.SERVER_TO_CLIENT); - }finally { - inputStreamLock.unlock(); - } - }else { - ReusableByteArrayInputStream bai = new ReusableByteArrayInputStream(); - bai.feedBuffer(data); - ret = protocol.readPacket(new DataInputStream(bai), EaglerBackendRPCProtocol.SERVER_TO_CLIENT); - } - return ret; - } - - @Override - public void subscribeEvents(int events) { - int newEvents = subscribedEvents | events; - if(newEvents != subscribedEvents) { - sendRPCPacket(new CPacketRPCSubscribeEvents(newEvents)); - subscribedEvents = events; - } - } - - @Override - public void unsubscribeEvents(int events) { - int newEvents = subscribedEvents & ~events; - if(newEvents != subscribedEvents) { - sendRPCPacket(new CPacketRPCSubscribeEvents(newEvents)); - subscribedEvents = events; - } - } - - @Override - public void unsubscribeAllEvents() { - if(subscribedEvents != 0) { - sendRPCPacket(new CPacketRPCSubscribeEvents(0)); - subscribedEvents = 0; - } - } - - @Override - public int getSubscribedEventsBits() { - return subscribedEvents; - } - - @Override - public void addEventListener(EnumSubscribeEvents eventType, - IEaglerRPCEventHandler handler) { - synchronized(eventHandlers) { - eventHandlers.put(eventType, handler); - } - } - - @Override - public void removeEventListener(EnumSubscribeEvents eventType, - IEaglerRPCEventHandler handler) { - synchronized(eventHandlers) { - eventHandlers.remove(eventType, handler); - } - } - - @Override - public void removeEventListeners(EnumSubscribeEvents eventType) { - synchronized(eventHandlers) { - eventHandlers.removeAll(eventType); - } - } - - @Override - public void addCloseListener(IEaglerRPCCloseHandler handler) { - synchronized(closeHandlers) { - closeHandlers.add(handler); - } - } - - @Override - public void removeCloseListener(IEaglerRPCCloseHandler handler) { - synchronized(closeHandlers) { - closeHandlers.remove(handler); - } - } - - @Override - public void removeCloseListeners() { - synchronized(closeHandlers) { - closeHandlers.clear(); - } - } - - @Override - public boolean redirectPlayerSupported() { - return gameProtocol >= 4; - } - - @Override - public void redirectPlayerToWebSocket(String webSocketURI) { - if(gameProtocol >= 4) { - if(webSocketURI == null) { - throw new NullPointerException("URI cannot be null!"); - } - sendRPCPacket(new CPacketRPCRedirectPlayer(webSocketURI)); - }else { - EaglerXBukkitAPIPlugin.logger() - .warning("[" + playerObj.getName() + "] some plugin tried to redirect player to \"" + webSocketURI - + "\" but that player's client does not support websocket redirects!"); - } - } - - @Override - public void setBaseRequestTimeout(int seconds) { - baseTimeout = seconds * 1000; - } - - protected IEaglerRPCFuture requestSendHelper(int type) { - EaglerRPCFutureImpl ret = new EaglerRPCFutureImpl(); - ret.setExpiresMSFromNow(baseTimeout); - int rqid = requestIDGenerator.incrementAndGet(); - sendRPCPacket(new CPacketRPCRequestPlayerInfo(rqid, type)); - waitingRequests.put(rqid, ret); - return ret; - } - - @Override - public IEaglerRPCFuture requestPlayerProfileUUID() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_UUID); - } - - @Override - public IEaglerRPCFuture requestPlayerRealIP() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_IP); - } - - @Override - public IEaglerRPCFuture requestPlayerOrigin() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_ORIGIN); - } - - @Override - public IEaglerRPCFuture requestPlayerUserAgent() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_USER_AGENT); - } - - @Override - public IEaglerRPCFuture requestPlayerSkinData() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_SKIN_DATA); - } - - @Override - public IEaglerRPCFuture requestPlayerCapeData() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CAPE_DATA); - } - - @Override - public IEaglerRPCFuture requestPlayerCookieData() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_COOKIE); - } - - @Override - public IEaglerRPCFuture requestPlayerClientBrandStr() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_STR); - } - - @Override - public IEaglerRPCFuture requestPlayerClientVersionStr() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VERSION_STR); - } - - @Override - public IEaglerRPCFuture requestPlayerClientBrandAndVersionStr() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_VERSION_STR); - } - - @Override - public IEaglerRPCFuture requestPlayerClientBrandUUID() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_UUID); - } - - @Override - public IEaglerRPCFuture requestPlayerVoiceStatus() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VOICE_STATUS); - } - - @Override - public IEaglerRPCFuture requestPlayerWebViewStatus() { - return requestSendHelper(CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_WEBVIEW_STATUS); - } - - protected void cleanupTimedOutRequests(long now) { - if(!waitingRequests.isEmpty()) { - List> expired = null; - Iterator> itr = waitingRequests.values().iterator(); - while(itr.hasNext()) { - EaglerRPCFutureImpl itm = itr.next(); - if(itm.hasExpiredBetter(now)) { - if(expired == null) { - expired = new ArrayList<>(4); - } - expired.add(itm); - try { - itr.remove(); - }catch(Throwable t) { - } - } - } - if(expired != null) { - for(int i = 0, l = expired.size(); i < l; ++i) { - try { - EaglerRPCFutureImpl itm = expired.get(i); - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() + "] An RPC request timed out before it could be completed!"); - itm.fireExceptionInternal(new EaglerRPCTimeoutException("The request was not completed in time!")); - }catch(Throwable t) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, "[" + playerObj.getName() + "] An unhandled exception was thrown while firing request timeout signal!", t); - } - } - } - } - } - - @Override - public void sendRawCustomPayloadPacket(String channel, byte[] data) { - sendRPCPacket(new CPacketRPCSendRawMessage(channel, data)); - } - - @Override - public boolean pauseMenuCustomizationSupported() { - return gameProtocol >= 4; - } - - @Override - public void setPauseMenuCustomizationState(CPacketRPCSetPauseMenuCustom packet) { - if(gameProtocol >= 4) { - sendRPCPacket(packet); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to configure pause menu customization, but the player's client does not support that feature!"); - } - } - - @Override - public void sendWebViewMessageString(String channelName, String data) { - if(gameProtocol >= 4) { - if(channelName == null) { - throw new NullPointerException("Channel cannot be null!"); - } - if(data == null) { - throw new NullPointerException("Data cannot be null!"); - } - sendRPCPacket(new CPacketRPCSendWebViewMessage(channelName, - CPacketRPCSendWebViewMessage.MESSAGE_TYPE_STRING, data.getBytes(StandardCharsets.UTF_8))); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to send a webview channel message, but the player's client does not support that feature!"); - } - } - - @Override - public void sendWebViewMessageBytes(String channelName, byte[] data) { - if(gameProtocol >= 4) { - if(channelName == null) { - throw new NullPointerException("Channel cannot be null!"); - } - if(data == null) { - throw new NullPointerException("Data cannot be null!"); - } - sendRPCPacket(new CPacketRPCSendWebViewMessage(channelName, CPacketRPCSendWebViewMessage.MESSAGE_TYPE_BINARY, data)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to send a webview channel message, but the player's client does not support that feature!"); - } - } - - @Override - public void forcePlayerSkin(byte[] skinData, boolean notifyOthers) { - if(skinData == null) { - throw new NullPointerException("Skin data cannot be null!"); - } - if(skinData.length > 32720) { - throw new IllegalArgumentException("Skin data cannot be more than 32720 bytes!"); - } - sendRPCPacket(new CPacketRPCSetPlayerSkin(notifyOthers, skinData)); - } - - @Override - public void forcePlayerCape(byte[] capeData, boolean notifyOthers) { - if(capeData == null) { - throw new NullPointerException("Cape data cannot be null!"); - } - if(capeData.length > 32720) { - throw new IllegalArgumentException("Cape data cannot be more than 32720 bytes!"); - } - sendRPCPacket(new CPacketRPCSetPlayerCape(notifyOthers, capeData)); - } - - @Override - public void setCookieData(byte[] cookieData, int expiresAfterSec, boolean revokeQuerySupported, - boolean saveToDisk) { - if(gameProtocol >= 4) { - sendRPCPacket(new CPacketRPCSetPlayerCookie(revokeQuerySupported, saveToDisk, expiresAfterSec, cookieData)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to set a cookie, but the player's client does not support that feature!"); - } - } - - @Override - public void setFNAWSkinsEnabled(boolean enabled, boolean force) { - sendRPCPacket(new CPacketRPCSetPlayerFNAWEn(enabled, force)); - } - - @Override - public void setFNAWSkinsEnabled(boolean enabled) { - sendRPCPacket(new CPacketRPCSetPlayerFNAWEn(enabled, false)); - } - - @Override - public void resetForcedMulti(boolean resetSkin, boolean resetCape, boolean resetFNAWForce, boolean notifyOtherPlayers) { - sendRPCPacket(new CPacketRPCResetPlayerMulti(resetSkin, resetCape, resetFNAWForce, notifyOtherPlayers)); - } - - @Override - public void resetForcedSkin(boolean notifyOtherPlayers) { - sendRPCPacket(new CPacketRPCResetPlayerMulti(true, false, false, notifyOtherPlayers)); - } - - @Override - public void resetForcedCape(boolean notifyOtherPlayers) { - sendRPCPacket(new CPacketRPCResetPlayerMulti(false, true, false, notifyOtherPlayers)); - } - - @Override - public void resetForcedFNAW() { - sendRPCPacket(new CPacketRPCResetPlayerMulti(false, false, true, false)); - } - - @Override - public boolean notifSupported() { - return gameProtocol >= 4; - } - - @Override - public void notifIconRegister(Map iconsToRegister) { - if(gameProtocol >= 4) { - sendRPCPacket(new CPacketRPCNotifIconRegister(iconsToRegister)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to register notification icons, but the player's client does not support that feature!"); - } - } - - @Override - public void notifIconRegister(UUID iconUUID, PacketImageData imageData) { - if(gameProtocol >= 4) { - Map toReg = new HashMap<>(1); - toReg.put(iconUUID, imageData); - sendRPCPacket(new CPacketRPCNotifIconRegister(toReg)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to register notification icons, but the player's client does not support that feature!"); - } - } - - @Override - public void notifIconRelease(Collection iconsToRelease) { - if(gameProtocol >= 4) { - sendRPCPacket(new CPacketRPCNotifIconRelease(iconsToRelease)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to release notification icons, but the player's client does not support that feature!"); - } - } - - @Override - public void notifIconRelease(UUID iconUUID) { - if(gameProtocol >= 4) { - sendRPCPacket(new CPacketRPCNotifIconRelease(Arrays.asList(iconUUID))); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to release notification icons, but the player's client does not support that feature!"); - } - } - - @Override - public void notifBadgeShow(CPacketRPCNotifBadgeShow packet) { - if(gameProtocol >= 4) { - sendRPCPacket(packet); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to show notification badge, but the player's client does not support that feature!"); - } - } - - @Override - public void notifBadgeHide(UUID badgeUUID) { - if(gameProtocol >= 4) { - sendRPCPacket(new CPacketRPCNotifBadgeHide(badgeUUID)); - }else { - EaglerXBukkitAPIPlugin.logger().warning("[" + playerObj.getName() - + "] some plugin tried to hide notification badge, but the player's client does not support that feature!"); - } - } - - @Override - public void setMeta(String key, T value) { - if(key == null) { - throw new NullPointerException("Key cannot be null!"); - } - metadata.put(key, value); - } - - @Override - public T getMeta(String key) { - if(key == null) { - throw new NullPointerException("Key cannot be null!"); - } - return (T)metadata.get(key); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/HelloPacketFactory.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/HelloPacketFactory.java deleted file mode 100644 index 613fd34c..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/HelloPacketFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCEnabled; - -public class HelloPacketFactory { - - public static final byte[] BASE_HELLO_PACKET; - - static { - try { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dao = new DataOutputStream(bao); - CPacketRPCEnabled pkt = new CPacketRPCEnabled(new int[] { EaglerBackendRPCProtocol.V1.vers }); - EaglerBackendRPCProtocol.INIT.writePacket(dao, EaglerBackendRPCProtocol.CLIENT_TO_SERVER, pkt); - BASE_HELLO_PACKET = bao.toByteArray(); - }catch(IOException ex) { - throw new RuntimeException(ex); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/PlayerDataObj.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/PlayerDataObj.java deleted file mode 100644 index a678384f..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/PlayerDataObj.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.util.List; -import java.util.logging.Level; - -import org.bukkit.entity.Player; -import org.bukkit.metadata.LazyMetadataValue; -import org.bukkit.metadata.MetadataValue; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledFailure; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledSuccess; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.EaglerXBukkitAPIPlugin; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EaglerRPCException; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.EaglerRPCInitException; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.IEaglerXBukkitAPI; -import net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.api.response.EaglerRPCTimeoutException; - -public class PlayerDataObj { - - public static final String METADATA_BASE = "EXRPC_PDataObj"; - - public final Player player; - - public String pluginChName = null; - - public volatile boolean hasRecievedReady = false; - public volatile boolean isSupported = true; - public volatile EaglerXBukkitImpl currentAPI = null; - - public volatile EaglerRPCFutureImpl openFuture = null; - - public static PlayerDataObj getForPlayer(Player player) { - List vigg = player.getMetadata(METADATA_BASE); - return !vigg.isEmpty() ? (PlayerDataObj)vigg.get(0).value() : null; - } - - public static void setupPlayer(Player player) { - player.setMetadata(METADATA_BASE, new LazyMetadataValue(EaglerXBukkitAPIPlugin.getEagler(), () -> new PlayerDataObj(player))); - } - - protected PlayerDataObj(Player player) { - this.player = player; - } - - public void firePluginReadyMsgRecieved(boolean modern) { - synchronized(this) { - if(!hasRecievedReady) { - hasRecievedReady = true; - pluginChName = modern ? EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN : EaglerBackendRPCProtocol.CHANNEL_NAME; - if(openFuture != null) { - EaglerXBukkitImpl.sendHelloPacket(pluginChName, player); - } - } - } - } - - public void firePluginMsgRecievedInternal(byte[] data) { - EaglerXBukkitImpl apiObj = null; - synchronized(this) { - if(openFuture != null) { - try { - handleOpenResult(openFuture, data); - }finally { - openFuture = null; - } - }else if(currentAPI != null) { - apiObj = currentAPI; - } - } - if(apiObj != null) { - handleAPIMessage(apiObj, data); - } - } - - public void firePlayerQuitEventInternal() { - synchronized(this) { - if(openFuture != null) { - try { - openFuture.fireExceptionInternal(new EaglerRPCException("Player quit before the connection could be established!")); - }finally { - openFuture = null; - } - }else if(currentAPI != null) { - currentAPI.fireAPIClosedEventInternal(); - } - } - } - - private void handleOpenResult(EaglerRPCFutureImpl apiFuture, byte[] data) { - EaglerBackendRPCPacket ret; - try { - ByteArrayInputStream bis = new ByteArrayInputStream(data); - ret = EaglerBackendRPCProtocol.INIT.readPacket(new DataInputStream(bis), EaglerBackendRPCProtocol.SERVER_TO_CLIENT); - if(bis.available() > 0) { - throw new IOException("There were " + bis.available() + " bytes available after reading packet \"" + ret.getClass().getSimpleName() + "\"!"); - } - }catch(IOException ex) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, "[" + player.getName() + "] Could not parse incoming RPC packet from bungee/velocity server! (protocol: INIT)", ex); - apiFuture.fireExceptionInternal(ex); - return; - } - if(ret instanceof SPacketRPCEnabledSuccess) { - SPacketRPCEnabledSuccess pkt = (SPacketRPCEnabledSuccess)ret; - if(pkt.selectedRPCProtocol != EaglerBackendRPCProtocol.V1.vers) { - try { - // send raw CPacketRPCDisabled - player.sendPluginMessage(EaglerXBukkitAPIPlugin.getEagler(), pluginChName, new byte[] { 0x03 }); - }finally { - apiFuture.fireExceptionInternal(new EaglerRPCException("Server tried to select an unsupported protocol: " + pkt.selectedRPCProtocol)); - } - }else { - currentAPI = EaglerXBukkitImpl.createFromHandshakeInternal(this, pkt); - apiFuture.fireCompleteInternal(currentAPI); - } - }else if(ret instanceof SPacketRPCEnabledFailure) { - SPacketRPCEnabledFailure pkt = (SPacketRPCEnabledFailure)ret; - String msg = "Server responded with failure code: "; - switch(pkt.failureCode) { - case SPacketRPCEnabledFailure.FAILURE_CODE_NOT_ENABLED: - msg += "FAILURE_CODE_NOT_ENABLED"; - break; - case SPacketRPCEnabledFailure.FAILURE_CODE_NOT_EAGLER_PLAYER: - msg += "FAILURE_CODE_NOT_EAGLER_PLAYER"; - break; - case SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_SERVER: - msg += "FAILURE_CODE_OUTDATED_SERVER"; - break; - case SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_CLIENT: - msg += "FAILURE_CODE_OUTDATED_CLIENT"; - break; - case SPacketRPCEnabledFailure.FAILURE_CODE_INTERNAL_ERROR: - msg += "FAILURE_CODE_INTERNAL_ERROR"; - break; - default: - msg += pkt.failureCode; - break; - } - apiFuture.fireExceptionInternal(new EaglerRPCInitException(pkt.failureCode, msg)); - }else { - EaglerXBukkitAPIPlugin.logger().severe("[" + player.getName() + "] Unknown response type from bungee/velocity to API open request: " + ret.getClass().getSimpleName()); - } - } - - private void handleAPIMessage(EaglerXBukkitImpl apiObj, byte[] data) { - EaglerBackendRPCPacket ret; - try { - ret = apiObj.decodePacket(data); - }catch(IOException ex) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, "[" + player.getName() + "] Could not parse incoming RPC packet from bungee/velocity server! (protocol: " + apiObj.getRPCProtocolVersion() + ")", ex); - return; - } - apiObj.fireAPIPacketRecievedInternal(ret); - } - - public void fireCheckRequestTimeoutsInternal(long now) { - EaglerXBukkitImpl apiObj; - synchronized(this) { - if(openFuture != null) { - if(openFuture.hasExpiredBetter(now)) { - try { - EaglerXBukkitAPIPlugin.logger().warning("[" + player.getName() + "] An RPC open request timed out before it could be completed!"); - openFuture.fireExceptionInternal(new EaglerRPCTimeoutException("The request was not completed in time!")); - }catch(Throwable t) { - EaglerXBukkitAPIPlugin.logger().log(Level.SEVERE, "[" + player.getName() + "] An unhandled exception was thrown while firing request timeout signal!", t); - }finally { - openFuture = null; - } - } - return; - }else { - apiObj = currentAPI; - } - } - if(apiObj != null) { - apiObj.cleanupTimedOutRequests(now); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayInputStream.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayInputStream.java deleted file mode 100644 index 2506bbac..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayInputStream.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.io.IOException; -import java.io.InputStream; - -public class ReusableByteArrayInputStream extends InputStream { - - private volatile byte[] currentBuffer = null; - private int idx = 0; - private int markIDX = 0; - - public void feedBuffer(byte[] b) { - currentBuffer = b; - idx = 0; - markIDX = 0; - } - - @Override - public int read() throws IOException { - if(currentBuffer.length <= idx) throw new IOException("ReusableByteArrayInputStream buffer underflow, no bytes remaining"); - return (int)currentBuffer[idx++] & 0xFF; - } - - @Override - public int read(byte b[], int off, int len) throws IOException { - if(idx + len > currentBuffer.length) { - throw new IOException( - "ReusableByteArrayInputStream buffer underflow, tried to read " + len + " when there are only " - + (currentBuffer.length - idx) + " bytes remaining", - new ArrayIndexOutOfBoundsException(idx + len - 1)); - } - if(off + len > b.length) { - throw new ArrayIndexOutOfBoundsException(off + len - 1); - } - System.arraycopy(currentBuffer, idx, b, off, len); - idx += len; - return len; - } - - public void mark() { - markIDX = idx; - } - - public void reset() { - idx = markIDX; - } - - public int getReaderIndex() { - return idx; - } - - public int available() { - return Math.max(currentBuffer.length - idx, 0); - } - - public void setReaderIndex(int i) { - idx = i; - markIDX = idx; - } - - public boolean markSupported() { - return true; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayOutputStream.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayOutputStream.java deleted file mode 100644 index 61453561..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/ReusableByteArrayOutputStream.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Arrays; - -public class ReusableByteArrayOutputStream extends OutputStream { - - private volatile byte[] currentBuffer = null; - private int idx = 0; - private int originalSize = 0; - - public void feedBuffer(byte[] buf) { - currentBuffer = buf; - idx = 0; - originalSize = buf == null ? 0 : buf.length; - } - - public boolean hasGrown() { - return currentBuffer.length != originalSize; - } - - public byte[] returnBuffer() { - return currentBuffer.length == idx ? currentBuffer : Arrays.copyOf(currentBuffer, idx); - } - - private void growBuffer(int i) { - int ii = currentBuffer.length; - int iii = i - ii; - if(iii > 0) { - int j = ii + (ii >> 1); - while(j < i) { - j += (j >> 1); - } - byte[] n = new byte[j]; - System.arraycopy(currentBuffer, 0, n, 0, ii); - currentBuffer = n; - } - } - - public int getWriterIndex() { - return idx; - } - - public void setWriterIndex(int i) { - idx = i; - } - - @Override - public void write(int b) throws IOException { - if(idx >= currentBuffer.length) { - growBuffer(idx + 1); - } - currentBuffer[idx++] = (byte) b; - } - - @Override - public void write(byte b[], int off, int len) throws IOException { - if(idx + len > currentBuffer.length) { - growBuffer(idx + len); - } - System.arraycopy(b, off, currentBuffer, idx, len); - idx += len; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/SameThreadExecutor.java b/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/SameThreadExecutor.java deleted file mode 100644 index 96415894..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/bukkit_rpc_helper/impl/SameThreadExecutor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.impl; - -import java.util.concurrent.Executor; - -import com.google.common.util.concurrent.MoreExecutors; - -public class SameThreadExecutor { - - public static final Executor SAME_THREAD_EXECUTOR; - - static { - Executor fuck; - try { - fuck = (Executor) MoreExecutors.class.getDeclaredMethod("newDirectExecutorService").invoke(null); - }catch(Throwable t) { - try { - fuck = (Executor) MoreExecutors.class.getDeclaredMethod("sameThreadExecutor").invoke(null); - }catch(Throwable t2) { - throw new RuntimeException("Google fucked up!", t2); - } - } - SAME_THREAD_EXECUTOR = fuck; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBukkitAPI/src/main/resources/plugin.yml b/gateway/EaglercraftXBukkitAPI/src/main/resources/plugin.yml deleted file mode 100644 index 8faf6097..00000000 --- a/gateway/EaglercraftXBukkitAPI/src/main/resources/plugin.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: EaglercraftXBukkitAPI -version: 1.0.1 -main: net.lax1dude.eaglercraft.v1_8.plugin.bukkit_rpc_helper.EaglerXBukkitAPIPlugin -description: Official EaglercraftX API for Bukkit servers -author: lax1dude -api-version: 1.8 \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/.gitignore b/gateway/EaglercraftXBungee/.gitignore deleted file mode 100644 index 341c9c00..00000000 --- a/gateway/EaglercraftXBungee/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -lib/* -.idea/* -*.iml -out/* -deps/BungeeCord.jar -/.gradle/ -/.settings/ -.classpath -.project -/build/ -/bin/ diff --git a/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar b/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar deleted file mode 100644 index ee6f8879..00000000 Binary files a/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar and /dev/null differ diff --git a/gateway/EaglercraftXBungee/build.gradle b/gateway/EaglercraftXBungee/build.gradle deleted file mode 100644 index ee6ba223..00000000 --- a/gateway/EaglercraftXBungee/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -plugins { - id 'java' - id 'eclipse' -} - -group = 'net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord' -version = '' - -repositories { - mavenCentral() -} - -sourceSets { - main { - java { - srcDirs( - 'src/main/java', - '../../sources/protocol-game/java', - '../backend-rpc-protocol/src/backend-rpc-protocol/java' - ) - } - } -} - -dependencies { - implementation files('deps/BungeeCord.jar') -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -jar { - compileJava.options.encoding = 'UTF-8' - javadoc.options.encoding = 'UTF-8' - - manifest { - attributes( - 'Main-Class': 'net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.shit.MainClass' - ) - } -} diff --git a/gateway/EaglercraftXBungee/deps/readme.txt b/gateway/EaglercraftXBungee/deps/readme.txt deleted file mode 100644 index e67b421e..00000000 --- a/gateway/EaglercraftXBungee/deps/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Place the BungeeCord JAR file in this folder, name it "BungeeCord.jar" - -You can download it from here: https://ci.md-5.net/job/BungeeCord/ \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.jar b/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e5832..00000000 Binary files a/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.properties b/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index eb7f6f99..00000000 --- a/gateway/EaglercraftXBungee/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Jun 20 10:14:47 CDT 2024 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gateway/EaglercraftXBungee/gradlew b/gateway/EaglercraftXBungee/gradlew deleted file mode 100644 index 1b6c7873..00000000 --- a/gateway/EaglercraftXBungee/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gateway/EaglercraftXBungee/gradlew.bat b/gateway/EaglercraftXBungee/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/gateway/EaglercraftXBungee/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/gateway/EaglercraftXBungee/readme.txt b/gateway/EaglercraftXBungee/readme.txt deleted file mode 100644 index 73dece37..00000000 --- a/gateway/EaglercraftXBungee/readme.txt +++ /dev/null @@ -1,9 +0,0 @@ -Plugin for eaglercraft on bungeecord - -Not using gradle to give more direct access to bungeecord's internals, as gradle only provides a dummy jar containing the api. - -EaglercraftXBungee requires netty's websocket client/server, which is already in the production bungeecord jar so it's ideal to compile directly against the real jar - -Simply link "src/main/java" and "src/main/resources" as source folders, and then add the latest version of bungeecord jar for minecraft 1.8 to the build path. - -To build, export the source folders as a JAR and export the JAR to contain all the classes found in the JARs in "deps" within it, but not including the classes from the actual bungeecord jar \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/settings.gradle b/gateway/EaglercraftXBungee/settings.gradle deleted file mode 100644 index 25cadfd4..00000000 --- a/gateway/EaglercraftXBungee/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'EaglercraftXBungee' - diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java deleted file mode 100644 index 7fd4d69b..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.logging.Level; -import java.util.logging.Logger; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandClientBrand; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandConfirmCode; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandDomain; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandEaglerPurge; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandEaglerRegister; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandRatelimit; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers.EaglerPacketEventListener; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers.EaglerPluginEventListener; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerUpdateSvc; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpWebServer; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.shit.CompatWarning; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.BinaryHttpClient; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.CapeServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.ISkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.api.plugin.PluginDescription; -import net.md_5.bungee.api.plugin.PluginManager; -import net.md_5.bungee.netty.PipelineUtils; -import net.md_5.bungee.BungeeCord; - -public class EaglerXBungee extends Plugin { - - public static final String NATIVE_BUNGEECORD_BUILD = "1.21-R0.1-SNAPSHOT:0aa2871:1893"; - public static final String NATIVE_BUNGEECORD_BUILD_DL = "https://ci.md-5.net/job/BungeeCord/1893/artifact/bootstrap/target/BungeeCord.jar"; - - public static final String NATIVE_WATERFALL_BUILD = "1.21-R0.1-SNAPSHOT:9ab9e2b:582"; - public static final String NATIVE_WATERFALL_BUILD_DL = "https://api.papermc.io/v2/projects/waterfall/versions/1.21/builds/582/downloads/waterfall-1.21-582.jar"; - - static { - CompatWarning.displayCompatWarning(); - } - - private static EaglerXBungee instance = null; - private EaglerBungeeConfig conf = null; - private EventLoopGroup eventLoopGroup; - private EventLoopGroup eventLoopGroupBoss; - private Collection openChannels; - private Timer closeInactiveConnections = null; - private Timer skinServiceTasks = null; - private Timer authServiceTasks = null; - private Timer updateServiceTasks = null; - private final ChannelFutureListener newChannelListener; - private ISkinService skinService; - private CapeServiceOffline capeService; - private VoiceService voiceService; - private DefaultAuthSystem defaultAuthSystem; - - public EaglerXBungee() { - instance = this; - openChannels = new LinkedList<>(); - newChannelListener = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture ch) throws Exception { - synchronized(openChannels) { // synchronize whole block to preserve logging order - if(ch.isSuccess()) { - EaglerXBungee.logger().info("Eaglercraft is listening on: " + ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get().toString()); - openChannels.add(ch.channel()); - }else { - EaglerXBungee.logger().severe("Eaglercraft could not bind port: " + ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get().toString()); - EaglerXBungee.logger().severe("Reason: " + ch.cause().toString()); - } - } - } - }; - } - - @Override - public void onLoad() { - Map templateGlobals = EaglerXBungeeAPIHelper.getTemplateGlobals(); - PluginDescription desc = this.getDescription(); - templateGlobals.put("plugin_name", desc.getName()); - templateGlobals.put("plugin_version", desc.getVersion()); - templateGlobals.put("plugin_authors", desc.getAuthor()); - templateGlobals.put("plugin_description", desc.getDescription()); - try { - eventLoopGroup = ((BungeeCord) getProxy()).eventLoops; - } catch (NoSuchFieldError e) { - try { - eventLoopGroup = (EventLoopGroup) BungeeCord.class.getField("workerEventLoopGroup").get(getProxy()); - eventLoopGroupBoss = (EventLoopGroup) BungeeCord.class.getField("bossEventLoopGroup").get(getProxy()); - } catch (IllegalAccessException | NoSuchFieldException ex) { - throw new RuntimeException(ex); - } - } - reloadConfig(); - } - - @Override - public void onEnable() { - PluginManager mgr = getProxy().getPluginManager(); - mgr.registerListener(this, new EaglerPluginEventListener(this)); - mgr.registerListener(this, new EaglerPacketEventListener(this)); - mgr.registerCommand(this, new CommandRatelimit()); - mgr.registerCommand(this, new CommandConfirmCode()); - mgr.registerCommand(this, new CommandDomain()); - mgr.registerCommand(this, new CommandClientBrand()); - EaglerAuthConfig authConf = conf.getAuthConfig(); - conf.setCracked(!BungeeCord.getInstance().getConfig().isOnlineMode() || !authConf.isEnableAuthentication()); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - if(!BungeeCord.getInstance().getConfig().isOnlineMode()) { - getLogger().severe("Online mode is set to false! Authentication system has been disabled"); - authConf.triggerOnlineModeDisabled(); - }else { - mgr.registerCommand(this, new CommandEaglerRegister(authConf.getEaglerCommandName())); - mgr.registerCommand(this, new CommandEaglerPurge(authConf.getEaglerCommandName())); - } - } - for(String str : GamePluginMessageProtocol.getAllChannels()) { - getProxy().registerChannel(str); - } - getProxy().registerChannel(EaglerBackendRPCProtocol.CHANNEL_NAME); - getProxy().registerChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_READY); - getProxy().registerChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN); - getProxy().registerChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN); - getProxy().registerChannel(EaglerPacketEventListener.GET_DOMAIN_CHANNEL); - startListeners(); - if(closeInactiveConnections != null) { - closeInactiveConnections.cancel(); - closeInactiveConnections = null; - } - if(skinServiceTasks != null) { - skinServiceTasks.cancel(); - skinServiceTasks = null; - } - closeInactiveConnections = new Timer("EaglerXBungee: Network Tick Tasks"); - closeInactiveConnections.scheduleAtFixedRate(EaglerPipeline.closeInactive, 0l, 250l); - boolean downloadSkins = conf.getDownloadVanillaSkins(); - if(downloadSkins) { - if(skinService == null) { - skinService = new SkinService(); - }else if(skinService instanceof SkinServiceOffline) { - skinService.shutdown(); - skinService = new SkinService(); - } - } else { - if(skinService == null) { - skinService = new SkinServiceOffline(); - }else if(skinService instanceof SkinService) { - skinService.shutdown(); - skinService = new SkinServiceOffline(); - } - } - skinService.init(conf.getSkinCacheURI(), conf.getSQLiteDriverClass(), conf.getSQLiteDriverPath(), - conf.getKeepObjectsDays(), conf.getKeepProfilesDays(), conf.getMaxObjects(), conf.getMaxProfiles()); - if(skinService instanceof SkinService) { - skinServiceTasks = new Timer("EaglerXBungee: Skin Service Tasks"); - skinServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - skinService.flush(); - }catch(Throwable t) { - logger().log(Level.SEVERE, "Error flushing skin cache!", t); - } - } - }, 1000l, 1000l); - } - capeService = new CapeServiceOffline(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - try { - defaultAuthSystem = DefaultAuthSystem.initializeAuthSystem(authConf); - }catch(DefaultAuthSystem.AuthSystemException ex) { - logger().log(Level.SEVERE, "Could not load authentication system!", ex); - } - if(defaultAuthSystem != null) { - authServiceTasks = new Timer("EaglerXBungee: Auth Service Tasks"); - authServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - defaultAuthSystem.flush(); - }catch(Throwable t) { - logger().log(Level.SEVERE, "Error flushing auth cache!", t); - } - } - }, 60000l, 60000l); - } - } - if(conf.getEnableVoiceChat()) { - voiceService = new VoiceService(conf); - logger().warning("Voice chat enabled, not recommended for public servers!"); - }else { - logger().info("Voice chat disabled, add \"allow_voice: true\" to your listeners to enable"); - } - if(updateServiceTasks != null) { - updateServiceTasks.cancel(); - updateServiceTasks = null; - } - if(!conf.getUpdateConfig().isBlockAllClientUpdates()) { - updateServiceTasks = new Timer("EaglerXBungee: Update Service Tasks"); - updateServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - EaglerUpdateSvc.updateTick(); - }catch(Throwable t) { - logger().log(Level.SEVERE, "Error ticking update service!", t); - } - } - }, 0l, 5000l); - } - } - - @Override - public void onDisable() { - stopListeners(); - PluginManager mgr = getProxy().getPluginManager(); - mgr.unregisterListeners(this); - mgr.unregisterCommands(this); - for(String str : GamePluginMessageProtocol.getAllChannels()) { - getProxy().unregisterChannel(str); - } - getProxy().unregisterChannel(EaglerBackendRPCProtocol.CHANNEL_NAME); - getProxy().unregisterChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_READY); - getProxy().unregisterChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN); - getProxy().unregisterChannel(EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN); - getProxy().unregisterChannel(EaglerPacketEventListener.GET_DOMAIN_CHANNEL); - if(closeInactiveConnections != null) { - closeInactiveConnections.cancel(); - closeInactiveConnections = null; - } - if(skinServiceTasks != null) { - skinServiceTasks.cancel(); - skinServiceTasks = null; - } - if(updateServiceTasks != null) { - updateServiceTasks.cancel(); - updateServiceTasks = null; - } - if(skinService != null) { - skinService.shutdown(); - skinService = null; - } - if(capeService != null) { - capeService.shutdown(); - capeService = null; - } - if(defaultAuthSystem != null) { - defaultAuthSystem.destroy(); - defaultAuthSystem = null; - if(authServiceTasks != null) { - authServiceTasks.cancel(); - authServiceTasks = null; - } - } - voiceService = null; - BinaryHttpClient.killEventLoop(); - } - - public void reload() { - stopListeners(); - reloadConfig(); - startListeners(); - } - - private void reloadConfig() { - try { - conf = EaglerBungeeConfig.loadConfig(getDataFolder()); - if(conf == null) { - throw new IOException("Config failed to parse!"); - } - conf.setCracked(!BungeeCord.getInstance().getConfig().isOnlineMode() || !conf.getAuthConfig().isEnableAuthentication()); - HttpWebServer.regenerate404Pages(); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - public void startListeners() { - for(EaglerListenerConfig conf : conf.getServerListeners()) { - if(conf.getAddress() != null) { - makeListener(conf, conf.getAddress()); - } - if(conf.getAddressV6() != null) { - makeListener(conf, conf.getAddressV6()); - } - } - } - - private void makeListener(EaglerListenerConfig confData, InetSocketAddress addr) { - ServerBootstrap bootstrap = new ServerBootstrap(); - bootstrap.option(ChannelOption.SO_REUSEADDR, true) - .childOption(ChannelOption.TCP_NODELAY, true) - .channel(PipelineUtils.getServerChannel(addr)); - if(eventLoopGroupBoss != null) { - bootstrap.group(eventLoopGroupBoss, eventLoopGroup); - }else { - bootstrap.group(eventLoopGroup); - } - bootstrap.childAttr(EaglerPipeline.LISTENER, confData) - .attr(EaglerPipeline.LOCAL_ADDRESS, addr) - .localAddress(addr) - .childHandler(EaglerPipeline.SERVER_CHILD) - .bind().addListener(newChannelListener); - } - - public void stopListeners() { - synchronized(openChannels) { - for(Channel c : openChannels) { - c.close().syncUninterruptibly(); - EaglerXBungee.logger().info("Eaglercraft listener closed: " + c.attr(EaglerPipeline.LOCAL_ADDRESS).get().toString()); - } - openChannels.clear(); - } - synchronized(EaglerPipeline.openChannels) { - EaglerPipeline.openChannels.clear(); - } - } - - public EaglerBungeeConfig getConfig() { - return conf; - } - - public EventLoopGroup getEventLoopGroup() { - return eventLoopGroup; - } - - public ISkinService getSkinService() { - return skinService; - } - - public CapeServiceOffline getCapeService() { - return capeService; - } - - public DefaultAuthSystem getAuthService() { - return defaultAuthSystem; - } - - public VoiceService getVoiceService() { - return voiceService; - } - - public static EaglerXBungee getEagler() { - return instance; - } - - public static Logger logger() { - return instance.getLogger(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EaglerXBungeeAPIHelper.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EaglerXBungeeAPIHelper.java deleted file mode 100644 index f6fd4ebe..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EaglerXBungeeAPIHelper.java +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.zip.GZIPOutputStream; - -import javax.imageio.ImageIO; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.SHA1Digest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.ServerInfoTemplateParser; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.CapeServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.ISkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinRescaler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketEnableFNAWSkinsEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketInvalidatePlayerCacheV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV3EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketServerInfoDataChunkV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUnforceClientV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.connection.Server; - -public class EaglerXBungeeAPIHelper { - - public static EaglerXBungee getEaglerXBungee() { - return EaglerXBungee.getEagler(); - } - - public static EaglerInitialHandler getEaglerHandle(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? (EaglerInitialHandler)conn : null; - } - - public static EaglerInitialHandler getEaglerHandle(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? (EaglerInitialHandler)conn : null; - } - - public static boolean isEaglerPlayer(ProxiedPlayer player) { - return player.getPendingConnection() instanceof EaglerInitialHandler; - } - - public static boolean isEaglerPlayer(PendingConnection conn) { - return conn instanceof EaglerInitialHandler; - } - - public static ProxiedPlayer getPlayer(PendingConnection conn) { - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - GameProtocolMessageController controller = initialHandler.getEaglerMessageController(); - if(controller != null) { - return controller.getUserConnection(); - }else { - return initialHandler.ch.getHandle().attr(EaglerPipeline.CONNECTION_INSTANCE).get().userConnection; - } - }else { - return null; - } - } - - public static final UUID BRAND_NULL_UUID = new UUID(0l, 0l); - public static final UUID BRAND_PENDING_UUID = new UUID(0x6969696969696969l, 0x6969696969696969l); - public static final UUID BRAND_VANILLA_UUID = new UUID(0x1DCE015CD384374El, 0x85030A4DE95E5736l); - - public static final UUID BRAND_EAGLERCRAFTX_V4_UUID = makeClientBrandUUID("EaglercraftX"); - public static final UUID BRAND_EAGLERCRAFTX_LEGACY_UUID = makeClientBrandUUIDLegacy("EaglercraftX"); - - public static UUID makeClientBrandUUID(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClient:" + name).getBytes(StandardCharsets.UTF_8)); - } - - public static UUID makeClientBrandUUIDLegacy(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8)); - } - - public static UUID getClientBrandUUID(ProxiedPlayer player) { - if(player == null) { - return BRAND_NULL_UUID; - } - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - UUID ret = ((EaglerInitialHandler)conn).getClientBrandUUID(); - if(ret != null) { - return ret; - }else { - return BRAND_NULL_UUID; - } - }else { - return BRAND_VANILLA_UUID; - } - } - - public static UUID getClientBrandUUID(PendingConnection conn) { - if(conn == null) { - return BRAND_NULL_UUID; - } - if(conn instanceof EaglerInitialHandler) { - UUID ret = ((EaglerInitialHandler)conn).getClientBrandUUID(); - if(ret != null) { - return ret; - }else { - return BRAND_NULL_UUID; - } - }else { - return BRAND_VANILLA_UUID; - } - } - - public static String getClientVersionString(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerVersionString() : null; - } - - public static String getClientVersionString(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerVersionString() : null; - } - - public static String getClientBrandString(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerBrandString() : null; - } - - public static String getClientBrandString(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerBrandString() : null; - } - - public static String getClientOrigin(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getOrigin() : null; - } - - public static String getClientOrigin(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getOrigin() : null; - } - - public static String getClientUserAgent(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getUserAgent() : null; - } - - public static String getClientUserAgent(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getUserAgent() : null; - } - - public static boolean getCookieAllowed(ProxiedPlayer player) { - if(player == null) { - return false; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).getCookieAllowed(); - } - - public static boolean getCookieAllowed(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).getCookieAllowed(); - } - - public static byte[] getCookieData(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getCookieData() : null; - } - - public static byte[] getCookieData(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getCookieData() : null; - } - - public static String getCookieDataString(ProxiedPlayer player) { - byte[] ret = getCookieData(player); - return ret != null ? new String(ret, StandardCharsets.UTF_8) : null; - } - - public static String getCookieDataString(PendingConnection conn) { - byte[] ret = getCookieData(conn); - return ret != null ? new String(ret, StandardCharsets.UTF_8) : null; - } - - public static void setCookieDataString(ProxiedPlayer player, String data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieDataString(ProxiedPlayer player, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieDataString(ProxiedPlayer player, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieDataString(ProxiedPlayer player, String data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player.getPendingConnection(), data != null ? data.getBytes(StandardCharsets.UTF_8) : null, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieDataString(PendingConnection conn, String data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieDataString(PendingConnection conn, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieDataString(PendingConnection conn, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieDataString(PendingConnection conn, String data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(ProxiedPlayer player, byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieData(ProxiedPlayer player, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieData(ProxiedPlayer player, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(ProxiedPlayer player, byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player.getPendingConnection(), data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(PendingConnection conn, byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieData(PendingConnection conn, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieData(PendingConnection conn, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(PendingConnection conn, byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).setCookieData(data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - }else { - throw new UnsupportedOperationException("Can't set cookies on vanilla players!"); - } - } - - public static void clearCookieData(ProxiedPlayer player) { - setCookieData(player.getPendingConnection(), (byte[])null, 0, false, false); - } - - public static void clearCookieData(PendingConnection conn) { - setCookieData(conn, (byte[])null, 0, false, false); - } - - public static boolean getRedirectSupported(ProxiedPlayer player) { - return getRedirectSupported(player.getPendingConnection()); - } - - public static boolean getRedirectSupported(PendingConnection player) { - return (player instanceof EaglerInitialHandler) && ((EaglerInitialHandler)player).redirectToWebSocketSupported(); - } - - public static void redirectPlayerToWebSocket(ProxiedPlayer player, String serverAddress) { - redirectPlayerToWebSocket(player.getPendingConnection(), serverAddress); - } - - public static void redirectPlayerToWebSocket(PendingConnection conn, String serverAddress) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).redirectPlayerToWebSocket(serverAddress); - }else { - throw new UnsupportedOperationException("Can't redirect vanilla players to websocket addresses!"); - } - } - - public static byte[] loadCustomSkinFromImage(File phile) throws IOException { - try(FileInputStream is = new FileInputStream(phile)) { - return loadCustomSkinFromImage(is); - } - } - - public static byte[] loadCustomCapeFromImage(File phile) throws IOException { - try(FileInputStream is = new FileInputStream(phile)) { - return loadCustomCapeFromImage(is); - } - } - - public static byte[] loadCustomSkinFromImage(InputStream phile) throws IOException { - return loadCustomSkinFromImage(ImageIO.read(phile)); - } - - public static byte[] loadCustomCapeFromImage(InputStream phile) throws IOException { - return loadCustomCapeFromImage(ImageIO.read(phile)); - } - - public static byte[] loadCustomSkinFromImage(BufferedImage img) throws IOException { - if(img.getWidth() != 64 || (img.getHeight() != 32 && img.getHeight() != 64)) { - throw new IOException("Invalid image dimensions!"); - } - byte[] ret = new byte[16384]; - if(img.getHeight() == 32) { - int[] pixels = new int[2048]; - img.getRGB(0, 0, 64, 32, pixels, 0, 64); - SkinRescaler.convert64x32To64x64(pixels, ret); - }else { - int[] pixels = new int[4096]; - img.getRGB(0, 0, 64, 64, pixels, 0, 64); - SkinRescaler.convertToBytes(pixels, ret); - } - return ret; - } - - public static byte[] loadCustomCapeFromImage(BufferedImage img) throws IOException { - if(img.getHeight() != 32 || (img.getWidth() != 32 && img.getWidth() != 64)) { - throw new IOException("Invalid image dimensions!"); - } - int[] pixels = new int[1024]; - img.getRGB(0, 0, 32, 32, pixels, 0, 32); - byte[] ret = new byte[4096]; - SkinRescaler.convertToBytes(pixels, ret); - return ret; - } - - public static void changePlayerSkinPreset(ProxiedPlayer player, int presetId, boolean notifyOtherPlayers) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - UUID uuid = initialHandler.getUniqueId(); - ISkinService svc = EaglerXBungee.getEagler().getSkinService(); - if(initialHandler.originalSkin == null) { - initialHandler.originalSkin = svc.getSkin(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherSkinPresetEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), presetId); - svc.registerEaglercraftPlayer(uuid, new SkinPacketVersionCache(replacement, replacement), -1); - if(initialHandler.getEaglerProtocol().ver >= 4) { - svc.processForceSkin(uuid, initialHandler); - } - if(notifyOtherPlayers) { - Server svr = player.getServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(true, false, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(ProxiedPlayer otherPlayer : svr.getInfo().getPlayers()) { - if(player != otherPlayer) { - PendingConnection otherConn = otherPlayer.getPendingConnection(); - if(otherConn instanceof EaglerInitialHandler) { - EaglerInitialHandler otherConnEag = (EaglerInitialHandler)otherConn; - if(otherConnEag.getEaglerProtocol().ver >= 4) { - otherConnEag.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerSkinCustom(ProxiedPlayer player, int modelId, byte[] texture, boolean notifyOtherPlayers) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - UUID uuid = initialHandler.getUniqueId(); - ISkinService svc = EaglerXBungee.getEagler().getSkinService(); - if(initialHandler.originalSkin == null) { - initialHandler.originalSkin = svc.getSkin(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherSkinCustomV3EAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), modelId, texture); - svc.registerEaglercraftPlayer(uuid, new SkinPacketVersionCache(replacement, null), modelId); - if(initialHandler.getEaglerProtocol().ver >= 4) { - svc.processForceSkin(uuid, initialHandler); - } - if(notifyOtherPlayers) { - Server svr = player.getServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(true, false, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(ProxiedPlayer otherPlayer : svr.getInfo().getPlayers()) { - if(player != otherPlayer) { - PendingConnection otherConn = otherPlayer.getPendingConnection(); - if(otherConn instanceof EaglerInitialHandler) { - EaglerInitialHandler otherConnEag = (EaglerInitialHandler)otherConn; - if(otherConnEag.getEaglerProtocol().ver >= 4) { - otherConnEag.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerCapePreset(ProxiedPlayer player, int presetId, boolean notifyOtherPlayers) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - UUID uuid = initialHandler.getUniqueId(); - CapeServiceOffline svc = EaglerXBungee.getEagler().getCapeService(); - if(initialHandler.originalCape == null) { - initialHandler.originalCape = svc.getCape(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherCapePresetEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), presetId); - svc.registerEaglercraftPlayer(uuid, replacement); - if(initialHandler.getEaglerProtocol().ver >= 4) { - svc.processForceCape(uuid, initialHandler); - } - if(notifyOtherPlayers) { - Server svr = player.getServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(false, true, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(ProxiedPlayer otherPlayer : svr.getInfo().getPlayers()) { - if(player != otherPlayer) { - PendingConnection otherConn = otherPlayer.getPendingConnection(); - if(otherConn instanceof EaglerInitialHandler) { - EaglerInitialHandler otherConnEag = (EaglerInitialHandler)otherConn; - if(otherConnEag.getEaglerProtocol().ver >= 4) { - otherConnEag.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerCapeCustom(ProxiedPlayer player, byte[] texture, boolean notifyOtherPlayers) { - changePlayerCapeCustom(player, texture, false, notifyOtherPlayers); - } - - public static void changePlayerCapeCustom(ProxiedPlayer player, byte[] texture, boolean compressedFormat, boolean notifyOtherPlayers) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - UUID uuid = initialHandler.getUniqueId(); - CapeServiceOffline svc = EaglerXBungee.getEagler().getCapeService(); - if(initialHandler.originalCape == null) { - initialHandler.originalCape = svc.getCape(uuid); - } - svc.unregisterPlayer(uuid); - byte[] capeTex; - if(compressedFormat) { - capeTex = texture; - }else { - capeTex = new byte[1173]; - convertCape32x32RGBAto23x17RGB(texture, capeTex); - } - GameMessagePacket replacement = new SPacketOtherCapeCustomEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), capeTex); - svc.registerEaglercraftPlayer(uuid, replacement); - if(initialHandler.getEaglerProtocol().ver >= 4) { - svc.processForceCape(uuid, initialHandler); - } - if(notifyOtherPlayers) { - Server svr = player.getServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(false, true, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(ProxiedPlayer otherPlayer : svr.getInfo().getPlayers()) { - if(player != otherPlayer) { - PendingConnection otherConn = otherPlayer.getPendingConnection(); - if(otherConn instanceof EaglerInitialHandler) { - EaglerInitialHandler otherConnEag = (EaglerInitialHandler)otherConn; - if(otherConnEag.getEaglerProtocol().ver >= 4) { - otherConnEag.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setEnableFNAWSkins(ProxiedPlayer player, boolean enable) { - setEnableFNAWSkins(player.getPendingConnection(), enable); - } - - public static void setEnableFNAWSkins(PendingConnection conn, boolean enable) { - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - if(enable != initialHandler.currentFNAWSkinEnableStatus.getAndSet(enable)) { - initialHandler.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(enable, initialHandler.currentFNAWSkinForceStatus.get())); - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setForceFNAWSkins(ProxiedPlayer player, boolean force) { - setForceFNAWSkins(player.getPendingConnection(), force); - } - - public static void setForceFNAWSkins(PendingConnection conn, boolean force) { - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - if(force != initialHandler.currentFNAWSkinForceStatus.getAndSet(force)) { - initialHandler.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(initialHandler.currentFNAWSkinEnableStatus.get(), force)); - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setEnableForceFNAWSkins(ProxiedPlayer player, boolean enable, boolean force) { - setForceFNAWSkins(player.getPendingConnection(), force); - } - - public static void setEnableForceFNAWSkins(PendingConnection conn, boolean enable, boolean force) { - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - if ((enable != initialHandler.currentFNAWSkinEnableStatus.getAndSet(enable)) - | (force != initialHandler.currentFNAWSkinForceStatus.getAndSet(force))) { - initialHandler.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(enable, force)); - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, byte[] skinOut) { - convertCape32x32RGBAto23x17RGB(skinIn, 0, skinOut, 0); - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = inOffset + ((y * 32 + x) << 2); - j = outOffset + ((y * 23 + x) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - for(int y = 0; y < 11; ++y) { - i = inOffset + (((y + 11) * 32 + 22) << 2); - j = outOffset + (((y + 6) * 23 + 22) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, byte[] skinOut) { - convertCape23x17RGBto32x32RGBA(skinIn, 0, skinOut, 0); - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = outOffset + ((y * 32 + x) << 2); - j = inOffset + ((y * 23 + x) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - for(int y = 0; y < 11; ++y) { - i = outOffset + (((y + 11) * 32 + 22) << 2); - j = inOffset + (((y + 6) * 23 + 22) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - - public static void resetPlayerSkin(ProxiedPlayer player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, true, false, false, notifyOtherPlayers); - } - - public static void resetPlayerCape(ProxiedPlayer player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, false, true, false, notifyOtherPlayers); - } - - public static void resetPlayerSkinAndCape(ProxiedPlayer player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, true, true, false, notifyOtherPlayers); - } - - public static void resetPlayerMulti(ProxiedPlayer player, boolean resetSkin, boolean resetCape, boolean resetForceFNAWSkins, boolean notifyOtherPlayers) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - UUID uuid = initialHandler.getUniqueId(); - boolean notifyResetSkin = false; - boolean notifyResetCape = false; - if(resetSkin) { - if(initialHandler.originalSkin != null) { - notifyResetSkin = true; - ISkinService svc = EaglerXBungee.getEagler().getSkinService(); - svc.unregisterPlayer(uuid); - svc.registerEaglercraftPlayer(uuid, initialHandler.originalSkin, initialHandler.originalSkin.getModelId()); - } - } - if(resetCape) { - if(initialHandler.originalCape != null) { - notifyResetCape = true; - CapeServiceOffline svc = EaglerXBungee.getEagler().getCapeService(); - svc.unregisterPlayer(uuid); - svc.registerEaglercraftPlayer(uuid, initialHandler.originalCape); - } - } - if(resetForceFNAWSkins) { - initialHandler.currentFNAWSkinForceStatus.set(false); - } - if(initialHandler.getEaglerProtocol().ver >= 4) { - initialHandler.sendEaglerMessage(new SPacketUnforceClientV4EAG(resetSkin, resetCape, resetForceFNAWSkins)); - } - if(notifyOtherPlayers && (notifyResetSkin || notifyResetCape)) { - Server svr = player.getServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(notifyResetSkin, notifyResetCape, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(ProxiedPlayer otherPlayer : svr.getInfo().getPlayers()) { - if(player != otherPlayer) { - PendingConnection otherConn = otherPlayer.getPendingConnection(); - if(otherConn instanceof EaglerInitialHandler) { - EaglerInitialHandler otherConnEag = (EaglerInitialHandler)otherConn; - if(otherConnEag.getEaglerProtocol().ver >= 4) { - otherConnEag.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static EnumVoiceState getClientVoiceState(ProxiedPlayer player) { - if(player == null) { - return EnumVoiceState.SERVER_DISABLE; - } - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)conn; - VoiceService svc = EaglerXBungee.getEagler().getVoiceService(); - if(svc != null && initialHandler.getEaglerListenerConfig().getEnableVoiceChat()) { - Server svr = player.getServer(); - if(svr != null) { - return svc.getPlayerVoiceState(initialHandler.getUniqueId(), svr.getInfo()); - }else { - return EnumVoiceState.SERVER_DISABLE; - } - }else { - return EnumVoiceState.SERVER_DISABLE; - } - }else { - return EnumVoiceState.SERVER_DISABLE; - } - } - - public static List convertServerInfoToChunks(String rawData, byte[] hashReturn) throws IOException { - return convertServerInfoToChunks(rawData.getBytes(StandardCharsets.UTF_8), hashReturn, 24576); - } - - public static List convertServerInfoToChunks(byte[] rawData, byte[] hashReturn) throws IOException { - return convertServerInfoToChunks(rawData, hashReturn, 24576); - } - - public static List convertServerInfoToChunks(byte[] rawData, byte[] hashReturn, int chunkSize) throws IOException { - if(hashReturn.length != 20) { - throw new IllegalArgumentException("Hash return array must be 20 bytes long!"); - } - - SHA1Digest digest = new SHA1Digest(); - digest.update(rawData, 0, rawData.length); - digest.doFinal(hashReturn, 0); - - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - bao.write((rawData.length >>> 24) & 0xFF); - bao.write((rawData.length >>> 16) & 0xFF); - bao.write((rawData.length >>> 8) & 0xFF); - bao.write(rawData.length & 0xFF); - - try(OutputStream os = new GZIPOutputStream(bao)) { - os.write(rawData); - } - - byte[] toFragment = bao.toByteArray(); - - int i = 0, j = 0, k = 0; - List ret = new ArrayList<>(); - while(i < toFragment.length) { - j = Math.min(toFragment.length - i, chunkSize); - byte[] chunk = new byte[j]; - System.arraycopy(toFragment, i, chunk, 0, j); - ret.add(new SPacketServerInfoDataChunkV4EAG(i + j == toFragment.length, k++, hashReturn, toFragment.length, chunk)); - i += j; - } - - return ret; - } - - public static String loadFileToStringServerInfo(File serverInfoFile) throws IOException { - return new String(loadFileToByteArrayServerInfo(serverInfoFile), StandardCharsets.UTF_8); - } - - public static byte[] loadFileToByteArrayServerInfo(File serverInfoFile) throws IOException { - long ll = serverInfoFile.length(); - if(ll > 0x2000000l) { - throw new IOException("File is too large: " + serverInfoFile.getAbsolutePath()); - } - int expectLen = (int)ll; - if(expectLen <= 0) { - expectLen = 1024; - } - ByteArrayOutputStream bao = new ByteArrayOutputStream(expectLen); - byte[] copyBuffer = new byte[Math.min(expectLen, 1024)]; - try(InputStream is = new FileInputStream(serverInfoFile)) { - int i; - while((i = is.read(copyBuffer)) != -1) { - bao.write(copyBuffer, 0, i); - } - } - return bao.toByteArray(); - } - - public static String loadServerInfoTemplateEagler(File serverInfoFile, File baseDir, boolean allowEvalMacro) throws IOException { - return loadServerInfoTemplateEagler(serverInfoFile, serverInfoFile.getParentFile(), allowEvalMacro); - } - - public static String loadServerInfoTemplateEagler(File serverInfoFile, boolean allowEvalMacro) throws IOException { - return loadServerInfoTemplateEagler(serverInfoFile, serverInfoFile.getParentFile(), allowEvalMacro); - } - - public static String loadServerInfoTemplateEagler(String serverInfoFile, File baseDir, boolean allowEvalMacro) throws IOException { - return ServerInfoTemplateParser.loadTemplate(serverInfoFile, baseDir, allowEvalMacro, templateGlobals); - } - - private static final Map templateGlobals = new ConcurrentHashMap<>(); - - public static Map getTemplateGlobals() { - return templateGlobals; - } - - public static boolean getWebViewSupport(ProxiedPlayer player) { - if(player == null) { - return false; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getWebViewSupport() : null; - } - - public static boolean getWebViewSupport(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).getWebViewSupport(); - } - - public static boolean getWebViewMessageChannelOpen(ProxiedPlayer player) { - if(player == null) { - return false; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).getWebViewMessageChannelOpen(); - } - - public static boolean getWebViewMessageChannelOpen(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).getWebViewMessageChannelOpen(); - } - - public static String getWebViewMessageChannelName(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getWebViewMessageChannelName() : null; - } - - public static String getWebViewMessageChannelName(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getWebViewMessageChannelName() : null; - } - - public static boolean checkCurrentWebViewChannelIsOpen(ProxiedPlayer player, String channelName) { - if(player == null) { - return false; - } - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)conn; - return eaglerHandler.getWebViewMessageChannelOpen() && channelName.equals(eaglerHandler.getWebViewMessageChannelName()); - }else { - return false; - } - } - - public static boolean checkCurrentWebViewChannelIsOpen(PendingConnection conn, String channelName) { - if(conn == null) { - return false; - } - if(conn instanceof EaglerInitialHandler) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)conn; - return eaglerHandler.getWebViewMessageChannelOpen() && channelName.equals(eaglerHandler.getWebViewMessageChannelName()); - }else { - return false; - } - } - - public static void sendWebViewMessagePacket(ProxiedPlayer player, String str) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendWebViewMessage(str); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendWebViewMessagePacket(PendingConnection conn, String str) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendWebViewMessage(str); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendWebViewMessagePacket(ProxiedPlayer player, byte[] data) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendWebViewMessage(data); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendWebViewMessagePacket(PendingConnection conn, byte[] data) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendWebViewMessage(data); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static EnumWebViewState getWebViewState(ProxiedPlayer player) { - if(player == null) { - return EnumWebViewState.NOT_SUPPORTED; - } - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - return ((EaglerInitialHandler)conn).getWebViewState(); - }else { - return EnumWebViewState.NOT_SUPPORTED; - } - } - - public static EnumWebViewState getWebViewState(PendingConnection conn) { - if(conn == null) { - return EnumWebViewState.NOT_SUPPORTED; - } - if(conn instanceof EaglerInitialHandler) { - return ((EaglerInitialHandler)conn).getWebViewState(); - }else { - return EnumWebViewState.NOT_SUPPORTED; - } - } - - public static PacketImageData loadPacketImageData(File img) throws IOException { - return loadPacketImageData(ImageIO.read(img), 255, 255); - } - - public static PacketImageData loadPacketImageData(File img, int maxWidth, int maxHeight) throws IOException { - return loadPacketImageData(ImageIO.read(img), maxWidth, maxHeight); - } - - public static PacketImageData loadPacketImageData(BufferedImage img) { - return loadPacketImageData(img, 255, 255); - } - - public static PacketImageData loadPacketImageData(BufferedImage img, int maxWidth, int maxHeight) { - int w = img.getWidth(); - int h = img.getHeight(); - if(w > maxWidth || h > maxHeight) { - float aspectRatio = (float)w / (float)h; - int nw, nh; - if(aspectRatio >= 1.0f) { - nw = (int)(maxWidth / aspectRatio); - nh = maxHeight; - }else { - nw = maxWidth; - nh = (int)(maxHeight * aspectRatio); - } - BufferedImage resized = new BufferedImage(nw, nh, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) resized.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, nw, nh); - g.drawImage(img, 0, 0, nw, nh, 0, 0, w, h, null); - g.dispose(); - img = resized; - } - int[] pixels = new int[w * h]; - img.getRGB(0, 0, w, h, pixels, 0, w); - return new PacketImageData(w, h, pixels); - } - - public static boolean canSendNotificationsTo(ProxiedPlayer player) { - if(player == null) { - return false; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).notificationSupported(); - } - - public static boolean canSendNotificationsTo(PendingConnection conn) { - return conn != null && (conn instanceof EaglerInitialHandler) && ((EaglerInitialHandler)conn).notificationSupported(); - } - - public static void registerNotificationIcon(ProxiedPlayer player, UUID uuid, PacketImageData imageData) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).registerNotificationIcon(uuid, imageData); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void registerNotificationIcon(PendingConnection conn, UUID uuid, PacketImageData imageData) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).registerNotificationIcon(uuid, imageData); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void registerNotificationIcons(ProxiedPlayer player, Map imageDatas) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).registerNotificationIcons(imageDatas); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void registerNotificationIcons(PendingConnection conn, Map imageDatas) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).registerNotificationIcons(imageDatas); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(ProxiedPlayer player, NotificationBadgeBuilder badgeBuilder) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).showNotificationBadge(badgeBuilder); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(PendingConnection conn, NotificationBadgeBuilder badgeBuilder) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).showNotificationBadge(badgeBuilder); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(ProxiedPlayer player, SPacketNotifBadgeShowV4EAG badgePacket) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).showNotificationBadge(badgePacket); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(PendingConnection conn, SPacketNotifBadgeShowV4EAG badgePacket) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).showNotificationBadge(badgePacket); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void hideNotificationBadge(ProxiedPlayer player, UUID badgeUUID) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).hideNotificationBadge(badgeUUID); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void hideNotificationBadge(PendingConnection conn, UUID badgeUUID) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).hideNotificationBadge(badgeUUID); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcon(ProxiedPlayer player, UUID uuid) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).releaseNotificationIcon(uuid); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcon(PendingConnection conn, UUID uuid) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).releaseNotificationIcon(uuid); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcons(ProxiedPlayer player, Collection uuids) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).releaseNotificationIcons(uuids); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcons(PendingConnection conn, Collection uuids) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler) conn).releaseNotificationIcons(uuids); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static int getEaglerProtocolVersion(ProxiedPlayer player) { - if(player == null) { - return -1; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerProtocolHandshake() : -1; - } - - public static int getEaglerProtocolVersion(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerProtocolHandshake() : -1; - } - - public static GamePluginMessageProtocol getMessageProtocolVersion(ProxiedPlayer player) { - if(player == null) { - return null; - } - PendingConnection conn = player.getPendingConnection(); - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerProtocol() : null; - } - - public static GamePluginMessageProtocol getMessageProtocolVersion(PendingConnection conn) { - return (conn instanceof EaglerInitialHandler) ? ((EaglerInitialHandler)conn).getEaglerProtocol() : null; - } - - public static void sendEaglerMessagePacket(ProxiedPlayer player, GameMessagePacket packet) { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendEaglerMessage(packet); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendEaglerMessagePacket(PendingConnection conn, GameMessagePacket packet) { - if(conn instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)conn).sendEaglerMessage(packet); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static long steadyTimeMillis() { - return System.nanoTime() / 1000000l; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumVoiceState.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumVoiceState.java deleted file mode 100644 index 4ceb3165..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumVoiceState.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api; - -public enum EnumVoiceState { - SERVER_DISABLE, - DISABLED, - ENABLED; -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumWebViewState.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumWebViewState.java deleted file mode 100644 index 42e89be3..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/EnumWebViewState.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api; - -public enum EnumWebViewState { - NOT_SUPPORTED, - SERVER_DISABLE, - CHANNEL_CLOSED, - CHANNEL_OPEN; -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/NotificationBadgeBuilder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/NotificationBadgeBuilder.java deleted file mode 100644 index 558470fe..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/NotificationBadgeBuilder.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG.EnumBadgePriority; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.chat.ComponentSerializer; - -public class NotificationBadgeBuilder { - - public static enum BadgePriority { - LOW, NORMAL, HIGHER, HIGHEST; - } - - private UUID badgeUUID = null; - private BaseComponent bodyComponent = null; - private BaseComponent titleComponent = null; - private BaseComponent sourceComponent = null; - private long originalTimestampSec = 0l; - private boolean silent = false; - private BadgePriority priority = BadgePriority.NORMAL; - private UUID mainIconUUID = null; - private UUID titleIconUUID = null; - private int hideAfterSec = 10; - private int expireAfterSec = 3600; - private int backgroundColor = 0xFFFFFF; - private int bodyTxtColor = 0xFFFFFF; - private int titleTxtColor = 0xFFFFFF; - private int sourceTxtColor = 0xFFFFFF; - - private SPacketNotifBadgeShowV4EAG packetCache = null; - private boolean packetDirty = true; - - public NotificationBadgeBuilder() { - originalTimestampSec = System.currentTimeMillis() / 1000l; - } - - public NotificationBadgeBuilder(NotificationBadgeBuilder builder) { - badgeUUID = builder.badgeUUID; - bodyComponent = builder.bodyComponent; - titleComponent = builder.titleComponent; - sourceComponent = builder.sourceComponent; - originalTimestampSec = builder.originalTimestampSec; - silent = builder.silent; - priority = builder.priority; - mainIconUUID = builder.mainIconUUID; - titleIconUUID = builder.titleIconUUID; - hideAfterSec = builder.hideAfterSec; - backgroundColor = builder.backgroundColor; - bodyTxtColor = builder.bodyTxtColor; - titleTxtColor = builder.titleTxtColor; - sourceTxtColor = builder.sourceTxtColor; - packetCache = !builder.packetDirty ? builder.packetCache : null; - packetDirty = builder.packetDirty; - } - - public NotificationBadgeBuilder(SPacketNotifBadgeShowV4EAG packet) { - badgeUUID = new UUID(packet.badgeUUIDMost, packet.badgeUUIDLeast); - try { - bodyComponent = ComponentSerializer.deserialize(packet.bodyComponent); - }catch(Throwable t) { - bodyComponent = new TextComponent(packet.bodyComponent); - } - try { - titleComponent = ComponentSerializer.deserialize(packet.titleComponent); - }catch(Throwable t) { - titleComponent = new TextComponent(packet.titleComponent); - } - try { - sourceComponent = ComponentSerializer.deserialize(packet.sourceComponent); - }catch(Throwable t) { - sourceComponent = new TextComponent(packet.sourceComponent); - } - originalTimestampSec = packet.originalTimestampSec; - silent = packet.silent; - switch(packet.priority) { - case LOW: - default: - priority = BadgePriority.LOW; - break; - case NORMAL: - priority = BadgePriority.NORMAL; - break; - case HIGHER: - priority = BadgePriority.HIGHER; - break; - case HIGHEST: - priority = BadgePriority.HIGHEST; - break; - } - mainIconUUID = new UUID(packet.mainIconUUIDMost, packet.mainIconUUIDLeast); - titleIconUUID = new UUID(packet.titleIconUUIDMost, packet.titleIconUUIDLeast); - hideAfterSec = packet.hideAfterSec; - backgroundColor = packet.backgroundColor; - bodyTxtColor = packet.bodyTxtColor; - titleTxtColor = packet.titleTxtColor; - sourceTxtColor = packet.sourceTxtColor; - packetCache = packet; - packetDirty = false; - } - - public UUID getBadgeUUID() { - return badgeUUID; - } - - public NotificationBadgeBuilder setBadgeUUID(UUID badgeUUID) { - this.badgeUUID = badgeUUID; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBadgeUUIDRandom() { - this.badgeUUID = UUID.randomUUID(); - this.packetDirty = true; - return this; - } - - public BaseComponent getBodyComponent() { - return bodyComponent; - } - - public NotificationBadgeBuilder setBodyComponent(BaseComponent bodyComponent) { - this.bodyComponent = bodyComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyComponent(String bodyText) { - this.bodyComponent = new TextComponent(bodyText); - this.packetDirty = true; - return this; - } - - public BaseComponent getTitleComponent() { - return titleComponent; - } - - public NotificationBadgeBuilder setTitleComponent(BaseComponent titleComponent) { - this.titleComponent = titleComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleComponent(String titleText) { - this.titleComponent = new TextComponent(titleText); - this.packetDirty = true; - return this; - } - - public BaseComponent getSourceComponent() { - return sourceComponent; - } - - public NotificationBadgeBuilder setSourceComponent(BaseComponent sourceComponent) { - this.sourceComponent = sourceComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceComponent(String sourceText) { - this.sourceComponent = new TextComponent(sourceText); - this.packetDirty = true; - return this; - } - - public long getOriginalTimestampSec() { - return originalTimestampSec; - } - - public NotificationBadgeBuilder setOriginalTimestampSec(long originalTimestampSec) { - this.originalTimestampSec = originalTimestampSec; - this.packetDirty = true; - return this; - } - - public boolean isSilent() { - return silent; - } - - public NotificationBadgeBuilder setSilent(boolean silent) { - this.silent = silent; - this.packetDirty = true; - return this; - } - - public BadgePriority getPriority() { - return priority; - } - - public NotificationBadgeBuilder setPriority(BadgePriority priority) { - this.priority = priority; - this.packetDirty = true; - return this; - } - - public UUID getMainIconUUID() { - return mainIconUUID; - } - - public NotificationBadgeBuilder setMainIconUUID(UUID mainIconUUID) { - this.mainIconUUID = mainIconUUID; - this.packetDirty = true; - return this; - } - - public UUID getTitleIconUUID() { - return titleIconUUID; - } - - public NotificationBadgeBuilder setTitleIconUUID(UUID titleIconUUID) { - this.titleIconUUID = titleIconUUID; - this.packetDirty = true; - return this; - } - - public int getHideAfterSec() { - return hideAfterSec; - } - - public NotificationBadgeBuilder setHideAfterSec(int hideAfterSec) { - this.hideAfterSec = hideAfterSec; - this.packetDirty = true; - return this; - } - - public int getExpireAfterSec() { - return expireAfterSec; - } - - public NotificationBadgeBuilder setExpireAfterSec(int expireAfterSec) { - this.expireAfterSec = expireAfterSec; - this.packetDirty = true; - return this; - } - - public int getBackgroundColor() { - return backgroundColor; - } - - public NotificationBadgeBuilder setBackgroundColor(int backgroundColor) { - this.backgroundColor = backgroundColor; - this.packetDirty = true; - return this; - } - - public int getBodyTxtColorRGB() { - return bodyTxtColor; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorRGB) { - this.bodyTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorR, int colorG, int colorB) { - this.bodyTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getTitleTxtColorRGB() { - return titleTxtColor; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorRGB) { - this.titleTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorR, int colorG, int colorB) { - this.titleTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getSourceTxtColorRGB() { - return sourceTxtColor; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorRGB) { - this.sourceTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorR, int colorG, int colorB) { - this.sourceTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public Object clone() { - return new NotificationBadgeBuilder(this); - } - - public SPacketNotifBadgeShowV4EAG buildPacket() { - if(packetDirty || packetCache == null) { - if(badgeUUID == null) { - badgeUUID = UUID.randomUUID(); - }else if(badgeUUID.getMostSignificantBits() == 0l && badgeUUID.getLeastSignificantBits() == 0l) { - throw new IllegalStateException("Badge UUID cannot be 0!"); - } - EnumBadgePriority internalPriority; - switch(priority) { - case LOW: - default: - internalPriority = EnumBadgePriority.LOW; - break; - case NORMAL: - internalPriority = EnumBadgePriority.NORMAL; - break; - case HIGHER: - internalPriority = EnumBadgePriority.HIGHER; - break; - case HIGHEST: - internalPriority = EnumBadgePriority.HIGHEST; - break; - } - String bodyComp = bodyComponent != null ? ComponentSerializer.toString(bodyComponent) : ""; - if(bodyComp.length() > 32767) { - throw new IllegalStateException("Body component is longer than 32767 chars serialized!"); - } - String titleComp = titleComponent != null ? ComponentSerializer.toString(titleComponent) : ""; - if(titleComp.length() > 255) { - throw new IllegalStateException("Title component is longer than 255 chars serialized!"); - } - String sourceComp = sourceComponent != null ? ComponentSerializer.toString(sourceComponent) : ""; - if(sourceComp.length() > 255) { - throw new IllegalStateException("Body component is longer than 255 chars serialized!"); - } - packetCache = new SPacketNotifBadgeShowV4EAG(badgeUUID.getMostSignificantBits(), - badgeUUID.getLeastSignificantBits(), bodyComp, titleComp, sourceComp, originalTimestampSec, silent, - internalPriority, mainIconUUID != null ? mainIconUUID.getMostSignificantBits() : 0l, - mainIconUUID != null ? mainIconUUID.getLeastSignificantBits() : 0l, - titleIconUUID != null ? titleIconUUID.getMostSignificantBits() : 0l, - titleIconUUID != null ? titleIconUUID.getLeastSignificantBits() : 0l, hideAfterSec, expireAfterSec, - backgroundColor, bodyTxtColor, titleTxtColor, sourceTxtColor); - packetDirty = false; - } - return packetCache; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftClientBrandEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftClientBrandEvent.java deleted file mode 100644 index 5b665890..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftClientBrandEvent.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; - -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.plugin.Cancellable; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftClientBrandEvent extends Event implements Cancellable { - - private final String clientBrand; - private final String clientVersion; - private final String origin; - private final int protocolVersion; - private final InetAddress remoteAddress; - private boolean cancelled; - private BaseComponent message; - - public EaglercraftClientBrandEvent(String clientBrand, String clientVersion, String origin, int protocolVersion, - InetAddress remoteAddress) { - this.clientBrand = clientBrand; - this.clientVersion = clientVersion; - this.origin = origin; - this.protocolVersion = protocolVersion; - this.remoteAddress = remoteAddress; - } - - public BaseComponent getMessage() { - return message; - } - - public void setMessage(BaseComponent message) { - this.message = message; - } - - public String getClientBrand() { - return clientBrand; - } - - public String getClientVersion() { - return clientVersion; - } - - public String getOrigin() { - return origin; - } - - public int getProtocolVersion() { - return protocolVersion; - } - - public InetAddress getRemoteAddress() { - return remoteAddress; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } - - public void setKickMessage(String message) { - this.cancelled = true; - this.message = new TextComponent(message); - } - - public void setKickMessage(BaseComponent message) { - this.cancelled = true; - this.message = message; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthCookieEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthCookieEvent.java deleted file mode 100644 index 98690ad2..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthCookieEvent.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftHandleAuthCookieEvent extends Event { - - public static enum AuthResponse { - ALLOW, DENY, REQUIRE_AUTH - } - - private final EaglerListenerConfig listener; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final boolean enableCookies; - private final byte[] cookieData; - private final EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod; - private final String eventAuthMessage; - private final Object authAttachment; - - private AuthResponse eventResponse; - private byte[] authUsername; - private String authProfileUsername; - private UUID authProfileUUID; - private String authRequestedServerRespose; - private String authDeniedMessage = "Bad Cookie!"; - private String applyTexturesPropValue; - private String applyTexturesPropSignature; - private boolean overrideEaglerToVanillaSkins; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglercraftHandleAuthCookieEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, byte[] authUsername, String authProfileUsername, UUID authProfileUUID, - boolean enableCookies, byte[] cookieData, EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod, - String eventAuthMessage, Object authAttachment, String authRequestedServerRespose, - Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.authUsername = authUsername; - this.authProfileUsername = authProfileUsername; - this.authProfileUUID = authProfileUUID; - this.enableCookies = enableCookies; - this.cookieData = cookieData; - this.eventAuthMethod = eventAuthMethod; - this.eventAuthMessage = eventAuthMessage; - this.authAttachment = authAttachment; - this.authRequestedServerRespose = authRequestedServerRespose; - this.continueThread = continueThread; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public boolean getCookiesEnabled() { - return enableCookies; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return cookieData != null ? new String(cookieData, StandardCharsets.UTF_8) : null; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public String getProfileUsername() { - return authProfileUsername; - } - - public void setProfileUsername(String username) { - this.authProfileUsername = username; - } - - public UUID getProfileUUID() { - return authProfileUUID; - } - - public void setProfileUUID(UUID uuid) { - this.authProfileUUID = uuid; - } - - public EaglercraftIsAuthRequiredEvent.AuthMethod getAuthType() { - return eventAuthMethod; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public String getAuthRequestedServer() { - return authRequestedServerRespose; - } - - public void setAuthRequestedServer(String server) { - this.authRequestedServerRespose = server; - } - - public void setLoginAllowed() { - this.eventResponse = AuthResponse.ALLOW; - this.authDeniedMessage = null; - } - - public void setLoginPasswordRequired() { - this.eventResponse = AuthResponse.REQUIRE_AUTH; - this.authDeniedMessage = null; - } - - public void setLoginDenied(String message) { - this.eventResponse = AuthResponse.DENY; - this.authDeniedMessage = message; - } - - public AuthResponse getLoginAllowed() { - return eventResponse; - } - - public String getLoginDeniedMessage() { - return authDeniedMessage; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftHandleAuthCookieEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - - public void applyTexturesProperty(String value, String signature) { - applyTexturesPropValue = value; - applyTexturesPropSignature = signature; - } - - public String getApplyTexturesPropertyValue() { - return applyTexturesPropValue; - } - - public String getApplyTexturesPropertySignature() { - return applyTexturesPropSignature; - } - - public void setOverrideEaglerToVanillaSkins(boolean overrideEaglerToVanillaSkins) { - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - } - - public boolean isOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthPasswordEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthPasswordEvent.java deleted file mode 100644 index 06a422c9..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftHandleAuthPasswordEvent.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftHandleAuthPasswordEvent extends Event { - - public static enum AuthResponse { - ALLOW, DENY - } - - private final EaglerListenerConfig listener; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final byte[] authUsername; - private final byte[] authSaltingData; - private final byte[] authPasswordData; - private final boolean enableCookies; - private final byte[] cookieData; - private final EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod; - private final String eventAuthMessage; - private final Object authAttachment; - - private AuthResponse eventResponse; - private String authProfileUsername; - private UUID authProfileUUID; - private String authRequestedServerRespose; - private String authDeniedMessage = "Password Incorrect!"; - private String applyTexturesPropValue; - private String applyTexturesPropSignature; - private boolean overrideEaglerToVanillaSkins; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglercraftHandleAuthPasswordEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, byte[] authUsername, byte[] authSaltingData, String authProfileUsername, - UUID authProfileUUID, byte[] authPasswordData, boolean enableCookies, byte[] cookieData, - EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod, String eventAuthMessage, Object authAttachment, - String authRequestedServerRespose, Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.authUsername = authUsername; - this.authSaltingData = authSaltingData; - this.authProfileUsername = authProfileUsername; - this.authProfileUUID = authProfileUUID; - this.authPasswordData = authPasswordData; - this.enableCookies = enableCookies; - this.cookieData = cookieData; - this.eventAuthMethod = eventAuthMethod; - this.eventAuthMessage = eventAuthMessage; - this.authAttachment = authAttachment; - this.authRequestedServerRespose = authRequestedServerRespose; - this.continueThread = continueThread; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public byte[] getAuthSaltingData() { - return authSaltingData; - } - - public boolean getCookiesEnabled() { - return enableCookies; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return cookieData != null ? new String(cookieData, StandardCharsets.UTF_8) : null; - } - - public String getProfileUsername() { - return authProfileUsername; - } - - public void setProfileUsername(String username) { - this.authProfileUsername = username; - } - - public UUID getProfileUUID() { - return authProfileUUID; - } - - public void setProfileUUID(UUID uuid) { - this.authProfileUUID = uuid; - } - - public byte[] getAuthPasswordDataResponse() { - return authPasswordData; - } - - public EaglercraftIsAuthRequiredEvent.AuthMethod getAuthType() { - return eventAuthMethod; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public String getAuthRequestedServer() { - return authRequestedServerRespose; - } - - public void setAuthRequestedServer(String server) { - this.authRequestedServerRespose = server; - } - - public void setLoginAllowed() { - this.eventResponse = AuthResponse.ALLOW; - this.authDeniedMessage = null; - } - - public void setLoginDenied(String message) { - this.eventResponse = AuthResponse.DENY; - this.authDeniedMessage = message; - } - - public AuthResponse getLoginAllowed() { - return eventResponse; - } - - public String getLoginDeniedMessage() { - return authDeniedMessage; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftHandleAuthPasswordEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - - public void applyTexturesProperty(String value, String signature) { - applyTexturesPropValue = value; - applyTexturesPropSignature = signature; - } - - public String getApplyTexturesPropertyValue() { - return applyTexturesPropValue; - } - - public String getApplyTexturesPropertySignature() { - return applyTexturesPropSignature; - } - - public void setOverrideEaglerToVanillaSkins(boolean overrideEaglerToVanillaSkins) { - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - } - - public boolean isOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftIsAuthRequiredEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftIsAuthRequiredEvent.java deleted file mode 100644 index e67b3e7d..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftIsAuthRequiredEvent.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftIsAuthRequiredEvent extends Event { - - public static enum AuthResponse { - SKIP, REQUIRE, DENY - } - - public static enum AuthMethod { - PLAINTEXT, EAGLER_SHA256, AUTHME_SHA256 - } - - public EaglercraftIsAuthRequiredEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, boolean wantsAuth, byte[] authUsername, - Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.wantsAuth = wantsAuth; - this.authUsername = authUsername; - this.continueThread = continueThread; - } - - private final EaglerListenerConfig listener; - private AuthResponse authResponse; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final boolean wantsAuth; - private final byte[] authUsername; - private byte[] authSaltingData; - private AuthMethod eventAuthMethod = null; - private String eventAuthMessage = "enter the code:"; - private String kickUserMessage = "Login Denied"; - private Object authAttachment; - private boolean enableCookieAuth; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public boolean isClientSolicitingPasscode() { - return wantsAuth; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public byte[] getSaltingData() { - return authSaltingData; - } - - public void setSaltingData(byte[] saltingData) { - authSaltingData = saltingData; - } - - public AuthMethod getUseAuthType() { - return eventAuthMethod; - } - - public void setUseAuthMethod(AuthMethod authMethod) { - this.eventAuthMethod = authMethod; - } - - public AuthResponse getAuthRequired() { - return authResponse; - } - - public void setAuthRequired(AuthResponse required) { - this.authResponse = required; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public void setAuthMessage(String eventAuthMessage) { - this.eventAuthMessage = eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public void setAuthAttachment(Object authAttachment) { - this.authAttachment = authAttachment; - } - - public boolean getEnableCookieAuth() { - return enableCookieAuth; - } - - public void setEnableCookieAuth(boolean enable) { - this.enableCookieAuth = enable; - } - - public boolean shouldKickUser() { - return authResponse == null || authResponse == AuthResponse.DENY; - } - - public String getKickMessage() { - return kickUserMessage; - } - - public void kickUser(String message) { - authResponse = AuthResponse.DENY; - kickUserMessage = message; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftIsAuthRequiredEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftMOTDEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftMOTDEvent.java deleted file mode 100644 index 535ef311..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftMOTDEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.MOTDConnection; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftMOTDEvent extends Event { - - protected final MOTDConnection connection; - - public EaglercraftMOTDEvent(MOTDConnection connection) { - this.connection = connection; - } - - public InetAddress getRemoteAddress() { - return connection.getAddress(); - } - - public EaglerListenerConfig getListener() { - return connection.getListener(); - } - - public String getAccept() { - return connection.getAccept(); - } - - public MOTDConnection getConnection() { - return connection; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterCapeEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterCapeEvent.java deleted file mode 100644 index fdaa7ec5..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterCapeEvent.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftRegisterCapeEvent extends Event { - - private final Object authAttachment; - private final String username; - private final UUID uuid; - private byte[] customTex = null; - - public EaglercraftRegisterCapeEvent(String username, UUID uuid, Object authAttachment) { - this.username = username; - this.uuid = uuid; - this.authAttachment = authAttachment; - } - - public String getUsername() { - return username; - } - - public UUID getUuid() { - return uuid; - } - - public void setForceUsePreset(int p) { - customTex = new byte[5]; - customTex[0] = (byte)1; - customTex[1] = (byte)(p >>> 24); - customTex[2] = (byte)(p >>> 16); - customTex[3] = (byte)(p >>> 8); - customTex[4] = (byte)(p & 0xFF); - } - - /** - * @param tex raw 32x32 pixel RGBA texture (4096 bytes long), see capes in "sources/resources/assets/eagler/capes" - */ - public void setForceUseCustom(byte[] tex) { - customTex = new byte[1174]; - customTex[0] = (byte)2; - EaglerXBungeeAPIHelper.convertCape32x32RGBAto23x17RGB(tex, 0, customTex, 1); - } - - public void setForceUseCustomByPacket(byte[] packet) { - customTex = packet; - } - - public byte[] getForceSetUseCustomPacket() { - return customTex; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterSkinEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterSkinEvent.java deleted file mode 100644 index 9a4565b2..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRegisterSkinEvent.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.util.UUID; - -import net.md_5.bungee.api.plugin.Event; -import net.md_5.bungee.protocol.Property; - -public class EaglercraftRegisterSkinEvent extends Event { - - private final Object authAttachment; - private final String username; - private final UUID uuid; - private Property useMojangProfileProperty = null; - private boolean useLoginResultTextures = false; - private byte[] customTex = null; - - public EaglercraftRegisterSkinEvent(String username, UUID uuid, Object authAttachment) { - this.username = username; - this.uuid = uuid; - this.authAttachment = authAttachment; - } - - public void setForceUseMojangProfileProperty(Property prop) { - useMojangProfileProperty = prop; - useLoginResultTextures = false; - customTex = null; - } - - public void setForceUseLoginResultObjectTextures(boolean b) { - useMojangProfileProperty = null; - useLoginResultTextures = b; - customTex = null; - } - - public void setForceUsePreset(int p) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = new byte[5]; - customTex[0] = (byte)1; - customTex[1] = (byte)(p >>> 24); - customTex[2] = (byte)(p >>> 16); - customTex[3] = (byte)(p >>> 8); - customTex[4] = (byte)(p & 0xFF); - } - - /** - * @param tex raw 64x64 pixel RGBA texture (16384 bytes long) - */ - public void setForceUseCustom(int model, byte[] tex) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = new byte[2 + tex.length]; - customTex[0] = (byte)2; - customTex[1] = (byte)model; - System.arraycopy(tex, 0, customTex, 2, tex.length); - } - - public void setForceUseCustomByPacket(byte[] packet) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = packet; - } - - public String getUsername() { - return username; - } - - public UUID getUuid() { - return uuid; - } - - public Property getForceUseMojangProfileProperty() { - return useMojangProfileProperty; - } - - public boolean getForceUseLoginResultObjectTextures() { - return useLoginResultTextures; - } - - public byte[] getForceSetUseCustomPacket() { - return customTex; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRevokeSessionQueryEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRevokeSessionQueryEvent.java deleted file mode 100644 index f0db999c..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftRevokeSessionQueryEvent.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.RevokeSessionQueryHandler; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftRevokeSessionQueryEvent extends Event { - - private final InetAddress remoteAddress; - private final String origin; - private final byte[] cookieData; - private final RevokeSessionQueryHandler queryHandler; - private EnumSessionRevokeStatus revokeStatus; - private boolean shouldDeleteCookie; - - public static enum EnumSessionRevokeStatus { - SUCCESS("ok", -1), FAILED_NOT_SUPPORTED("error", 1), FAILED_NOT_ALLOWED("error", 2), - FAILED_NOT_FOUND("error", 3), FAILED_SERVER_ERROR("error", 4); - - public final String status; - public final int code; - - private EnumSessionRevokeStatus(String status, int code) { - this.status = status; - this.code = code; - } - } - - public EaglercraftRevokeSessionQueryEvent(InetAddress remoteAddress, String origin, byte[] cookieData, - RevokeSessionQueryHandler queryHandler) { - this.remoteAddress = remoteAddress; - this.origin = origin; - this.cookieData = cookieData; - this.queryHandler = queryHandler; - this.revokeStatus = EnumSessionRevokeStatus.FAILED_NOT_SUPPORTED; - this.shouldDeleteCookie = false; - } - - public InetAddress getRemoteAddress() { - return remoteAddress; - } - - public String getOrigin() { - return origin; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return new String(cookieData, StandardCharsets.UTF_8); - } - - public RevokeSessionQueryHandler getQuery() { - return queryHandler; - } - - public void setResultStatus(EnumSessionRevokeStatus revokeStatus) { - this.revokeStatus = revokeStatus; - } - - public EnumSessionRevokeStatus getResultStatus() { - return revokeStatus; - } - - public boolean getShouldDeleteCookie() { - return shouldDeleteCookie; - } - - public void setShouldDeleteCookie(boolean b) { - this.shouldDeleteCookie = b; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftVoiceStatusChangeEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftVoiceStatusChangeEvent.java deleted file mode 100644 index 9ac07954..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftVoiceStatusChangeEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftVoiceStatusChangeEvent extends Event { - - public static enum EnumVoiceState { - SERVER_DISABLE, DISABLED, ENABLED; - } - - private final ProxiedPlayer playerObj; - private final EaglerListenerConfig listener; - private final EaglerInitialHandler eaglerHandler; - private final EnumVoiceState voiceStateOld; - private final EnumVoiceState voiceStateNew; - - public EaglercraftVoiceStatusChangeEvent(ProxiedPlayer playerObj, EaglerListenerConfig listener, - EaglerInitialHandler eaglerHandler, EnumVoiceState voiceStateOld, EnumVoiceState voiceStateNew) { - this.playerObj = playerObj; - this.listener = listener; - this.eaglerHandler = eaglerHandler; - this.voiceStateOld = voiceStateOld; - this.voiceStateNew = voiceStateNew; - } - - public ProxiedPlayer getPlayerObj() { - return playerObj; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public EaglerInitialHandler getEaglerHandler() { - return eaglerHandler; - } - - public EnumVoiceState getVoiceStateOld() { - return voiceStateOld; - } - - public EnumVoiceState getVoiceStateNew() { - return voiceStateNew; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebSocketOpenEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebSocketOpenEvent.java deleted file mode 100644 index 21f8d93a..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebSocketOpenEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import io.netty.channel.Channel; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.plugin.Cancellable; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftWebSocketOpenEvent extends Event implements Cancellable { - - private final Channel channel; - private final EaglerListenerConfig listener; - private final String realIP; - private final String origin; - private final String userAgent; - private boolean cancelled = false; - - public EaglercraftWebSocketOpenEvent(Channel channel, EaglerListenerConfig listener, String realIP, String origin, String userAgent) { - this.channel = channel; - this.listener = listener; - this.realIP = realIP; - this.origin = origin; - this.userAgent = userAgent; - } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean var1) { - cancelled = var1; - } - - public Channel getChannel() { - return channel; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public String getRealIP() { - return realIP; - } - - public String getOrigin() { - return origin; - } - - public String getUserAgent() { - return userAgent; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewChannelEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewChannelEvent.java deleted file mode 100644 index 3742d86b..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewChannelEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftWebViewChannelEvent extends Event { - - public static enum EventType { - CHANNEL_OPEN, CHANNEL_CLOSE; - } - - private final ProxiedPlayer player; - private final EaglerListenerConfig listener; - private final String channel; - private final EventType type; - - public EaglercraftWebViewChannelEvent(ProxiedPlayer player, EaglerListenerConfig listener, String channel, EventType type) { - this.player = player; - this.listener = listener; - this.channel = channel; - this.type = type; - } - - public ProxiedPlayer getPlayer() { - return player; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public String getChannel() { - return channel; - } - - public EventType getType() { - return type; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewMessageEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewMessageEvent.java deleted file mode 100644 index 73105549..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/event/EaglercraftWebViewMessageEvent.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event; - -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketWebViewMessageV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketWebViewMessageV4EAG; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Event; - -public class EaglercraftWebViewMessageEvent extends Event { - - public static enum MessageType { - STRING(SPacketWebViewMessageV4EAG.TYPE_STRING), BINARY(SPacketWebViewMessageV4EAG.TYPE_BINARY); - - private final int id; - - private MessageType(int id) { - this.id = id; - } - - private static MessageType fromId(int id) { - switch(id) { - case CPacketWebViewMessageV4EAG.TYPE_STRING: - return STRING; - default: - case CPacketWebViewMessageV4EAG.TYPE_BINARY: - return BINARY; - } - } - } - - private final ProxiedPlayer player; - private final EaglerListenerConfig listener; - private final String currentChannel; - private final EaglerInitialHandler eaglerHandler; - private final MessageType type; - private final byte[] data; - private String asString; - - public EaglercraftWebViewMessageEvent(ProxiedPlayer player, EaglerListenerConfig listener, String currentChannel, MessageType type, byte[] data) { - this.player = player; - this.listener = listener; - this.currentChannel = currentChannel; - this.eaglerHandler = EaglerXBungeeAPIHelper.getEaglerHandle(player); - this.type = type; - this.data = data; - } - - public EaglercraftWebViewMessageEvent(ProxiedPlayer player, EaglerListenerConfig listener, String currentChannel, CPacketWebViewMessageV4EAG packet) { - this.player = player; - this.listener = listener; - this.currentChannel = currentChannel; - this.eaglerHandler = EaglerXBungeeAPIHelper.getEaglerHandle(player); - this.type = MessageType.fromId(packet.type); - this.data = packet.data; - } - - public ProxiedPlayer getPlayer() { - return player; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public EaglerInitialHandler getEaglerHandle() { - return eaglerHandler; - } - - public void sendResponse(MessageType type, byte[] data) { - eaglerHandler.sendEaglerMessage(new SPacketWebViewMessageV4EAG(type.id, data)); - } - - public void sendResponse(String str) { - sendResponse(MessageType.STRING, str.getBytes(StandardCharsets.UTF_8)); - } - - public void sendResponse(byte[] data) { - sendResponse(MessageType.BINARY, data); - } - - public MessageType getType() { - return type; - } - - public byte[] getAsBinary() { - return data; - } - - public String getAsString() { - if(asString == null) { - asString = new String(data, StandardCharsets.UTF_8); - } - return asString; - } - - public String getChannelName() { - return currentChannel; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQueryHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQueryHandler.java deleted file mode 100644 index 9fe6ab69..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQueryHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.HttpServerQueryHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.QueryManager; - -public abstract class EaglerQueryHandler extends HttpServerQueryHandler { - - public static void registerQueryType(String name, Class clazz) { - QueryManager.registerQueryType(name, clazz); - } - - public static void unregisterQueryType(String name) { - QueryManager.unregisterQueryType(name); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQuerySimpleHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQuerySimpleHandler.java deleted file mode 100644 index 712b74ee..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/EaglerQuerySimpleHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query; - -import com.google.gson.JsonObject; - -public abstract class EaglerQuerySimpleHandler extends EaglerQueryHandler { - - @Override - protected void processString(String str) { - throw new UnexpectedDataException(); - } - - @Override - protected void processJson(JsonObject obj) { - throw new UnexpectedDataException(); - } - - @Override - protected void processBytes(byte[] bytes) { - throw new UnexpectedDataException(); - } - - @Override - protected void acceptText() { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptText(boolean bool) { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptBinary() { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptBinary(boolean bool) { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void closed() { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/MOTDConnection.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/MOTDConnection.java deleted file mode 100644 index 84005d32..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/api/query/MOTDConnection.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query; - -import java.net.InetAddress; -import java.util.List; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; - -public interface MOTDConnection { - - boolean isClosed(); - void close(); - - String getAccept(); - InetAddress getAddress(); - EaglerListenerConfig getListener(); - long getConnectionTimestamp(); - - public default long getConnectionAge() { - return EaglerXBungeeAPIHelper.steadyTimeMillis() - getConnectionTimestamp(); - } - - void sendToUser(); - void setKeepAlive(boolean enable); - - String getLine1(); - String getLine2(); - List getPlayerList(); - int[] getBitmap(); - int getOnlinePlayers(); - int getMaxPlayers(); - String getSubType(); - - void setLine1(String p); - void setLine2(String p); - void setPlayerList(List p); - void setPlayerList(String... p); - void setBitmap(int[] p); - void setOnlinePlayers(int i); - void setMaxPlayers(int i); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java deleted file mode 100644 index 519c8258..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; - -public class AuthLoadingCache { - - private static class CacheEntry { - - private long lastHit; - private V instance; - - private CacheEntry(V instance) { - this.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - this.instance = instance; - } - - } - - public static interface CacheLoader { - V load(K key); - } - - public static interface CacheVisitor { - boolean shouldEvict(K key, V value); - } - - private final ReadWriteLock cacheMapLock; - private final Map> cacheMap; - private final CacheLoader provider; - private final long cacheTTL; - - private long cacheTimer; - - public AuthLoadingCache(CacheLoader provider, long cacheTTL) { - this.cacheMapLock = new ReentrantReadWriteLock(); - this.cacheMap = new HashMap<>(); - this.provider = provider; - this.cacheTTL = cacheTTL; - } - - public V get(K key) { - CacheEntry etr; - cacheMapLock.readLock().lock(); - try { - etr = cacheMap.get(key); - }finally { - cacheMapLock.readLock().unlock(); - } - if(etr == null) { - cacheMapLock.writeLock().lock(); - V loaded = provider.load(key); - try { - cacheMap.put(key, new CacheEntry<>(loaded)); - }finally { - cacheMapLock.writeLock().unlock(); - } - return loaded; - }else { - etr.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - return etr.instance; - } - } - - public void evict(K key) { - cacheMapLock.writeLock().lock(); - try { - cacheMap.remove(key); - }finally { - cacheMapLock.writeLock().unlock(); - } - } - - public void evictAll(CacheVisitor visitor) { - cacheMapLock.writeLock().lock(); - try { - Iterator>> itr = cacheMap.entrySet().iterator(); - while(itr.hasNext()) { - Entry> etr = itr.next(); - if(visitor.shouldEvict(etr.getKey(), etr.getValue().instance)) { - itr.remove(); - } - } - }finally { - cacheMapLock.writeLock().unlock(); - } - } - - public void tick() { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - if(millis - cacheTimer > (cacheTTL / 2L)) { - cacheTimer = millis; - cacheMapLock.writeLock().lock(); - try { - Iterator> mapItr = cacheMap.values().iterator(); - while(mapItr.hasNext()) { - CacheEntry etr = mapItr.next(); - if(millis - etr.lastHit > cacheTTL) { - mapItr.remove(); - } - } - }finally { - cacheMapLock.writeLock().unlock(); - } - } - } - - public void flush() { - cacheMapLock.writeLock().lock(); - try { - cacheMap.clear(); - }finally { - cacheMapLock.writeLock().unlock(); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/DefaultAuthSystem.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/DefaultAuthSystem.java deleted file mode 100644 index faeafae8..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/DefaultAuthSystem.java +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Properties; -import java.util.Random; -import java.util.UUID; -import java.util.logging.Level; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang3.ArrayUtils; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftHandleAuthPasswordEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftIsAuthRequiredEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftIsAuthRequiredEvent.AuthMethod; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftIsAuthRequiredEvent.AuthResponse; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.sqlite.EaglerDrivers; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.protocol.Property; - -public class DefaultAuthSystem { - - public static class AuthSystemException extends RuntimeException { - - public AuthSystemException() { - } - - public AuthSystemException(String message, Throwable cause) { - super(message, cause); - } - - public AuthSystemException(String message) { - super(message); - } - - public AuthSystemException(Throwable cause) { - super(cause); - } - - } - - protected final String uri; - protected final Connection databaseConnection; - protected final String passwordPromptScreenText; - protected final String wrongPasswordScreenText; - protected final String notRegisteredScreenText; - protected final String eaglerCommandName; - protected final String useRegisterCommandText; - protected final String useChangeCommandText; - protected final String commandSuccessText; - protected final String lastEaglerLoginMessage; - protected final String tooManyRegistrationsMessage; - protected final String needVanillaToRegisterMessage; - protected final boolean overrideEaglerToVanillaSkins; - protected final int maxRegistrationsPerIP; - - protected final SecureRandom secureRandom; - - public static DefaultAuthSystem initializeAuthSystem(EaglerAuthConfig config) throws AuthSystemException { - String databaseURI = config.getDatabaseURI(); - Connection conn; - try { - conn = EaglerDrivers.connectToDatabase(databaseURI, config.getDriverClass(), config.getDriverPath(), new Properties()); - if(conn == null) { - throw new IllegalStateException("Connection is null"); - } - }catch(Throwable t) { - throw new AuthSystemException("Could not initialize '" + databaseURI + "'!", t); - } - EaglerXBungee.logger().info("Connected to database: " + databaseURI); - try { - try(Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE IF NOT EXISTS \"eaglercraft_accounts\" (" - + "\"Version\" TINYINT NOT NULL," - + "\"MojangUUID\" TEXT(32) NOT NULL," - + "\"MojangUsername\" TEXT(16) NOT NULL," - + "\"HashBase\" BLOB NOT NULL," - + "\"HashSalt\" BLOB NOT NULL," - + "\"MojangTextures\" BLOB," - + "\"Registered\" DATETIME NOT NULL," - + "\"RegisteredIP\" VARCHAR(42) NOT NULL," - + "\"LastLogin\" DATETIME," - + "\"LastLoginIP\" VARCHAR(42)," - + "PRIMARY KEY(\"MojangUUID\"))"); - stmt.execute("CREATE UNIQUE INDEX IF NOT EXISTS \"MojangUsername\" ON " - + "\"eaglercraft_accounts\" (\"MojangUsername\")"); - } - return new DefaultAuthSystem(databaseURI, conn, config.getPasswordPromptScreenText(), - config.getWrongPasswordScreenText(), config.getNotRegisteredScreenText(), - config.getEaglerCommandName(), config.getUseRegisterCommandText(), config.getUseChangeCommandText(), - config.getCommandSuccessText(), config.getLastEaglerLoginMessage(), - config.getTooManyRegistrationsMessage(), config.getNeedVanillaToRegisterMessage(), - config.getOverrideEaglerToVanillaSkins(), config.getMaxRegistrationsPerIP()); - }catch(AuthSystemException ex) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw ex; - }catch(Throwable t) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw new AuthSystemException("Could not initialize '" + databaseURI + "'!", t); - } - } - - protected final PreparedStatement registerUser; - protected final PreparedStatement isRegisteredUser; - protected final PreparedStatement pruneUsers; - protected final PreparedStatement updatePassword; - protected final PreparedStatement updateMojangUsername; - protected final PreparedStatement getRegistrationsOnIP; - protected final PreparedStatement checkRegistrationByUUID; - protected final PreparedStatement checkRegistrationByName; - protected final PreparedStatement setLastLogin; - protected final PreparedStatement updateTextures; - - protected class AccountLoader implements AuthLoadingCache.CacheLoader { - - @Override - public CachedAccountInfo load(String key) { - try { - CachedAccountInfo cachedInfo = null; - synchronized(checkRegistrationByName) { - checkRegistrationByName.setString(1, key); - try(ResultSet res = checkRegistrationByName.executeQuery()) { - if (res.next()) { - cachedInfo = new CachedAccountInfo(res.getInt(1), parseMojangUUID(res.getString(2)), key, - res.getBytes(3), res.getBytes(4), res.getBytes(5), res.getDate(6), res.getString(7), - res.getDate(8), res.getString(9)); - } - } - } - return cachedInfo; - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - - } - - protected class CachedAccountInfo { - - protected int version; - protected UUID mojangUUID; - protected String mojangUsername; - protected byte[] texturesProperty; - protected byte[] hashBase; - protected byte[] hashSalt; - protected long registered; - protected String registeredIP; - protected long lastLogin; - protected String lastLoginIP; - - protected CachedAccountInfo(int version, UUID mojangUUID, String mojangUsername, byte[] texturesProperty, - byte[] hashBase, byte[] hashSalt, Date registered, String registeredIP, Date lastLogin, - String lastLoginIP) { - this(version, mojangUUID, mojangUsername, texturesProperty, hashBase, hashSalt, - registered == null ? 0l : registered.getTime(), registeredIP, - lastLogin == null ? 0l : lastLogin.getTime(), lastLoginIP); - } - - protected CachedAccountInfo(int version, UUID mojangUUID, String mojangUsername, byte[] texturesProperty, - byte[] hashBase, byte[] hashSalt, long registered, String registeredIP, long lastLogin, - String lastLoginIP) { - this.version = version; - this.mojangUUID = mojangUUID; - this.mojangUsername = mojangUsername; - this.texturesProperty = texturesProperty; - this.hashBase = hashBase; - this.hashSalt = hashSalt; - this.registered = registered; - this.registeredIP = registeredIP; - this.lastLogin = lastLogin; - this.lastLoginIP = lastLoginIP; - } - - } - - protected final AuthLoadingCache authLoadingCache; - - protected DefaultAuthSystem(String uri, Connection databaseConnection, String passwordPromptScreenText, - String wrongPasswordScreenText, String notRegisteredScreenText, String eaglerCommandName, - String useRegisterCommandText, String useChangeCommandText, String commandSuccessText, - String lastEaglerLoginMessage, String tooManyRegistrationsMessage, String needVanillaToRegisterMessage, - boolean overrideEaglerToVanillaSkins, int maxRegistrationsPerIP) throws SQLException { - this.uri = uri; - this.databaseConnection = databaseConnection; - this.passwordPromptScreenText = passwordPromptScreenText; - this.wrongPasswordScreenText = wrongPasswordScreenText; - this.notRegisteredScreenText = notRegisteredScreenText; - this.eaglerCommandName = eaglerCommandName; - this.useRegisterCommandText = useRegisterCommandText; - this.useChangeCommandText = useChangeCommandText; - this.commandSuccessText = commandSuccessText; - this.lastEaglerLoginMessage = lastEaglerLoginMessage; - this.tooManyRegistrationsMessage = tooManyRegistrationsMessage; - this.needVanillaToRegisterMessage = needVanillaToRegisterMessage; - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - this.maxRegistrationsPerIP = maxRegistrationsPerIP; - this.registerUser = databaseConnection.prepareStatement("INSERT INTO eaglercraft_accounts (Version, MojangUUID, MojangUsername, MojangTextures, HashBase, HashSalt, Registered, RegisteredIP) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); - this.isRegisteredUser = databaseConnection.prepareStatement("SELECT COUNT(MojangUUID) AS total_accounts FROM eaglercraft_accounts WHERE MojangUUID = ?"); - this.pruneUsers = databaseConnection.prepareStatement("DELETE FROM eaglercraft_accounts WHERE LastLogin < ?"); - this.updatePassword = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET HashBase = ?, HashSalt = ? WHERE MojangUUID = ?"); - this.updateMojangUsername = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET MojangUsername = ? WHERE MojangUUID = ?"); - this.getRegistrationsOnIP = databaseConnection.prepareStatement("SELECT COUNT(MojangUUID) AS total_accounts FROM eaglercraft_accounts WHERE RegisteredIP = ?"); - this.checkRegistrationByUUID = databaseConnection.prepareStatement("SELECT Version, MojangUsername, LastLogin, LastLoginIP FROM eaglercraft_accounts WHERE MojangUUID = ?"); - this.checkRegistrationByName = databaseConnection.prepareStatement("SELECT Version, MojangUUID, MojangTextures, HashBase, HashSalt, Registered, RegisteredIP, LastLogin, LastLoginIP FROM eaglercraft_accounts WHERE MojangUsername = ?"); - this.setLastLogin = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET LastLogin = ?, LastLoginIP = ? WHERE MojangUUID = ?"); - this.updateTextures = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET MojangTextures = ? WHERE MojangUUID = ?"); - this.authLoadingCache = new AuthLoadingCache<>(new AccountLoader(), 120000l); - this.secureRandom = new SecureRandom(); - } - - public void handleIsAuthRequiredEvent(EaglercraftIsAuthRequiredEvent event) { - String username = new String(event.getAuthUsername(), StandardCharsets.US_ASCII); - - String usrs = username.toString(); - if(!usrs.equals(usrs.replaceAll("[^A-Za-z0-9_]", "_").trim())) { - event.kickUser("Invalid characters in username"); - return; - } - - if(username.length() < 3) { - event.kickUser("Username must be at least 3 characters"); - return; - } - - if(username.length() > 16) { - event.kickUser("Username must be under 16 characters"); - return; - } - - CachedAccountInfo info = authLoadingCache.get(username); - if(info == null) { - event.kickUser(notRegisteredScreenText); - return; - } - - event.setAuthAttachment(info); - event.setAuthRequired(AuthResponse.REQUIRE); - event.setAuthMessage(passwordPromptScreenText); - event.setUseAuthMethod(AuthMethod.EAGLER_SHA256); - - byte[] randomBytes = new byte[32]; - Random rng; - synchronized(secureRandom) { - rng = new Random(secureRandom.nextLong()); - } - - rng.nextBytes(randomBytes); - - byte[] saltingData = new byte[64]; - System.arraycopy(info.hashSalt, 0, saltingData, 0, 32); - System.arraycopy(randomBytes, 0, saltingData, 32, 32); - - event.setSaltingData(saltingData); - } - - public void handleAuthPasswordEvent(EaglercraftHandleAuthPasswordEvent event) { - CachedAccountInfo info = event.getAuthAttachment(); - - if(info == null) { - event.setLoginDenied(notRegisteredScreenText); - return; - } - - - byte[] responseHash = event.getAuthPasswordDataResponse(); - - if(responseHash.length != 32) { - event.setLoginDenied("Wrong number of bits in checksum!"); - return; - } - - byte[] saltingData = event.getAuthSaltingData(); - - SHA256Digest digest = new SHA256Digest(); - - digest.update(info.hashBase, 0, 32); - digest.update(saltingData, 32, 32); - digest.update(HashUtils.EAGLER_SHA256_SALT_BASE, 0, 32); - - byte[] hashed = new byte[32]; - digest.doFinal(hashed, 0); - - if(!Arrays.equals(hashed, responseHash)) { - event.setLoginDenied(wrongPasswordScreenText); - EaglerXBungee.logger().warning("User \"" + info.mojangUsername + "\" entered the wrong password while logging in from: " + event.getRemoteAddress().getHostAddress()); - return; - } - - try { - synchronized(setLastLogin) { - setLastLogin.setDate(1, new Date(System.currentTimeMillis())); - setLastLogin.setString(2, event.getRemoteAddress().getHostAddress()); - setLastLogin.setString(3, getMojangUUID(info.mojangUUID)); - if(setLastLogin.executeUpdate() == 0) { - throw new SQLException("Query did not alter the database"); - } - } - }catch(SQLException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "Could not update last login for \"" + info.mojangUUID.toString() + "\"", ex); - } - - event.setLoginAllowed(); - event.setProfileUsername(info.mojangUsername); - event.setProfileUUID(info.mojangUUID); - - byte[] texturesProp = info.texturesProperty; - if(texturesProp != null) { - try { - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(texturesProp)); - int valueLen = dis.readInt(); - int sigLen = dis.readInt(); - byte[] valueBytes = new byte[valueLen]; - dis.read(valueBytes); - String valueB64 = Base64.encodeBase64String(valueBytes); - String sigB64 = null; - if(sigLen > 0) { - valueBytes = new byte[sigLen]; - dis.read(valueBytes); - sigB64 = Base64.encodeBase64String(valueBytes); - } - event.applyTexturesProperty(valueB64, sigB64); - event.setOverrideEaglerToVanillaSkins(overrideEaglerToVanillaSkins); - }catch(IOException ex) { - } - } - } - - public void processSetPassword(ProxiedPlayer player, String password) throws TooManyRegisteredOnIPException, AuthException { - PendingConnection conn = player.getPendingConnection(); - if(conn instanceof EaglerInitialHandler) { - throw new AuthException("Cannot register from an eaglercraft account!"); - }else if(!conn.isOnlineMode()) { - throw new AuthException("Cannot register without online mode enabled!"); - }else { - try { - String uuid = getMojangUUID(player.getUniqueId()); - synchronized(registerUser) { - int cnt; - synchronized(isRegisteredUser) { - isRegisteredUser.setString(1, uuid); - try(ResultSet set = isRegisteredUser.executeQuery()) { - if(set.next()) { - cnt = set.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved while checking if user exists"); - } - } - } - - SHA256Digest digest = new SHA256Digest(); - - int passLen = password.length(); - - digest.update((byte)((passLen >> 8) & 0xFF)); - digest.update((byte)(passLen & 0xFF)); - for(int i = 0; i < passLen; ++i) { - char codePoint = password.charAt(i); - digest.update((byte)((codePoint >> 8) & 0xFF)); - digest.update((byte)(codePoint & 0xFF)); - } - - digest.update(HashUtils.EAGLER_SHA256_SALT_SAVE, 0, 32); - - byte[] hashed = new byte[32]; - digest.doFinal(hashed, 0); - - byte[] randomBytes = new byte[32]; - synchronized(secureRandom) { - secureRandom.nextBytes(randomBytes); - } - - digest.reset(); - - digest.update(hashed, 0, 32); - digest.update(randomBytes, 0, 32); - digest.update(HashUtils.EAGLER_SHA256_SALT_BASE, 0, 32); - - digest.doFinal(hashed, 0); - - String username = player.getName(); - authLoadingCache.evict(username); - - if(cnt > 0) { - synchronized(updatePassword) { - updatePassword.setBytes(1, hashed); - updatePassword.setBytes(2, randomBytes); - updatePassword.setString(3, uuid); - if(updatePassword.executeUpdate() <= 0) { - throw new AuthException("Update password query did not alter the database!"); - } - } - }else { - String sockAddr = sockAddrToString(player.getSocketAddress()); - if(maxRegistrationsPerIP > 0) { - if(countUsersOnIP(sockAddr) >= maxRegistrationsPerIP) { - throw new TooManyRegisteredOnIPException(sockAddr); - } - } - Date nowDate = new Date(System.currentTimeMillis()); - registerUser.setInt(1, 1); - registerUser.setString(2, uuid); - registerUser.setString(3, username); - LoginResult res = ((InitialHandler)player.getPendingConnection()).getLoginProfile(); - if(res != null) { - registerUser.setBytes(4, getTexturesProperty(res)); - }else { - registerUser.setBytes(4, null); - } - registerUser.setBytes(5, hashed); - registerUser.setBytes(6, randomBytes); - registerUser.setDate(7, nowDate); - registerUser.setString(8, sockAddr); - if(registerUser.executeUpdate() <= 0) { - throw new AuthException("Registration query did not alter the database!"); - } - } - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - } - - private static byte[] getTexturesProperty(LoginResult profile) { - try { - Property[] props = profile.getProperties(); - for(int i = 0; i < props.length; ++i) { - Property prop = props[i]; - if("textures".equals(prop.getName())) { - byte[] texturesData = Base64.decodeBase64(prop.getValue()); - byte[] signatureData = prop.getSignature() == null ? ArrayUtils.EMPTY_BYTE_ARRAY : Base64.decodeBase64(prop.getSignature()); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dao = new DataOutputStream(bao); - dao.writeInt(texturesData.length); - dao.writeInt(signatureData.length); - dao.write(texturesData); - dao.write(signatureData); - return bao.toByteArray(); - } - } - }catch(Throwable t) { - } - return null; - } - - public int pruneUsers(long before) throws AuthException { - try { - authLoadingCache.flush(); - synchronized(pruneUsers) { - pruneUsers.setDate(1, new Date(before)); - return pruneUsers.executeUpdate(); - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - - public int countUsersOnIP(String addr) throws AuthException { - synchronized(getRegistrationsOnIP) { - try { - getRegistrationsOnIP.setString(1, addr); - try(ResultSet set = getRegistrationsOnIP.executeQuery()) { - if(set.next()) { - return set.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved while counting accounts"); - } - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - } - - public void handleVanillaLogin(PostLoginEvent loginEvent) { - ProxiedPlayer player = loginEvent.getPlayer(); - PendingConnection con = player.getPendingConnection(); - if(!(con instanceof EaglerInitialHandler)) { - Date lastLogin = null; - String lastLoginIP = null; - boolean isRegistered = false; - synchronized(checkRegistrationByUUID) { - UUID uuid = player.getUniqueId(); - try { - String uuidString = getMojangUUID(uuid); - checkRegistrationByUUID.setString(1, getMojangUUID(player.getUniqueId())); - try(ResultSet res = checkRegistrationByUUID.executeQuery()) { - if(res.next()) { - isRegistered = true; - int vers = res.getInt(1); - String username = res.getString(2); - lastLogin = res.getDate(3); - lastLoginIP = res.getString(4); - String playerName = player.getName(); - if(!playerName.equals(username)) { - EaglerXBungee.logger().info("Player \"" + uuid.toString() + "\" changed their username from \"" + username - + "\" to \"" + playerName + "\", updating authentication database..."); - synchronized(updateMojangUsername) { - updateMojangUsername.setString(1, playerName); - updateMojangUsername.setString(2, uuidString); - if(updateMojangUsername.executeUpdate() == 0) { - throw new SQLException("Failed to update username to \"" + playerName + "\""); - } - } - } - } - } - byte[] texProperty = getTexturesProperty(((InitialHandler)con).getLoginProfile()); - if(texProperty != null) { - synchronized(updateTextures) { - updateTextures.setBytes(1, texProperty); - updateTextures.setString(2, uuidString); - updateTextures.executeUpdate(); - } - } - }catch(SQLException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "Could not look up UUID \"" + uuid.toString() + "\" in auth database!", ex); - } - } - if(isRegistered) { - if(lastLogin != null) { - String dateStr; - java.util.Date juLastLogin = new java.util.Date(lastLogin.getTime()); - Calendar calendar = Calendar.getInstance(); - int yearToday = calendar.get(Calendar.YEAR); - calendar.setTime(juLastLogin); - if(calendar.get(Calendar.YEAR) != yearToday) { - dateStr = (new SimpleDateFormat("EE, MMM d, yyyy, HH:mm z")).format(juLastLogin); - }else { - dateStr = (new SimpleDateFormat("EE, MMM d, HH:mm z")).format(juLastLogin); - } - TextComponent comp = new TextComponent(lastEaglerLoginMessage.replace("$date", dateStr).replace("$ip", "" + lastLoginIP)); - comp.setColor(ChatColor.GREEN); - player.sendMessage(comp); - } - player.sendMessage(new TextComponent(useChangeCommandText)); - }else { - player.sendMessage(new TextComponent(useRegisterCommandText)); - } - } - } - - private void destroyStatement(Statement stmt) { - try { - stmt.close(); - } catch (SQLException e) { - } - } - - public void flush() { - authLoadingCache.flush(); - } - - public void destroy() { - destroyStatement(registerUser); - destroyStatement(isRegisteredUser); - destroyStatement(pruneUsers); - destroyStatement(updatePassword); - destroyStatement(updateMojangUsername); - destroyStatement(getRegistrationsOnIP); - destroyStatement(checkRegistrationByUUID); - destroyStatement(checkRegistrationByName); - destroyStatement(setLastLogin); - destroyStatement(updateTextures); - try { - databaseConnection.close(); - EaglerXBungee.logger().info("Successfully disconnected from database '" + uri + "'"); - } catch (SQLException e) { - EaglerXBungee.logger().log(Level.WARNING, "Exception disconnecting from database '" + uri + "'!", e); - } - } - - public static class AuthException extends RuntimeException { - - public AuthException(String msg) { - super(msg); - } - - public AuthException(Throwable t) { - super(t); - } - - public AuthException(String msg, Throwable t) { - super(msg, t); - } - - } - - public static class TooManyRegisteredOnIPException extends AuthException { - - public TooManyRegisteredOnIPException(String ip) { - super(ip); - } - - } - - private static final String hexString = "0123456789abcdef"; - - private static final char[] HEX = new char[] { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - public static String getMojangUUID(UUID uuid) { - char[] ret = new char[32]; - long msb = uuid.getMostSignificantBits(); - long lsb = uuid.getLeastSignificantBits(); - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - ret[i] = HEX[(int)((msb >> j) & 15l)]; - ret[i + 16] = HEX[(int)((lsb >> j) & 15l)]; - } - return new String(ret); - } - - public static UUID parseMojangUUID(String uuid) { - long msb = 0l; - long lsb = 0l; - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - msb |= ((long)hexString.indexOf(uuid.charAt(i)) << j); - lsb |= ((long)hexString.indexOf(uuid.charAt(i + 16)) << j); - } - return new UUID(msb, lsb); - } - - private static String sockAddrToString(SocketAddress addr) { - if(addr instanceof InetSocketAddress) { - return ((InetSocketAddress)addr).getAddress().getHostAddress(); - }else { - return "127.0.0.1"; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/GeneralDigest.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/GeneralDigest.java deleted file mode 100644 index 9283c4ae..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/GeneralDigest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -/** - * base implementation of MD4 family style digest as outlined in "Handbook of - * Applied Cryptography", pages 344 - 347. - */ -public abstract class GeneralDigest { - private byte[] xBuf; - private int xBufOff; - - private long byteCount; - - /** - * Standard constructor - */ - protected GeneralDigest() { - xBuf = new byte[4]; - xBufOff = 0; - } - - /** - * Copy constructor. We are using copy constructors in place of the - * Object.clone() interface as this interface is not supported by J2ME. - */ - protected GeneralDigest(GeneralDigest t) { - xBuf = new byte[t.xBuf.length]; - System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); - - xBufOff = t.xBufOff; - byteCount = t.byteCount; - } - - public void update(byte in) { - xBuf[xBufOff++] = in; - - if (xBufOff == xBuf.length) { - processWord(xBuf, 0); - xBufOff = 0; - } - - byteCount++; - } - - public void update(byte[] in, int inOff, int len) { - // - // fill the current word - // - while ((xBufOff != 0) && (len > 0)) { - update(in[inOff]); - - inOff++; - len--; - } - - // - // process whole words. - // - while (len > xBuf.length) { - processWord(in, inOff); - - inOff += xBuf.length; - len -= xBuf.length; - byteCount += xBuf.length; - } - - // - // load in the remainder. - // - while (len > 0) { - update(in[inOff]); - - inOff++; - len--; - } - } - - public void finish() { - long bitLength = (byteCount << 3); - - // - // add the pad bytes. - // - update((byte) 128); - - while (xBufOff != 0) { - update((byte) 0); - } - - processLength(bitLength); - - processBlock(); - } - - public void reset() { - byteCount = 0; - - xBufOff = 0; - for (int i = 0; i < xBuf.length; i++) { - xBuf[i] = 0; - } - } - - protected abstract void processWord(byte[] in, int inOff); - - protected abstract void processLength(long bitLength); - - protected abstract void processBlock(); -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/HashUtils.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/HashUtils.java deleted file mode 100644 index 89a6dfab..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/HashUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -public class HashUtils { - - public static final byte[] EAGLER_SHA256_SALT_BASE = new byte[] { (byte) 117, (byte) 43, (byte) 1, (byte) 112, - (byte) 75, (byte) 3, (byte) 188, (byte) 61, (byte) 121, (byte) 31, (byte) 34, (byte) 181, (byte) 234, - (byte) 31, (byte) 247, (byte) 72, (byte) 12, (byte) 168, (byte) 138, (byte) 45, (byte) 143, (byte) 77, - (byte) 118, (byte) 245, (byte) 187, (byte) 242, (byte) 188, (byte) 219, (byte) 160, (byte) 235, (byte) 235, - (byte) 68 }; - - public static final byte[] EAGLER_SHA256_SALT_SAVE = new byte[] { (byte) 49, (byte) 25, (byte) 39, (byte) 38, - (byte) 253, (byte) 85, (byte) 70, (byte) 245, (byte) 71, (byte) 150, (byte) 253, (byte) 206, (byte) 4, - (byte) 26, (byte) 198, (byte) 249, (byte) 145, (byte) 251, (byte) 232, (byte) 174, (byte) 186, (byte) 98, - (byte) 27, (byte) 232, (byte) 55, (byte) 144, (byte) 83, (byte) 21, (byte) 36, (byte) 55, (byte) 170, - (byte) 118 }; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA1Digest.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA1Digest.java deleted file mode 100644 index 0bfbb9a6..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA1Digest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -/** - * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", - * pages 346 - 349. - * - * It is interesting to ponder why the, apart from the extra IV, the other - * difference here from MD5 is the "endienness" of the word processing! - */ -public class SHA1Digest extends GeneralDigest { - private static final int DIGEST_LENGTH = 20; - - private int H1, H2, H3, H4, H5; - - private int[] X = new int[80]; - private int xOff; - - /** - * Standard constructor - */ - public SHA1Digest() { - reset(); - } - - /** - * Copy constructor. This will copy the state of the provided message digest. - */ - public SHA1Digest(SHA1Digest t) { - super(t); - - H1 = t.H1; - H2 = t.H2; - H3 = t.H3; - H4 = t.H4; - H5 = t.H5; - - System.arraycopy(t.X, 0, X, 0, t.X.length); - xOff = t.xOff; - } - - public String getAlgorithmName() { - return "SHA-1"; - } - - public int getDigestSize() { - return DIGEST_LENGTH; - } - - protected void processWord(byte[] in, int inOff) { - X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) | ((in[inOff + 2] & 0xff) << 8) - | ((in[inOff + 3] & 0xff)); - - if (xOff == 16) { - processBlock(); - } - } - - private void unpackWord(int word, byte[] out, int outOff) { - out[outOff] = (byte) (word >>> 24); - out[outOff + 1] = (byte) (word >>> 16); - out[outOff + 2] = (byte) (word >>> 8); - out[outOff + 3] = (byte) word; - } - - protected void processLength(long bitLength) { - if (xOff > 14) { - processBlock(); - } - - X[14] = (int) (bitLength >>> 32); - X[15] = (int) (bitLength & 0xffffffff); - } - - public int doFinal(byte[] out, int outOff) { - finish(); - - unpackWord(H1, out, outOff); - unpackWord(H2, out, outOff + 4); - unpackWord(H3, out, outOff + 8); - unpackWord(H4, out, outOff + 12); - unpackWord(H5, out, outOff + 16); - - reset(); - - return DIGEST_LENGTH; - } - - /** - * reset the chaining variables - */ - public void reset() { - super.reset(); - - H1 = 0x67452301; - H2 = 0xefcdab89; - H3 = 0x98badcfe; - H4 = 0x10325476; - H5 = 0xc3d2e1f0; - - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - // - // Additive constants - // - private static final int Y1 = 0x5a827999; - private static final int Y2 = 0x6ed9eba1; - private static final int Y3 = 0x8f1bbcdc; - private static final int Y4 = 0xca62c1d6; - - private int f(int u, int v, int w) { - return ((u & v) | ((~u) & w)); - } - - private int h(int u, int v, int w) { - return (u ^ v ^ w); - } - - private int g(int u, int v, int w) { - return ((u & v) | (u & w) | (v & w)); - } - - private int rotateLeft(int x, int n) { - return (x << n) | (x >>> (32 - n)); - } - - protected void processBlock() { - // - // expand 16 word block into 80 word block. - // - for (int i = 16; i <= 79; i++) { - X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1); - } - - // - // set up working variables. - // - int A = H1; - int B = H2; - int C = H3; - int D = H4; - int E = H5; - - // - // round 1 - // - for (int j = 0; j <= 19; j++) { - int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 2 - // - for (int j = 20; j <= 39; j++) { - int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 3 - // - for (int j = 40; j <= 59; j++) { - int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 4 - // - for (int j = 60; j <= 79; j++) { - int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - H1 += A; - H2 += B; - H3 += C; - H4 += D; - H5 += E; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - private static final String hex = "0123456789abcdef"; - - public static String hash2string(byte[] b) { - char[] ret = new char[b.length * 2]; - for(int i = 0; i < b.length; ++i) { - int bb = (int)b[i] & 0xFF; - ret[i * 2] = hex.charAt((bb >> 4) & 0xF); - ret[i * 2 + 1] = hex.charAt(bb & 0xF); - } - return new String(ret); - } - -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA256Digest.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA256Digest.java deleted file mode 100644 index c57a9355..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/SHA256Digest.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth; - -public class SHA256Digest extends GeneralDigest { - - private static final int DIGEST_LENGTH = 32; - - private int H1, H2, H3, H4, H5, H6, H7, H8; - - private int[] X = new int[64]; - private int xOff; - - public SHA256Digest() { - reset(); - } - - public static int bigEndianToInt(byte[] bs, int off) { - int n = bs[off] << 24; - n |= (bs[++off] & 0xff) << 16; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff); - return n; - } - - public static void bigEndianToInt(byte[] bs, int off, int[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = bigEndianToInt(bs, off); - off += 4; - } - } - - public static byte[] intToBigEndian(int n) { - byte[] bs = new byte[4]; - intToBigEndian(n, bs, 0); - return bs; - } - - public static void intToBigEndian(int n, byte[] bs, int off) { - bs[off] = (byte) (n >>> 24); - bs[++off] = (byte) (n >>> 16); - bs[++off] = (byte) (n >>> 8); - bs[++off] = (byte) (n); - } - - protected void processWord(byte[] in, int inOff) { - X[xOff] = bigEndianToInt(in, inOff); - - if (++xOff == 16) { - processBlock(); - } - } - - protected void processLength(long bitLength) { - if (xOff > 14) { - processBlock(); - } - - X[14] = (int) (bitLength >>> 32); - X[15] = (int) (bitLength & 0xffffffff); - } - - public int doFinal(byte[] out, int outOff) { - finish(); - - intToBigEndian(H1, out, outOff); - intToBigEndian(H2, out, outOff + 4); - intToBigEndian(H3, out, outOff + 8); - intToBigEndian(H4, out, outOff + 12); - intToBigEndian(H5, out, outOff + 16); - intToBigEndian(H6, out, outOff + 20); - intToBigEndian(H7, out, outOff + 24); - intToBigEndian(H8, out, outOff + 28); - - reset(); - - return DIGEST_LENGTH; - } - - /** - * reset the chaining variables - */ - public void reset() { - super.reset(); - - /* - * SHA-256 initial hash value The first 32 bits of the fractional parts of the - * square roots of the first eight prime numbers - */ - - H1 = 0x6a09e667; - H2 = 0xbb67ae85; - H3 = 0x3c6ef372; - H4 = 0xa54ff53a; - H5 = 0x510e527f; - H6 = 0x9b05688c; - H7 = 0x1f83d9ab; - H8 = 0x5be0cd19; - - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - protected void processBlock() { - // - // expand 16 word block into 64 word blocks. - // - for (int t = 16; t <= 63; t++) { - X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16]; - } - - // - // set up working variables. - // - int a = H1; - int b = H2; - int c = H3; - int d = H4; - int e = H5; - int f = H6; - int g = H7; - int h = H8; - - int t = 0; - for (int i = 0; i < 8; i++) { - // t = 8 * i - h += Sum1(e) + Ch(e, f, g) + K[t] + X[t]; - d += h; - h += Sum0(a) + Maj(a, b, c); - ++t; - - // t = 8 * i + 1 - g += Sum1(d) + Ch(d, e, f) + K[t] + X[t]; - c += g; - g += Sum0(h) + Maj(h, a, b); - ++t; - - // t = 8 * i + 2 - f += Sum1(c) + Ch(c, d, e) + K[t] + X[t]; - b += f; - f += Sum0(g) + Maj(g, h, a); - ++t; - - // t = 8 * i + 3 - e += Sum1(b) + Ch(b, c, d) + K[t] + X[t]; - a += e; - e += Sum0(f) + Maj(f, g, h); - ++t; - - // t = 8 * i + 4 - d += Sum1(a) + Ch(a, b, c) + K[t] + X[t]; - h += d; - d += Sum0(e) + Maj(e, f, g); - ++t; - - // t = 8 * i + 5 - c += Sum1(h) + Ch(h, a, b) + K[t] + X[t]; - g += c; - c += Sum0(d) + Maj(d, e, f); - ++t; - - // t = 8 * i + 6 - b += Sum1(g) + Ch(g, h, a) + K[t] + X[t]; - f += b; - b += Sum0(c) + Maj(c, d, e); - ++t; - - // t = 8 * i + 7 - a += Sum1(f) + Ch(f, g, h) + K[t] + X[t]; - e += a; - a += Sum0(b) + Maj(b, c, d); - ++t; - } - - H1 += a; - H2 += b; - H3 += c; - H4 += d; - H5 += e; - H6 += f; - H7 += g; - H8 += h; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - for (int i = 0; i < 16; i++) { - X[i] = 0; - } - } - - /* SHA-256 functions */ - private static int Ch(int x, int y, int z) { - return (x & y) ^ ((~x) & z); -// return z ^ (x & (y ^ z)); - } - - private static int Maj(int x, int y, int z) { -// return (x & y) ^ (x & z) ^ (y & z); - return (x & y) | (z & (x ^ y)); - } - - private static int Sum0(int x) { - return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10)); - } - - private static int Sum1(int x) { - return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7)); - } - - private static int Theta0(int x) { - return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3); - } - - private static int Theta1(int x) { - return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10); - } - - /* - * SHA-256 Constants (represent the first 32 bits of the fractional parts of the - * cube roots of the first sixty-four prime numbers) - */ - static final int K[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, - 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, - 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, - 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, - 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, - 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; - -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandClientBrand.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandClientBrand.java deleted file mode 100644 index 6e720ab6..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandClientBrand.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import io.netty.buffer.Unpooled; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.OverflowPacketException; -import net.md_5.bungee.protocol.packet.PluginMessage; - -public class CommandClientBrand extends Command { - - public CommandClientBrand() { - super("client-brand", "eaglercraft.command.clientbrand", "clientbrand"); - } - - @Override - public void execute(CommandSender var1, String[] var2) { - if(var2.length == 1) { - ProxiedPlayer player = BungeeCord.getInstance().getPlayer(var2[0]); - if(player != null) { - if(player.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler handler = (EaglerInitialHandler)player.getPendingConnection(); - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client Brand: " + ChatColor.WHITE + handler.getEaglerBrandString())); - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client Version: " + ChatColor.WHITE + handler.getEaglerVersionString())); - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client UUID: " + ChatColor.WHITE + handler.getClientBrandUUID())); - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Minecraft Client Brand: " + ChatColor.WHITE + decodeMCBrand(handler.getBrandMessage()))); - }else { - var1.sendMessage(new TextComponent(ChatColor.RED + "That player is not using eaglercraft!")); - } - }else { - var1.sendMessage(new TextComponent(ChatColor.RED + "That player was not found!")); - } - return; - } - if(var2.length == 2) { - ProxiedPlayer player = BungeeCord.getInstance().getPlayer(var2[1]); - if(player != null) { - if(player.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler handler = (EaglerInitialHandler)player.getPendingConnection(); - if("uuid".equalsIgnoreCase(var2[0])) { - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client UUID: " + ChatColor.WHITE + handler.getClientBrandUUID())); - return; - }else if("name".equalsIgnoreCase(var2[0])) { - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client Brand: " + ChatColor.WHITE + handler.getEaglerBrandString())); - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Eagler Client Version: " + ChatColor.WHITE + handler.getEaglerVersionString())); - return; - }else if("mc".equalsIgnoreCase(var2[0])) { - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Minecraft Client Brand: " + ChatColor.WHITE + decodeMCBrand(handler.getBrandMessage()))); - return; - } - }else { - var1.sendMessage(new TextComponent(ChatColor.RED + "That player is not using eaglercraft!")); - return; - } - }else { - var1.sendMessage(new TextComponent(ChatColor.RED + "That player was not found!")); - return; - } - } - var1.sendMessage(new TextComponent(ChatColor.RED + "Usage: /client-brand [uuid|name|mc] ")); - } - - private static String decodeMCBrand(PluginMessage pkt) { - if(pkt == null) { - return "null"; - } - try { - return DefinedPacket.readString(Unpooled.wrappedBuffer(pkt.getData()), 64); - }catch(OverflowPacketException | IndexOutOfBoundsException ex) { - return "null"; - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandConfirmCode.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandConfirmCode.java deleted file mode 100644 index 25859ecc..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandConfirmCode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.SHA1Digest; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.plugin.Command; - -public class CommandConfirmCode extends Command { - - public static String confirmHash = null; - - public CommandConfirmCode() { - super("confirm-code", "eaglercraft.command.confirmcode", "confirmcode"); - } - - @Override - public void execute(CommandSender var1, String[] var2) { - if(var2.length != 1) { - var1.sendMessage(new TextComponent(ChatColor.RED + "How to use: " + ChatColor.WHITE + "/confirm-code ")); - }else { - var1.sendMessage(new TextComponent(ChatColor.YELLOW + "Server list 2FA code has been set to: " + ChatColor.GREEN + var2[0])); - var1.sendMessage(new TextComponent(ChatColor.YELLOW + "You can now return to the server list site and continue")); - byte[] bts = var2[0].getBytes(StandardCharsets.US_ASCII); - SHA1Digest dg = new SHA1Digest(); - dg.update(bts, 0, bts.length); - byte[] f = new byte[20]; - dg.doFinal(f, 0); - confirmHash = SHA1Digest.hash2string(f); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandDomain.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandDomain.java deleted file mode 100644 index 70616a93..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandDomain.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Command; - -public class CommandDomain extends Command { - - public CommandDomain() { - super("domain", "eaglercraft.command.domain"); - } - - @Override - public void execute(CommandSender var1, String[] var2) { - if(var2.length != 1) { - var1.sendMessage(new TextComponent(ChatColor.RED + "How to use: " + ChatColor.WHITE + "/domain ")); - }else { - ProxiedPlayer player = ProxyServer.getInstance().getPlayer(var2[0]); - if(player == null) { - var1.sendMessage(new TextComponent(ChatColor.RED + "That user is not online")); - return; - } - PendingConnection conn = player.getPendingConnection(); - if(!(conn instanceof EaglerInitialHandler)) { - var1.sendMessage(new TextComponent(ChatColor.RED + "That user is not using Eaglercraft")); - return; - } - String origin = ((EaglerInitialHandler)conn).getOrigin(); - if(origin != null) { - var1.sendMessage(new TextComponent(ChatColor.BLUE + "Domain of " + var2[0] + " is '" + origin + "'")); - }else { - var1.sendMessage(new TextComponent(ChatColor.RED + "That user's browser did not send an origin header")); - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerPurge.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerPurge.java deleted file mode 100644 index e29a9629..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerPurge.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import java.util.logging.Level; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem.AuthException; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.command.ConsoleCommandSender; - -public class CommandEaglerPurge extends Command { - - public CommandEaglerPurge(String name) { - super(name + "-purge", "eaglercraft.command.purge"); - } - - @Override - public void execute(CommandSender var1, String[] var2) { - if(var1 instanceof ConsoleCommandSender) { - if(var2.length != 1) { - TextComponent comp = new TextComponent("Use /" + getName() + " "); - comp.setColor(ChatColor.RED); - var1.sendMessage(comp); - return; - } - int mx; - try { - mx = Integer.parseInt(var2[0]); - }catch(NumberFormatException ex) { - TextComponent comp = new TextComponent("'" + var2[0] + "' is not an integer!"); - comp.setColor(ChatColor.RED); - var1.sendMessage(comp); - return; - } - EaglerAuthConfig authConf = EaglerXBungee.getEagler().getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = EaglerXBungee.getEagler().getAuthService(); - if(srv != null) { - int cnt; - try { - EaglerXBungee.logger().warning("Console is attempting to purge all accounts with " + mx + " days of inactivity"); - cnt = srv.pruneUsers(System.currentTimeMillis() - mx * 86400000l); - }catch(AuthException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "Failed to purge accounts", ex); - TextComponent comp = new TextComponent("Failed to purge, check log! Reason: " + ex.getMessage()); - comp.setColor(ChatColor.AQUA); - var1.sendMessage(comp); - return; - } - EaglerXBungee.logger().warning("Console purged " + cnt + " accounts from auth database"); - TextComponent comp = new TextComponent("Purged " + cnt + " old accounts from the database"); - comp.setColor(ChatColor.AQUA); - var1.sendMessage(comp); - } - } - }else { - TextComponent comp = new TextComponent("This command can only be run from the console!"); - comp.setColor(ChatColor.RED); - var1.sendMessage(comp); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerRegister.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerRegister.java deleted file mode 100644 index 744d34d5..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandEaglerRegister.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import java.util.logging.Level; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.plugin.Command; - -public class CommandEaglerRegister extends Command { - - public CommandEaglerRegister(String name) { - super(name); - } - - @Override - public void execute(CommandSender sender, String[] args) { - if(sender instanceof ProxiedPlayer) { - ProxiedPlayer player = (ProxiedPlayer)sender; - if(args.length != 1) { - TextComponent comp = new TextComponent("Use: /" + getName() + " "); - comp.setColor(ChatColor.RED); - player.sendMessage(comp); - return; - } - EaglerAuthConfig authConf = EaglerXBungee.getEagler().getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = EaglerXBungee.getEagler().getAuthService(); - if(srv != null) { - if(!(player.getPendingConnection() instanceof EaglerInitialHandler)) { - try { - srv.processSetPassword(player, args[0]); - sender.sendMessage(new TextComponent(authConf.getCommandSuccessText())); - }catch(DefaultAuthSystem.TooManyRegisteredOnIPException ex) { - String tooManyReg = authConf.getTooManyRegistrationsMessage(); - sender.sendMessage(new TextComponent(tooManyReg)); - }catch(DefaultAuthSystem.AuthException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "Internal exception while processing password change from \"" + player.getName() + "\"", ex); - TextComponent comp = new TextComponent("Internal error, check console logs"); - comp.setColor(ChatColor.RED); - sender.sendMessage(comp); - } - }else { - player.sendMessage(new TextComponent(authConf.getNeedVanillaToRegisterMessage())); - } - } - } - }else { - TextComponent comp = new TextComponent("You must be a player to use this command!"); - comp.setColor(ChatColor.RED); - sender.sendMessage(comp); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandRatelimit.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandRatelimit.java deleted file mode 100644 index 7af384da..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/command/CommandRatelimit.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerRateLimiter; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.plugin.Command; - -public class CommandRatelimit extends Command { - - public CommandRatelimit() { - super("ratelimit", "eaglercraft.command.ratelimit"); - } - - @Override - public void execute(CommandSender sender, String[] args) { - if((args.length != 1 && args.length != 2) || !args[0].equalsIgnoreCase("reset")) { - TextComponent comp = new TextComponent("Usage: /ratelimit reset [ip|login|motd|query]"); //TODO: allow reset ratelimit on specific listeners - comp.setColor(ChatColor.RED); - sender.sendMessage(comp); - }else { - int resetNum = 0; - if(args.length == 2) { - if(args[1].equalsIgnoreCase("ip")) { - resetNum = 1; - }else if(args[1].equalsIgnoreCase("login")) { - resetNum = 2; - }else if(args[1].equalsIgnoreCase("motd")) { - resetNum = 3; - }else if(args[1].equalsIgnoreCase("query")) { - resetNum = 4; - }else { - TextComponent comp = new TextComponent("Unknown ratelimit '" + args[1] + "'!"); - comp.setColor(ChatColor.RED); - sender.sendMessage(comp); - return; - } - } - EaglerBungeeConfig conf = EaglerXBungee.getEagler().getConfig(); - for(EaglerListenerConfig listener : conf.getServerListeners()) { - if(resetNum == 0 || resetNum == 1) { - EaglerRateLimiter limiter = listener.getRatelimitIp(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 2) { - EaglerRateLimiter limiter = listener.getRatelimitLogin(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 3) { - EaglerRateLimiter limiter = listener.getRatelimitMOTD(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 4) { - EaglerRateLimiter limiter = listener.getRatelimitQuery(); - if(limiter != null) { - limiter.reset(); - } - } - } - sender.sendMessage(new TextComponent("Ratelimits reset.")); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerAuthConfig.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerAuthConfig.java deleted file mode 100644 index 225c271e..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerAuthConfig.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.config.Configuration; - -public class EaglerAuthConfig { - - static EaglerAuthConfig loadConfig(Configuration config) { - boolean enableAuthentication = config.getBoolean("enable_authentication_system"); - boolean useBuiltInAuthentication = config.getBoolean("use_onboard_eaglerx_system"); - String databaseURI = config.getString("auth_db_uri"); - String driverClass = config.getString("sql_driver_class", "internal"); - String driverPath = config.getString("sql_driver_path", null); - String passwordPromptScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("password_prompt_screen_text", "")); - String notRegisteredScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("not_registered_screen_text", "")); - String wrongPasswordScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("wrong_password_screen_text", "")); - String eaglerCommandName = config.getString("eagler_command_name"); - String useRegisterCommandText = ChatColor.translateAlternateColorCodes('&', config.getString("use_register_command_text", "")); - String useChangeCommandText = ChatColor.translateAlternateColorCodes('&', config.getString("use_change_command_text", "")); - String commandSuccessText = ChatColor.translateAlternateColorCodes('&', config.getString("command_success_text", "")); - String lastEaglerLoginMessage = ChatColor.translateAlternateColorCodes('&', config.getString("last_eagler_login_message", "")); - String tooManyRegistrationsMessage = ChatColor.translateAlternateColorCodes('&', config.getString("too_many_registrations_message", "")); - String needVanillaToRegisterMessage = ChatColor.translateAlternateColorCodes('&', config.getString("need_vanilla_to_register_message", "")); - boolean overrideEaglerToVanillaSkins = config.getBoolean("override_eagler_to_vanilla_skins"); - int maxRegistrationsPerIP = config.getInt("max_registration_per_ip", -1); - return new EaglerAuthConfig(enableAuthentication, useBuiltInAuthentication, databaseURI, driverClass, - driverPath, passwordPromptScreenText, wrongPasswordScreenText, notRegisteredScreenText, - eaglerCommandName, useRegisterCommandText, useChangeCommandText, commandSuccessText, - lastEaglerLoginMessage, tooManyRegistrationsMessage, needVanillaToRegisterMessage, - overrideEaglerToVanillaSkins, maxRegistrationsPerIP); - } - - private boolean enableAuthentication; - private boolean useBuiltInAuthentication; - - private final String databaseURI; - private final String driverClass; - private final String driverPath; - private final String passwordPromptScreenText; - private final String wrongPasswordScreenText; - private final String notRegisteredScreenText; - private final String eaglerCommandName; - private final String useRegisterCommandText; - private final String useChangeCommandText; - private final String commandSuccessText; - private final String lastEaglerLoginMessage; - private final String tooManyRegistrationsMessage; - private final String needVanillaToRegisterMessage; - private final boolean overrideEaglerToVanillaSkins; - private final int maxRegistrationsPerIP; - - private EaglerAuthConfig(boolean enableAuthentication, boolean useBuiltInAuthentication, String databaseURI, - String driverClass, String driverPath, String passwordPromptScreenText, String wrongPasswordScreenText, - String notRegisteredScreenText, String eaglerCommandName, String useRegisterCommandText, - String useChangeCommandText, String commandSuccessText, String lastEaglerLoginMessage, - String tooManyRegistrationsMessage, String needVanillaToRegisterMessage, - boolean overrideEaglerToVanillaSkins, int maxRegistrationsPerIP) { - this.enableAuthentication = enableAuthentication; - this.useBuiltInAuthentication = useBuiltInAuthentication; - this.databaseURI = databaseURI; - this.driverClass = driverClass; - this.driverPath = driverPath; - this.passwordPromptScreenText = passwordPromptScreenText; - this.wrongPasswordScreenText = wrongPasswordScreenText; - this.notRegisteredScreenText = notRegisteredScreenText; - this.eaglerCommandName = eaglerCommandName; - this.useRegisterCommandText = useRegisterCommandText; - this.useChangeCommandText = useChangeCommandText; - this.commandSuccessText = commandSuccessText; - this.lastEaglerLoginMessage = lastEaglerLoginMessage; - this.tooManyRegistrationsMessage = tooManyRegistrationsMessage; - this.needVanillaToRegisterMessage = needVanillaToRegisterMessage; - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - this.maxRegistrationsPerIP = maxRegistrationsPerIP; - } - - public boolean isEnableAuthentication() { - return enableAuthentication; - } - - public boolean isUseBuiltInAuthentication() { - return useBuiltInAuthentication; - } - - public void triggerOnlineModeDisabled() { - enableAuthentication = false; - useBuiltInAuthentication = false; - } - - public String getDatabaseURI() { - return databaseURI; - } - - public String getDriverClass() { - return driverClass; - } - - public String getDriverPath() { - return driverPath; - } - - public String getPasswordPromptScreenText() { - return passwordPromptScreenText; - } - - public String getWrongPasswordScreenText() { - return wrongPasswordScreenText; - } - - public String getNotRegisteredScreenText() { - return notRegisteredScreenText; - } - - public String getEaglerCommandName() { - return eaglerCommandName; - } - - public String getUseRegisterCommandText() { - return useRegisterCommandText; - } - - public String getUseChangeCommandText() { - return useChangeCommandText; - } - - public String getCommandSuccessText() { - return commandSuccessText; - } - - public String getLastEaglerLoginMessage() { - return lastEaglerLoginMessage; - } - - public String getTooManyRegistrationsMessage() { - return tooManyRegistrationsMessage; - } - - public String getNeedVanillaToRegisterMessage() { - return needVanillaToRegisterMessage; - } - - public boolean getOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } - - public int getMaxRegistrationsPerIP() { - return maxRegistrationsPerIP; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerBungeeConfig.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerBungeeConfig.java deleted file mode 100644 index 2ddc23f1..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerBungeeConfig.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpContentType; -import net.md_5.bungee.config.Configuration; -import net.md_5.bungee.config.ConfigurationProvider; -import net.md_5.bungee.config.YamlConfiguration; -import net.md_5.bungee.protocol.Property; - -public class EaglerBungeeConfig { - - public static EaglerBungeeConfig loadConfig(File directory) throws IOException { - Map contentTypes = new HashMap<>(); - - try(InputStream is = new FileInputStream(getConfigFile(directory, "http_mime_types.json"))) { - loadMimeTypes(is, contentTypes); - }catch(Throwable t) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_http_mime_types.json")) { - loadMimeTypes(is, contentTypes); - }catch(IOException ex) { - EaglerXBungee.logger().severe("Could not load default_http_mime_types.json!"); - throw new RuntimeException(ex); - } - } - - directory.mkdirs(); - ConfigurationProvider prov = ConfigurationProvider.getProvider(YamlConfiguration.class); - - Configuration configYml = prov.load(getConfigFile(directory, "settings.yml")); - String serverName = configYml.getString("server_name", "EaglercraftXBungee Server"); - EaglerXBungeeAPIHelper.getTemplateGlobals().put("server_name", serverName); - String serverUUIDString = configYml.getString("server_uuid", null); - if(serverUUIDString == null) { - throw new IOException("You must specify a server_uuid!"); - } - - UUID serverUUID = null; - try { - serverUUID = UUID.fromString(serverUUIDString); - }catch(Throwable t) { - } - - if(serverUUID == null) { - throw new IOException("The server_uuid \"" + serverUUIDString + "\" is invalid!"); - } - - Configuration listenerYml = prov.load(getConfigFile(directory, "listeners.yml")); - Iterator listeners = listenerYml.getKeys().iterator(); - Map serverListeners = new HashMap<>(); - boolean voiceChat = false; - - while(listeners.hasNext()) { - String name = listeners.next(); - EaglerListenerConfig conf = EaglerListenerConfig.loadConfig(listenerYml.getSection(name), contentTypes); - if(conf != null) { - serverListeners.put(name, conf); - voiceChat |= conf.getEnableVoiceChat(); - }else { - EaglerXBungee.logger().severe("Invalid listener config: " + name); - } - } - - if(serverListeners.size() == 0) { - EaglerXBungee.logger().severe("No Listeners Configured!"); - } - - Configuration authserivceYml = prov.load(getConfigFile(directory, "authservice.yml")); - EaglerAuthConfig authConfig = EaglerAuthConfig.loadConfig(authserivceYml); - - Configuration updatesYml = prov.load(getConfigFile(directory, "updates.yml")); - EaglerUpdateConfig updatesConfig = EaglerUpdateConfig.loadConfig(updatesYml); - - Configuration iceServersYml = prov.load(getConfigFile(directory, "ice_servers.yml")); - Collection iceServers = loadICEServers(iceServersYml); - - if(authConfig.isEnableAuthentication()) { - for(EaglerListenerConfig lst : serverListeners.values()) { - if(lst.getRatelimitLogin() != null) lst.getRatelimitLogin().setDivisor(2); - if(lst.getRatelimitIp() != null) lst.getRatelimitIp().setDivisor(2); - } - } - - File pauseMenuFolder = new File(directory, "pause_menu"); - if(!pauseMenuFolder.isDirectory() && !pauseMenuFolder.mkdir()) { - throw new IOException("Could not create directory: " + pauseMenuFolder.getAbsolutePath()); - } - - File pauseMenuYml = new File(pauseMenuFolder, "pause_menu.yml"); - if(!pauseMenuYml.isFile()) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_pause_menu.yml")) { - copyConfigFile(is, pauseMenuYml); - } - File f2 = new File(pauseMenuFolder, "server_info.html"); - if(!f2.isFile()) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_pause_menu_server_info.html")) { - copyConfigFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "test_image.png"); - if(!f2.isFile()) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_pause_menu_test_image.png")) { - copyBinaryFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "message_api_example.html"); - if(!f2.isFile()) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_message_api_example.html")) { - copyConfigFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "message_api_v1.js"); - if(!f2.isFile()) { - try(InputStream is = EaglerBungeeConfig.class.getResourceAsStream("default_message_api_v1.js")) { - copyConfigFile(is, f2); - } - } - } - EaglerPauseMenuConfig pauseMenuConfig = EaglerPauseMenuConfig.loadConfig(prov.load(pauseMenuYml), pauseMenuFolder); - - long websocketKeepAliveTimeout = configYml.getInt("websocket_connection_timeout", 15000); - long websocketHandshakeTimeout = configYml.getInt("websocket_handshake_timeout", 5000); - long builtinHttpServerTimeout = configYml.getInt("builtin_http_server_timeout", 10000); - int websocketCompressionLevel = configYml.getInt("http_websocket_compression_level", 6); - - boolean downloadVanillaSkins = configYml.getBoolean("download_vanilla_skins_to_clients", false); - Collection validSkinUrls = (Collection)configYml.getList("valid_skin_download_urls"); - int uuidRateLimitPlayer = configYml.getInt("uuid_lookup_ratelimit_player", 50); - int uuidRateLimitGlobal = configYml.getInt("uuid_lookup_ratelimit_global", 175); - int skinRateLimitPlayer = configYml.getInt("skin_download_ratelimit_player", 1000); - int skinRateLimitGlobal = configYml.getInt("skin_download_ratelimit_global", 30000); - - String skinCacheURI = configYml.getString("skin_cache_db_uri", "jdbc:sqlite:eaglercraft_skins_cache.db"); - int keepObjectsDays = configYml.getInt("skin_cache_keep_objects_days", 45); - int keepProfilesDays = configYml.getInt("skin_cache_keep_profiles_days", 7); - int maxObjects = configYml.getInt("skin_cache_max_objects", 32768); - int maxProfiles = configYml.getInt("skin_cache_max_profiles", 32768); - int antagonistsRateLimit = configYml.getInt("skin_cache_antagonists_ratelimit", 15); - String sqliteDriverClass = configYml.getString("sql_driver_class", "internal"); - String sqliteDriverPath = configYml.getString("sql_driver_path", null); - String eaglerPlayersVanillaSkin = configYml.getString("eagler_players_vanilla_skin", null); - if(eaglerPlayersVanillaSkin != null && eaglerPlayersVanillaSkin.length() == 0) { - eaglerPlayersVanillaSkin = null; - } - boolean enableIsEaglerPlayerProperty = configYml.getBoolean("enable_is_eagler_player_property", true); - Set disableVoiceOnServers = new HashSet<>((Collection)configYml.getList("disable_voice_chat_on_servers")); - boolean disableFNAWSkinsEverywhere = configYml.getBoolean("disable_fnaw_skins_everywhere", false); - Set disableFNAWSkinsOnServers = new HashSet<>((Collection)configYml.getList("disable_fnaw_skins_on_servers")); - boolean enableBackendRPCAPI = configYml.getBoolean("enable_backend_rpc_api", false); - boolean useModernizedChannelNames = configYml.getBoolean("use_modernized_channel_names", false); - - final EaglerBungeeConfig ret = new EaglerBungeeConfig(serverName, serverUUID, websocketKeepAliveTimeout, - websocketHandshakeTimeout, builtinHttpServerTimeout, websocketCompressionLevel, serverListeners, - contentTypes, downloadVanillaSkins, validSkinUrls, uuidRateLimitPlayer, uuidRateLimitGlobal, - skinRateLimitPlayer, skinRateLimitGlobal, skinCacheURI, keepObjectsDays, keepProfilesDays, maxObjects, - maxProfiles, antagonistsRateLimit, sqliteDriverClass, sqliteDriverPath, eaglerPlayersVanillaSkin, - enableIsEaglerPlayerProperty, authConfig, updatesConfig, iceServers, voiceChat, disableVoiceOnServers, - disableFNAWSkinsEverywhere, disableFNAWSkinsOnServers, enableBackendRPCAPI, useModernizedChannelNames, - pauseMenuConfig); - - if(eaglerPlayersVanillaSkin != null) { - VanillaDefaultSkinProfileLoader.lookupVanillaSkinUser(ret); - } - - return ret; - } - - private static File getConfigFile(File directory, String fileName) throws IOException { - File file = new File(directory, fileName); - if(!file.isFile()) { - try (BufferedReader is = new BufferedReader(new InputStreamReader( - EaglerBungeeConfig.class.getResourceAsStream("default_" + fileName), StandardCharsets.UTF_8)); - PrintWriter os = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { - String line; - while((line = is.readLine()) != null) { - if(line.contains("${")) { - line = line.replace("${random_uuid}", UUID.randomUUID().toString()); - } - os.println(line); - } - } - } - return file; - } - - private static void copyConfigFile(InputStream is, File file) throws IOException { - try(PrintWriter os = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - String line; - while((line = reader.readLine()) != null) { - os.println(line); - } - } - } - - private static void copyBinaryFile(InputStream is, File file) throws IOException { - try(OutputStream os = new FileOutputStream(file)) { - byte[] copyBuffer = new byte[1024]; - int i; - while((i = is.read(copyBuffer)) != -1) { - os.write(copyBuffer, 0, i); - } - } - } - - private static void loadMimeTypes(InputStream file, Map contentTypes) throws IOException { - JsonObject obj = parseJsonObject(file); - for(Entry etr : obj.entrySet()) { - String mime = etr.getKey(); - try { - JsonObject e = etr.getValue().getAsJsonObject(); - JsonArray arr = e.getAsJsonArray("files"); - if(arr == null || arr.size() == 0) { - EaglerXBungee.logger().warning("MIME type '" + mime + "' defines no extensions!"); - continue; - } - HashSet exts = new HashSet<>(); - for(int i = 0, l = arr.size(); i < l; ++i) { - exts.add(arr.get(i).getAsString()); - } - long expires = 0l; - JsonElement ex = e.get("expires"); - if(ex != null) { - expires = ex.getAsInt() * 1000l; - } - String charset = null; - ex = e.get("charset"); - if(ex != null) { - charset = ex.getAsString(); - } - HttpContentType typeObj = new HttpContentType(exts, mime, charset, expires); - for(String s : exts) { - contentTypes.put(s, typeObj); - } - }catch(Throwable t) { - EaglerXBungee.logger().warning("Exception parsing MIME type '" + mime + "' - " + t.toString()); - } - } - } - - private static Collection loadICEServers(Configuration config) { - Collection ret = new ArrayList<>(config.contains("voice_stun_servers") ? (List)config.getList("voice_stun_servers") : (List)config.getList("voice_servers_no_passwd")); - Configuration turnServers = config.contains("voice_turn_servers") ? config.getSection("voice_turn_servers") : config.getSection("voice_servers_passwd"); - Iterator turnItr = turnServers.getKeys().iterator(); - while(turnItr.hasNext()) { - String name = turnItr.next(); - Configuration turnSvr = turnServers.getSection(name); - ret.add(turnSvr.getString("url") + ";" + turnSvr.getString("username") + ";" + turnSvr.getString("password")); - } - return ret; - } - - private static JsonObject parseJsonObject(InputStream file) throws IOException { - try { - return JsonParser.parseReader(new InputStreamReader(file, StandardCharsets.UTF_8)).getAsJsonObject(); - }catch(JsonSyntaxException ex) { - throw new IOException("Invalid JSONObject", ex); - } - } - - public static final Property isEaglerProperty = new Property("isEaglerPlayer", "true"); - - private final String serverName; - private final UUID serverUUID; - private final long websocketKeepAliveTimeout; - private final long websocketHandshakeTimeout; - private final long builtinHttpServerTimeout; - private final int httpWebsocketCompressionLevel; - private final Map serverListeners; - private final Map contentTypes; - private final boolean downloadVanillaSkins; - private final Collection validSkinUrls; - private final int uuidRateLimitPlayer; - private final int uuidRateLimitGlobal; - private final int skinRateLimitPlayer; - private final int skinRateLimitGlobal; - private final String skinCacheURI; - private final int keepObjectsDays; - private final int keepProfilesDays; - private final int maxObjects; - private final int maxProfiles; - private final int antagonistsRateLimit; - private final String sqliteDriverClass; - private final String sqliteDriverPath; - private final String eaglerPlayersVanillaSkin; - private final boolean enableIsEaglerPlayerProperty; - private final EaglerAuthConfig authConfig; - private final EaglerUpdateConfig updateConfig; - private final Collection iceServers; - private final boolean enableVoiceChat; - private final Set disableVoiceOnServers; - private final boolean disableFNAWSkinsEverywhere; - private final Set disableFNAWSkinsOnServers; - private final boolean enableBackendRPCAPI; - private final boolean useModernizedChannelNames; - private final EaglerPauseMenuConfig pauseMenuConf; - private boolean isCrackedFlag; - Property[] eaglerPlayersVanillaSkinCached = new Property[] { isEaglerProperty }; - - public String getServerName() { - return serverName; - } - - public UUID getServerUUID() { - return serverUUID; - } - - public long getWebsocketKeepAliveTimeout() { - return websocketKeepAliveTimeout; - } - - public long getWebsocketHandshakeTimeout() { - return websocketHandshakeTimeout; - } - - public long getBuiltinHttpServerTimeout() { - return builtinHttpServerTimeout; - } - - public int getHttpWebsocketCompressionLevel() { - return httpWebsocketCompressionLevel; - } - - public Collection getServerListeners() { - return serverListeners.values(); - } - - public EaglerListenerConfig getServerListenersByName(String name) { - return serverListeners.get(name); - } - - public Map getContentType() { - return contentTypes; - } - - public Map getContentTypes() { - return contentTypes; - } - - public boolean getDownloadVanillaSkins() { - return downloadVanillaSkins; - } - - public Collection getValidSkinUrls() { - return validSkinUrls; - } - - public boolean isValidSkinHost(String host) { - host = host.toLowerCase(); - for(String str : validSkinUrls) { - if(str.length() > 0) { - str = str.toLowerCase(); - if(str.charAt(0) == '*') { - if(host.endsWith(str.substring(1))) { - return true; - } - }else { - if(host.equals(str)) { - return true; - } - } - } - } - return false; - } - - public int getUuidRateLimitPlayer() { - return uuidRateLimitPlayer; - } - - public int getUuidRateLimitGlobal() { - return uuidRateLimitGlobal; - } - - public int getSkinRateLimitPlayer() { - return skinRateLimitPlayer; - } - - public int getSkinRateLimitGlobal() { - return skinRateLimitGlobal; - } - - public String getSkinCacheURI() { - return skinCacheURI; - } - - public String getSQLiteDriverClass() { - return sqliteDriverClass; - } - - public String getSQLiteDriverPath() { - return sqliteDriverPath; - } - - public int getKeepObjectsDays() { - return keepObjectsDays; - } - - public int getKeepProfilesDays() { - return keepProfilesDays; - } - - public int getMaxObjects() { - return maxObjects; - } - - public int getMaxProfiles() { - return maxProfiles; - } - - public int getAntagonistsRateLimit() { - return antagonistsRateLimit; - } - - public String getEaglerPlayersVanillaSkin() { - return eaglerPlayersVanillaSkin; - } - - public boolean getEnableIsEaglerPlayerProperty() { - return enableIsEaglerPlayerProperty; - } - - public Property[] getEaglerPlayersVanillaSkinProperties() { - return eaglerPlayersVanillaSkinCached; - } - - public boolean isCracked() { - return isCrackedFlag; - } - - public void setCracked(boolean cracked) { - isCrackedFlag = cracked; - } - - public EaglerAuthConfig getAuthConfig() { - return authConfig; - } - - public EaglerUpdateConfig getUpdateConfig() { - return updateConfig; - } - - public Collection getICEServers() { - return iceServers; - } - - public boolean getEnableVoiceChat() { - return enableVoiceChat; - } - - public Set getDisableVoiceOnServersSet() { - return disableVoiceOnServers; - } - - public boolean getDisableFNAWSkinsEverywhere() { - return disableFNAWSkinsEverywhere; - } - - public Set getDisableFNAWSkinsOnServersSet() { - return disableFNAWSkinsOnServers; - } - - public boolean getEnableBackendRPCAPI() { - return enableBackendRPCAPI; - } - - public boolean getUseModernizedChannelNames() { - return useModernizedChannelNames; - } - - public EaglerPauseMenuConfig getPauseMenuConf() { - return pauseMenuConf; - } - - private EaglerBungeeConfig(String serverName, UUID serverUUID, long websocketKeepAliveTimeout, - long websocketHandshakeTimeout, long builtinHttpServerTimeout, int httpWebsocketCompressionLevel, - Map serverListeners, Map contentTypes, - boolean downloadVanillaSkins, Collection validSkinUrls, int uuidRateLimitPlayer, - int uuidRateLimitGlobal, int skinRateLimitPlayer, int skinRateLimitGlobal, String skinCacheURI, - int keepObjectsDays, int keepProfilesDays, int maxObjects, int maxProfiles, int antagonistsRateLimit, - String sqliteDriverClass, String sqliteDriverPath, String eaglerPlayersVanillaSkin, - boolean enableIsEaglerPlayerProperty, EaglerAuthConfig authConfig, EaglerUpdateConfig updateConfig, - Collection iceServers, boolean enableVoiceChat, Set disableVoiceOnServers, - boolean disableFNAWSkinsEverywhere, Set disableFNAWSkinsOnServers, - boolean enableBackendRPCAPI, boolean useModernizedChannelNames, EaglerPauseMenuConfig pauseMenuConf) { - this.serverName = serverName; - this.serverUUID = serverUUID; - this.serverListeners = serverListeners; - this.websocketHandshakeTimeout = websocketHandshakeTimeout; - this.websocketKeepAliveTimeout = websocketKeepAliveTimeout; - this.builtinHttpServerTimeout = builtinHttpServerTimeout; - this.httpWebsocketCompressionLevel = httpWebsocketCompressionLevel; - this.contentTypes = contentTypes; - this.downloadVanillaSkins = downloadVanillaSkins; - this.validSkinUrls = validSkinUrls; - this.uuidRateLimitPlayer = uuidRateLimitPlayer; - this.uuidRateLimitGlobal = uuidRateLimitGlobal; - this.skinRateLimitPlayer = skinRateLimitPlayer; - this.skinRateLimitGlobal = skinRateLimitGlobal; - this.skinCacheURI = skinCacheURI; - this.keepObjectsDays = keepObjectsDays; - this.keepProfilesDays = keepProfilesDays; - this.maxObjects = maxObjects; - this.maxProfiles = maxProfiles; - this.antagonistsRateLimit = antagonistsRateLimit; - this.sqliteDriverClass = sqliteDriverClass; - this.sqliteDriverPath = sqliteDriverPath; - this.eaglerPlayersVanillaSkin = eaglerPlayersVanillaSkin; - this.enableIsEaglerPlayerProperty = enableIsEaglerPlayerProperty; - this.authConfig = authConfig; - this.updateConfig = updateConfig; - this.iceServers = iceServers; - this.enableVoiceChat = enableVoiceChat; - this.disableVoiceOnServers = disableVoiceOnServers; - this.disableFNAWSkinsEverywhere = disableFNAWSkinsEverywhere; - this.disableFNAWSkinsOnServers = disableFNAWSkinsOnServers; - this.enableBackendRPCAPI = enableBackendRPCAPI; - this.useModernizedChannelNames = useModernizedChannelNames; - this.pauseMenuConf = pauseMenuConf; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerListenerConfig.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerListenerConfig.java deleted file mode 100644 index fc1a76ec..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerListenerConfig.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.io.File; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import io.netty.handler.codec.http.HttpRequest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpContentType; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpWebServer; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.config.ListenerInfo; -import net.md_5.bungee.config.Configuration; - -public class EaglerListenerConfig extends ListenerInfo { - - static EaglerListenerConfig loadConfig(Configuration config, Map contentTypes) { - - String host = config.getString("address", "0.0.0.0:8081"); - InetSocketAddress hostv4 = null; - if(host != null && !host.equalsIgnoreCase("null") && !host.equalsIgnoreCase("none")) { - int i = host.lastIndexOf(':'); - if(i == -1) { - throw new IllegalArgumentException("Invalid address: " + host + "! Must be an ipv4:port combo"); - } - hostv4 = new InetSocketAddress(host.substring(0, i), Integer.parseInt(host.substring(i + 1))); - } - - String hostV6 = config.getString("address_v6", "null"); - InetSocketAddress hostv6 = null; - if(hostV6 != null && !hostV6.equalsIgnoreCase("null") && !hostV6.equalsIgnoreCase("none") && hostV6.length() > 0) { - int i = hostV6.lastIndexOf(':'); - if(i == -1) { - throw new IllegalArgumentException("Invalid address: " + host + "! Must be an ipv6:port combo"); - } - hostv6 = new InetSocketAddress(hostV6.substring(0, i), Integer.parseInt(hostV6.substring(i + 1))); - } - - if(hostv4 == null && hostv6 == null) { - throw new IllegalArgumentException("Invalid host specifies no addresses, both v4 and v6 address are null"); - } - - int maxPlayer = config.getInt("max_players", 60); - String tabListType = config.getString("tab_list", "GLOBAL_PING"); - String defaultServer = config.getString("default_server", "lobby"); - boolean forceDefaultServer = config.getBoolean("force_default_server", false); - boolean forwardIp = config.getBoolean("forward_ip", false); - String forwardIpHeader = config.getString("forward_ip_header", "X-Real-IP"); - String redirectLegacyClientsTo = config.getString("redirect_legacy_clients_to", "null"); - if(redirectLegacyClientsTo != null && (redirectLegacyClientsTo.equalsIgnoreCase("null") || redirectLegacyClientsTo.length() == 0)) { - redirectLegacyClientsTo = null; - } - String serverIcon = config.getString("server_icon", "server-icon.png"); - List serverMOTD = (List) config.getList("server_motd", Arrays.asList("&6An EaglercraftX server")); - for(int i = 0, l = serverMOTD.size(); i < l; ++i) { - serverMOTD.set(i, ChatColor.translateAlternateColorCodes('&', serverMOTD.get(i))); - } - boolean allowMOTD = config.getBoolean("allow_motd", true); - boolean allowQuery = config.getBoolean("allow_query", true); - int minMCProtocol = config.getInt("min_minecraft_protocol", 47); - int maxMCProtocol = config.getInt("max_minecraft_protocol", 340); - boolean allowV3 = config.getBoolean("allow_protocol_v3", true); - boolean allowV4 = config.getBoolean("allow_protocol_v4", true); - if(!allowV3 && !allowV4) { - throw new IllegalArgumentException("Both v3 and v4 protocol are disabled!"); - } - int defragSendDelay = config.getInt("protocol_v4_defrag_send_delay", 10); - boolean haproxyProtocol = config.getBoolean("use_haproxy_protocol", false); - - int cacheTTL = 7200; - boolean cacheAnimation = false; - boolean cacheResults = true; - boolean cacheTrending = true; - boolean cachePortfolios = false; - - Configuration cacheConf = config.getSection("request_motd_cache"); - if(cacheConf != null) { - cacheTTL = cacheConf.getInt("cache_ttl", 7200); - cacheAnimation = cacheConf.getBoolean("online_server_list_animation", false); - cacheResults = cacheConf.getBoolean("online_server_list_results", true); - cacheTrending = cacheConf.getBoolean("online_server_list_trending", true); - cachePortfolios = cacheConf.getBoolean("online_server_list_portfolios", false); - } - - HttpWebServer httpServer = null; - Configuration httpServerConf = config.getSection("http_server"); - - if(httpServerConf != null && httpServerConf.getBoolean("enabled", false)) { - String rootDirectory = httpServerConf.getString("root", "web"); - String page404 = httpServerConf.getString("page_404_not_found", "default"); - if(page404 != null && (page404.length() == 0 || page404.equalsIgnoreCase("null") || page404.equalsIgnoreCase("default"))) { - page404 = null; - } - List defaultIndex = Arrays.asList("index.html", "index.htm"); - List indexPageRaw = httpServerConf.getList("page_index_name", defaultIndex); - List indexPage = new ArrayList<>(indexPageRaw.size()); - - for(int i = 0, l = indexPageRaw.size(); i < l; ++i) { - Object o = indexPageRaw.get(i); - if(o instanceof String) { - indexPage.add((String)o); - } - } - - if(indexPage.size() == 0) { - indexPage.addAll(defaultIndex); - } - - httpServer = new HttpWebServer(new File(EaglerXBungee.getEagler().getDataFolder(), rootDirectory), - contentTypes, indexPage, page404); - } - - boolean enableVoiceChat = config.getBoolean("allow_voice", false); - - EaglerRateLimiter ratelimitIp = null; - EaglerRateLimiter ratelimitLogin = null; - EaglerRateLimiter ratelimitMOTD = null; - EaglerRateLimiter ratelimitQuery = null; - - Configuration rateLimitConfig = config.getSection("ratelimit"); - if(rateLimitConfig != null) { - Configuration ratelimitIpConfig = rateLimitConfig.getSection("ip"); - if(ratelimitIpConfig != null && ratelimitIpConfig.getBoolean("enable", false)) { - ratelimitIp = EaglerRateLimiter.loadConfig(ratelimitIpConfig); - } - Configuration ratelimitLoginConfig = rateLimitConfig.getSection("login"); - if(ratelimitLoginConfig != null && ratelimitLoginConfig.getBoolean("enable", false)) { - ratelimitLogin = EaglerRateLimiter.loadConfig(ratelimitLoginConfig); - } - Configuration ratelimitMOTDConfig = rateLimitConfig.getSection("motd"); - if(ratelimitMOTDConfig != null && ratelimitMOTDConfig.getBoolean("enable", false)) { - ratelimitMOTD = EaglerRateLimiter.loadConfig(ratelimitMOTDConfig); - } - Configuration ratelimitQueryConfig = rateLimitConfig.getSection("query"); - if(ratelimitQueryConfig != null && ratelimitQueryConfig.getBoolean("enable", false)) { - ratelimitQuery = EaglerRateLimiter.loadConfig(ratelimitQueryConfig); - } - } - - MOTDCacheConfiguration cacheConfig = new MOTDCacheConfiguration(cacheTTL, cacheAnimation, cacheResults, - cacheTrending, cachePortfolios); - return new EaglerListenerConfig(hostv4, hostv6, maxPlayer, tabListType, defaultServer, forceDefaultServer, - forwardIp, forwardIpHeader, redirectLegacyClientsTo, serverIcon, serverMOTD, allowMOTD, allowQuery, - minMCProtocol, maxMCProtocol, allowV3, allowV4, defragSendDelay, haproxyProtocol, cacheConfig, - httpServer, enableVoiceChat, ratelimitIp, ratelimitLogin, ratelimitMOTD, ratelimitQuery); - } - - private final InetSocketAddress address; - private final InetSocketAddress addressV6; - private final int maxPlayer; - private final String tabListType; - private final String defaultServer; - private final boolean forceDefaultServer; - private final boolean forwardIp; - private final String forwardIpHeader; - private final String redirectLegacyClientsTo; - private final String serverIcon; - private final List serverMOTD; - private final boolean allowMOTD; - private final boolean allowQuery; - private final int minMCProtocol; - private final int maxMCProtocol; - private final boolean allowV3; - private final boolean allowV4; - private final int defragSendDelay; - private final boolean haproxyProtocol; - private final MOTDCacheConfiguration motdCacheConfig; - private final HttpWebServer webServer; - private boolean serverIconSet = false; - private int[] serverIconPixels = null; - private final boolean enableVoiceChat; - private final EaglerRateLimiter ratelimitIp; - private final EaglerRateLimiter ratelimitLogin; - private final EaglerRateLimiter ratelimitMOTD; - private final EaglerRateLimiter ratelimitQuery; - - public EaglerListenerConfig(InetSocketAddress address, InetSocketAddress addressV6, int maxPlayer, - String tabListType, String defaultServer, boolean forceDefaultServer, boolean forwardIp, - String forwardIpHeader, String redirectLegacyClientsTo, String serverIcon, List serverMOTD, - boolean allowMOTD, boolean allowQuery, int minMCProtocol, int maxMCProtocol, boolean allowV3, - boolean allowV4, int defragSendDelay, boolean haproxyProtocol, MOTDCacheConfiguration motdCacheConfig, - HttpWebServer webServer, boolean enableVoiceChat, EaglerRateLimiter ratelimitIp, - EaglerRateLimiter ratelimitLogin, EaglerRateLimiter ratelimitMOTD, EaglerRateLimiter ratelimitQuery) { - super(address, String.join("\n", serverMOTD), maxPlayer, 60, Arrays.asList(defaultServer), forceDefaultServer, - Collections.emptyMap(), tabListType, false, false, 0, false, false); - this.address = address; - this.addressV6 = addressV6; - this.maxPlayer = maxPlayer; - this.tabListType = tabListType; - this.defaultServer = defaultServer; - this.forceDefaultServer = forceDefaultServer; - this.forwardIp = forwardIp; - this.forwardIpHeader = forwardIpHeader; - this.redirectLegacyClientsTo = redirectLegacyClientsTo; - this.serverIcon = serverIcon; - this.serverMOTD = serverMOTD; - this.allowMOTD = allowMOTD; - this.allowQuery = allowQuery; - this.minMCProtocol = minMCProtocol; - this.maxMCProtocol = maxMCProtocol; - this.allowV3 = allowV3; - this.allowV4 = allowV4; - this.defragSendDelay = defragSendDelay; - this.haproxyProtocol = haproxyProtocol; - this.motdCacheConfig = motdCacheConfig; - this.webServer = webServer; - this.enableVoiceChat = enableVoiceChat; - this.ratelimitIp = ratelimitIp; - this.ratelimitLogin = ratelimitLogin; - this.ratelimitMOTD = ratelimitMOTD; - this.ratelimitQuery = ratelimitQuery; - } - - public InetSocketAddress getAddress() { - return address; - } - - public InetSocketAddress getAddressV6() { - return addressV6; - } - - public int getMaxPlayer() { - return maxPlayer; - } - - public String getTabListType() { - return tabListType; - } - - public String getDefaultServer() { - return defaultServer; - } - - public boolean isForceDefaultServer() { - return forceDefaultServer; - } - - public boolean isForwardIp() { - return forwardIp; - } - - public String getForwardIpHeader() { - return forwardIpHeader; - } - - public String getServerIconName() { - return serverIcon; - } - - public int[] getServerIconPixels() { - if(!serverIconSet) { - if(serverIcon != null) { - File f = new File(serverIcon); - if(f.isFile()) { - serverIconPixels = ServerIconLoader.createServerIcon(f); - if(serverIconPixels == null) { - EaglerXBungee.logger().warning("Server icon could not be loaded: " + f.getAbsolutePath()); - } - }else { - EaglerXBungee.logger().warning("Server icon is not a file: " + f.getAbsolutePath()); - } - } - serverIconSet = true; - } - return serverIconPixels; - } - - public List getServerMOTD() { - return serverMOTD; - } - - public boolean isAllowMOTD() { - return allowMOTD; - } - - public boolean isAllowQuery() { - return allowQuery; - } - - public int getMinMCProtocol() { - return minMCProtocol; - } - - public int getMaxMCProtocol() { - return maxMCProtocol; - } - - public boolean isAllowV3() { - return allowV3; - } - - public boolean isAllowV4() { - return allowV4; - } - - public int getDefragSendDelay() { - return defragSendDelay; - } - - public boolean isHAProxyProtocol() { - return haproxyProtocol; - } - - public HttpWebServer getWebServer() { - return webServer; - } - - public MOTDCacheConfiguration getMOTDCacheConfig() { - return motdCacheConfig; - } - - public boolean blockRequest(HttpRequest request) { - return false; - } - - public String redirectLegacyClientsTo() { - return redirectLegacyClientsTo; - } - - public boolean getEnableVoiceChat() { - return enableVoiceChat; - } - - public EaglerRateLimiter getRatelimitIp() { - return ratelimitIp; - } - - public EaglerRateLimiter getRatelimitLogin() { - return ratelimitLogin; - } - - public EaglerRateLimiter getRatelimitMOTD() { - return ratelimitMOTD; - } - - public EaglerRateLimiter getRatelimitQuery() { - return ratelimitQuery; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerPauseMenuConfig.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerPauseMenuConfig.java deleted file mode 100644 index 69c4dac1..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerPauseMenuConfig.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.WeakHashMap; - -import gnu.trove.map.TIntObjectMap; -import gnu.trove.map.hash.TIntObjectHashMap; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketServerInfoDataChunkV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleOutputBufferImpl; -import net.md_5.bungee.config.Configuration; - -public class EaglerPauseMenuConfig { - - private boolean enableCustomPauseMenu; - private SPacketCustomizePauseMenuV4EAG customPauseMenuPacket; - private byte[] serverInfoHash; - private List serverInfoChunks; - private int infoSendRate; - - static EaglerPauseMenuConfig loadConfig(Configuration conf, File baseDir) throws IOException { - boolean enabled = conf.getBoolean("enable_custom_pause_menu", false); - if(!enabled) { - return new EaglerPauseMenuConfig(false, null, null, 1); - } - - Configuration server_info_button = conf.getSection("server_info_button"); - boolean enableInfoButton = server_info_button.getBoolean("enable_button", false); - String infoButtonText = server_info_button.getString("button_text", "Server Info"); - boolean infoButtonModeNewTab = server_info_button.getBoolean("button_mode_open_new_tab", false); - String infoButtonEmbedURL = server_info_button.getString("server_info_embed_url", ""); - boolean infoButtonModeEmbedFile = server_info_button.getBoolean("button_mode_embed_file", true); - String infoButtonEmbedFile = server_info_button.getString("server_info_embed_file", "server_info.html"); - String infoButtonEmbedScreenTitle = server_info_button.getString("server_info_embed_screen_title", "Server Info"); - int infoSendRate = server_info_button.getInt("server_info_embed_send_chunk_rate", 1); - int infoChunkSize = server_info_button.getInt("server_info_embed_send_chunk_size", 24576); - if(infoChunkSize > 32720) { - throw new IOException("Chunk size " +infoChunkSize + " is too large! Max is 32720 bytes"); - } - boolean infoButtonEnableTemplateMacros = server_info_button.getBoolean("enable_template_macros", true); - Configuration globals = server_info_button.getSection("server_info_embed_template_globals"); - for(String s : globals.getKeys()) { - EaglerXBungeeAPIHelper.getTemplateGlobals().put(s, globals.getString(s)); - } - boolean infoButtonAllowTemplateEvalMacro = server_info_button.getBoolean("allow_embed_template_eval_macro", false); - boolean infoButtonEnableWebviewJavascript = server_info_button.getBoolean("enable_webview_javascript", false); - boolean infoButtonEnableWebviewMessageAPI = server_info_button.getBoolean("enable_webview_message_api", false); - boolean infoButtonEnableWebviewStrictCSP = server_info_button.getBoolean("enable_webview_strict_csp", true); - - Configuration discord_button = conf.getSection("discord_button"); - boolean enableDiscordButton = discord_button.getBoolean("enable_button", false); - String discordButtonText = discord_button.getString("button_text", "Discord"); - String discordButtonURL = discord_button.getString("button_url", "https://invite url here"); - - int infoButtonMode = enableInfoButton - ? (infoButtonModeEmbedFile - ? (infoButtonEmbedFile.length() > 0 - ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE) - : (infoButtonEmbedURL.length() > 0 - ? (infoButtonModeNewTab ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_EXTERNAL_URL - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP) - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE)) - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE; - - int discordButtonMode = (enableDiscordButton && discordButtonURL.length() > 0) - ? SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_INVITE_URL - : SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_NONE; - - int webviewPerms = (infoButtonEnableWebviewJavascript ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_JAVASCRIPT : 0) | - (infoButtonEnableWebviewMessageAPI ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_MESSAGE_API : 0) | - (infoButtonEnableWebviewStrictCSP ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_STRICT_CSP : 0); - - Map imagesToActuallyLoad = new WeakHashMap<>(); - - Configuration custom_images = conf.getSection("custom_images"); - for(String s : custom_images.getKeys()) { - String fileName = custom_images.getString(s, ""); - if(fileName.length() > 0) { - imagesToActuallyLoad.put(s, fileName); - } - } - - Map imageMappings = null; - List customImageDatas = null; - - if(imagesToActuallyLoad.size() > 0) { - Map imageLoadingCache = new HashMap<>(); - TIntObjectMap imageDumbHashTable = new TIntObjectHashMap<>(); - - imageMappings = new HashMap<>(); - customImageDatas = new ArrayList<>(); - - outer_loop: for(Entry etr : imagesToActuallyLoad.entrySet()) { - String key = etr.getKey(); - String value = etr.getValue(); - PacketImageData existing = imageLoadingCache.get(value); - if(existing != null) { - for(int i = 0, l = customImageDatas.size(); i < l; ++i) { - if(customImageDatas.get(i) == existing) { - imageMappings.put(key, i); - continue outer_loop; - } - } - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(existing); - continue outer_loop; - }else { - PacketImageData img = EaglerXBungeeAPIHelper.loadPacketImageData(new File(baseDir, value), 64, 64); - int hashCode = Arrays.hashCode(img.rgba); - PacketImageData possibleClone = imageDumbHashTable.get(hashCode); - if (possibleClone != null && possibleClone.width == img.width && possibleClone.height == img.height - && Arrays.equals(img.rgba, possibleClone.rgba)) { - for(int i = 0, l = customImageDatas.size(); i < l; ++i) { - if(customImageDatas.get(i) == possibleClone) { - imageMappings.put(key, i); - continue outer_loop; - } - } - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(possibleClone); - continue outer_loop; - }else { - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(img); - imageDumbHashTable.put(hashCode, img); - continue outer_loop; - } - } - } - } - - SPacketCustomizePauseMenuV4EAG pausePacket = new SPacketCustomizePauseMenuV4EAG(); - List serverInfoChunks = null; - - pausePacket.serverInfoMode = infoButtonMode; - switch(infoButtonMode) { - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE: - default: - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_EXTERNAL_URL: - pausePacket.serverInfoButtonText = infoButtonText; - pausePacket.serverInfoURL = infoButtonEmbedURL; - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP: - pausePacket.serverInfoButtonText = infoButtonText; - pausePacket.serverInfoURL = infoButtonEmbedURL; - pausePacket.serverInfoEmbedPerms = webviewPerms; - pausePacket.serverInfoEmbedTitle = infoButtonEmbedScreenTitle; - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS: - pausePacket.serverInfoButtonText = infoButtonText; - byte[] hash = new byte[20]; - String rawData = EaglerXBungeeAPIHelper.loadFileToStringServerInfo(new File(baseDir, infoButtonEmbedFile)); - if(infoButtonEnableTemplateMacros) { - rawData = EaglerXBungeeAPIHelper.loadServerInfoTemplateEagler(rawData, baseDir, infoButtonAllowTemplateEvalMacro); - } - serverInfoChunks = EaglerXBungeeAPIHelper.convertServerInfoToChunks(rawData.getBytes(StandardCharsets.UTF_8), hash, infoChunkSize); - if(!serverInfoChunks.isEmpty()) { - SPacketServerInfoDataChunkV4EAG pk = serverInfoChunks.get(0); - EaglerXBungee.logger().info("Total server info embed size: " + pk.finalSize + " bytes" + (serverInfoChunks.size() > 1 ? (" (" + serverInfoChunks.size() + " chunks)") : "")); - } - pausePacket.serverInfoEmbedPerms = webviewPerms; - pausePacket.serverInfoEmbedTitle = infoButtonEmbedScreenTitle; - pausePacket.serverInfoHash = hash; - break; - } - - pausePacket.discordButtonMode = discordButtonMode; - switch(discordButtonMode) { - case SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_NONE: - default: - break; - case SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_INVITE_URL: - pausePacket.discordButtonMode = discordButtonMode; - pausePacket.discordButtonText = discordButtonText; - pausePacket.discordInviteURL = discordButtonURL; - break; - } - - pausePacket.imageMappings = imageMappings; - pausePacket.imageData = customImageDatas; - - SimpleOutputBufferImpl ob = new SimpleOutputBufferImpl(new TestOutputStream()); - pausePacket.writePacket(ob); - int cnt = ob.size(); - - EaglerXBungee.logger().info("Total pause menu packet size: " + cnt + " bytes"); - if(cnt > 32760) { - throw new IOException("Pause menu packet is " + (cnt - 32760) + " bytes too large! Try making the images smaller or reusing the same image file for multiple icons!"); - } - - return new EaglerPauseMenuConfig(enabled, pausePacket, serverInfoChunks, infoSendRate); - } - - private EaglerPauseMenuConfig(boolean enableCustomPauseMenu, SPacketCustomizePauseMenuV4EAG customPauseMenuPacket, - List serverInfoChunks, int infoSendRate) { - this.enableCustomPauseMenu = enableCustomPauseMenu; - this.customPauseMenuPacket = customPauseMenuPacket; - this.serverInfoHash = customPauseMenuPacket != null ? customPauseMenuPacket.serverInfoHash : null; - this.serverInfoChunks = serverInfoChunks; - this.infoSendRate = infoSendRate; - } - - public boolean getEnabled() { - return enableCustomPauseMenu; - } - - public SPacketCustomizePauseMenuV4EAG getPacket() { - return customPauseMenuPacket; - } - - public byte[] getServerInfoHash() { - return serverInfoHash; - } - - public List getServerInfo() { - return serverInfoChunks; - } - - public int getInfoSendRate() { - return infoSendRate; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerRateLimiter.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerRateLimiter.java deleted file mode 100644 index 4a15a617..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerRateLimiter.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.md_5.bungee.config.Configuration; - -public class EaglerRateLimiter { - - private final int period; - private final int limit; - private final int limitLockout; - private int effectiveLimit; - private int effectiveLimitLockout; - private final int lockoutDuration; - private final List exceptions; - - private EaglerRateLimiter(int period, int limit, int limitLockout, int lockoutDuration, List exceptions) { - this.period = period * 1000 / limit; - this.limit = this.effectiveLimit = limit; - this.limitLockout = this.effectiveLimitLockout = limitLockout; - this.lockoutDuration = lockoutDuration * 1000; - this.exceptions = exceptions; - } - - public void setDivisor(int d) { - this.effectiveLimit = this.limit * d; - this.effectiveLimitLockout = this.limitLockout * d; - } - - public int getPeriod() { - return period; - } - - public int getLimit() { - return effectiveLimit; - } - - public int getLimitLockout() { - return effectiveLimitLockout; - } - - public int getLockoutDuration() { - return lockoutDuration; - } - - public List getExceptions() { - return exceptions; - } - - public boolean isException(String addr) { - for(int i = 0, l = exceptions.size(); i < l; ++i) { - String str = exceptions.get(i); - int ll = str.length() - 1; - if(str.indexOf('*') == 0) { - if(addr.endsWith(str.substring(1))) { - return true; - } - }else if(str.lastIndexOf('*') == ll) { - if(addr.startsWith(str.substring(ll))) { - return true; - } - }else { - if(addr.equals(str)) { - return true; - } - } - } - return false; - } - - protected class RateLimiter { - - protected int requestCounter = 0; - protected long lockoutTimestamp = 0l; - protected long cooldownTimestamp = 0l; - - protected RateLimitStatus rateLimit() { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - tick(millis); - if(lockoutTimestamp != 0l) { - return RateLimitStatus.LOCKED_OUT; - }else { - if(++requestCounter > EaglerRateLimiter.this.effectiveLimitLockout) { - lockoutTimestamp = millis; - requestCounter = 0; - return RateLimitStatus.LIMITED_NOW_LOCKED_OUT; - }else if(requestCounter > EaglerRateLimiter.this.effectiveLimit) { - return RateLimitStatus.LIMITED; - }else { - return RateLimitStatus.OK; - } - } - } - - protected void tick(long millis) { - if(lockoutTimestamp != 0l) { - if(millis - lockoutTimestamp > EaglerRateLimiter.this.lockoutDuration) { - requestCounter = 0; - lockoutTimestamp = 0l; - cooldownTimestamp = millis; - } - }else { - long delta = millis - cooldownTimestamp; - long decr = delta / EaglerRateLimiter.this.period; - if(decr >= requestCounter) { - requestCounter = 0; - cooldownTimestamp = millis; - }else { - requestCounter -= decr; - cooldownTimestamp += decr * EaglerRateLimiter.this.period; - if(requestCounter < 0) { - requestCounter = 0; - } - } - } - } - } - - private final Map ratelimiters = new HashMap<>(); - - public RateLimitStatus rateLimit(String addr) { - addr = addr.toLowerCase(); - if(isException(addr)) { - return RateLimitStatus.OK; - }else { - RateLimiter limiter; - synchronized(ratelimiters) { - limiter = ratelimiters.get(addr); - if(limiter == null) { - limiter = new RateLimiter(); - ratelimiters.put(addr, limiter); - } - } - return limiter.rateLimit(); - } - } - - public void tick() { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - synchronized(ratelimiters) { - Iterator itr = ratelimiters.values().iterator(); - while(itr.hasNext()) { - RateLimiter i = itr.next(); - i.tick(millis); - if(i.requestCounter <= 0 && i.lockoutTimestamp <= 0l) { - itr.remove(); - } - } - } - } - - public void reset() { - synchronized(ratelimiters) { - ratelimiters.clear(); - } - } - - static EaglerRateLimiter loadConfig(Configuration config) { - int period = config.getInt("period", -1); - int limit = config.getInt("limit", -1); - int limitLockout = config.getInt("limit_lockout", -1); - int lockoutDuration = config.getInt("lockout_duration", -1); - Collection exc = (Collection) config.getList("exceptions"); - List exceptions = new ArrayList<>(); - for(String str : exc) { - exceptions.add(str.toLowerCase()); - } - if(period != -1 && limit != -1 && limitLockout != -1 && lockoutDuration != -1) { - return new EaglerRateLimiter(period, limit, limitLockout, lockoutDuration, exceptions); - }else { - return null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerUpdateConfig.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerUpdateConfig.java deleted file mode 100644 index f239a125..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/EaglerUpdateConfig.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.util.Collection; - -import net.md_5.bungee.config.Configuration; - -public class EaglerUpdateConfig { - - static EaglerUpdateConfig loadConfig(Configuration config) { - boolean blockAllClientUpdates = config.getBoolean("block_all_client_updates", false); - boolean discardLoginPacketCerts = config.getBoolean("discard_login_packet_certs", false); - int certPacketDataRateLimit = config.getInt("cert_packet_data_rate_limit", 524288); - boolean enableEagcertFolder = config.getBoolean("enable_eagcert_folder", true); - boolean downloadLatestCerts = config.getBoolean("download_latest_certs", true); - int checkForUpdatesEvery = config.getInt("check_for_update_every", 28800); - Collection downloadCertURLs = (Collection)config.getList("download_certs_from"); - return new EaglerUpdateConfig(blockAllClientUpdates, discardLoginPacketCerts, certPacketDataRateLimit, - enableEagcertFolder, downloadLatestCerts, checkForUpdatesEvery, downloadCertURLs); - } - - private final boolean blockAllClientUpdates; - private final boolean discardLoginPacketCerts; - private final int certPacketDataRateLimit; - private final boolean enableEagcertFolder; - private final boolean downloadLatestCerts; - private final int checkForUpdatesEvery; - private final Collection downloadCertURLs; - - public EaglerUpdateConfig(boolean blockAllClientUpdates, boolean discardLoginPacketCerts, - int certPacketDataRateLimit, boolean enableEagcertFolder, boolean downloadLatestCerts, - int checkForUpdatesEvery, Collection downloadCertURLs) { - this.blockAllClientUpdates = blockAllClientUpdates; - this.discardLoginPacketCerts = discardLoginPacketCerts; - this.certPacketDataRateLimit = certPacketDataRateLimit; - this.enableEagcertFolder = enableEagcertFolder; - this.downloadLatestCerts = downloadLatestCerts; - this.checkForUpdatesEvery = checkForUpdatesEvery; - this.downloadCertURLs = downloadCertURLs; - } - - public boolean isBlockAllClientUpdates() { - return blockAllClientUpdates; - } - - public boolean isDiscardLoginPacketCerts() { - return discardLoginPacketCerts; - } - - public int getCertPacketDataRateLimit() { - return certPacketDataRateLimit; - } - - public boolean isEnableEagcertFolder() { - return enableEagcertFolder; - } - - public boolean isDownloadLatestCerts() { - return downloadLatestCerts && enableEagcertFolder; - } - - public int getCheckForUpdatesEvery() { - return checkForUpdatesEvery; - } - - public Collection getDownloadCertURLs() { - return downloadCertURLs; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/MOTDCacheConfiguration.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/MOTDCacheConfiguration.java deleted file mode 100644 index 5259356e..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/MOTDCacheConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -public class MOTDCacheConfiguration { - - public final int cacheTTL; - public final boolean cacheServerListAnimation; - public final boolean cacheServerListResults; - public final boolean cacheServerListTrending; - public final boolean cacheServerListPortfolios; - - public MOTDCacheConfiguration(int cacheTTL, boolean cacheServerListAnimation, boolean cacheServerListResults, - boolean cacheServerListTrending, boolean cacheServerListPortfolios) { - this.cacheTTL = cacheTTL; - this.cacheServerListAnimation = cacheServerListAnimation; - this.cacheServerListResults = cacheServerListResults; - this.cacheServerListTrending = cacheServerListTrending; - this.cacheServerListPortfolios = cacheServerListPortfolios; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/RateLimitStatus.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/RateLimitStatus.java deleted file mode 100644 index e91bea7d..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/RateLimitStatus.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -public enum RateLimitStatus { - OK, LIMITED, LIMITED_NOW_LOCKED_OUT, LOCKED_OUT; -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerIconLoader.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerIconLoader.java deleted file mode 100644 index 2e514537..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerIconLoader.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -class ServerIconLoader { - - static int[] createServerIcon(BufferedImage awtIcon) { - BufferedImage icon = awtIcon; - boolean gotScaled = false; - if(icon.getWidth() != 64 || icon.getHeight() != 64) { - icon = new BufferedImage(64, 64, awtIcon.getType()); - Graphics2D g = (Graphics2D) icon.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ? - RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, 64, 64); - int ow = awtIcon.getWidth(); - int oh = awtIcon.getHeight(); - int nw, nh; - float aspectRatio = (float)oh / (float)ow; - if(aspectRatio >= 1.0f) { - nw = (int)(64 / aspectRatio); - nh = 64; - }else { - nw = 64; - nh = (int)(64 * aspectRatio); - } - g.drawImage(awtIcon, (64 - nw) / 2, (64 - nh) / 2, (64 - nw) / 2 + nw, (64 - nh) / 2 + nh, 0, 0, awtIcon.getWidth(), awtIcon.getHeight(), null); - g.dispose(); - gotScaled = true; - } - int[] pxls = icon.getRGB(0, 0, 64, 64, new int[4096], 0, 64); - if(gotScaled) { - for(int i = 0; i < pxls.length; ++i) { - if((pxls[i] & 0xFFFFFF) == 0) { - pxls[i] = 0; - } - } - } - return pxls; - } - - static int[] createServerIcon(InputStream f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - - static int[] createServerIcon(File f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerInfoTemplateParser.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerInfoTemplateParser.java deleted file mode 100644 index 7f3f27cc..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/ServerInfoTemplateParser.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -import org.apache.commons.codec.binary.Base64; - -import com.google.common.html.HtmlEscapers; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.repackage.lang3.StrTokenizer; -import net.md_5.bungee.BungeeCord; - -public class ServerInfoTemplateParser { - - private static final Gson jsonEscaper = (new GsonBuilder()).disableHtmlEscaping().create(); - - private static class State { - private boolean evalAllowed; - private File baseDir; - private Map globals; - private boolean htmlEscape; - private boolean strEscape; - private boolean disableMacros; - private boolean enableEval; - private State(File baseDir, boolean evalAllowed, Map globals) { - this.baseDir = baseDir; - this.evalAllowed = evalAllowed; - this.globals = globals; - } - private State push() { - return new State(baseDir, evalAllowed, globals); - } - } - - public static String loadTemplate(String content, File baseDir, boolean evalAllowed, Map globals) throws IOException { - return loadTemplate(content, new State(baseDir, evalAllowed, globals)); - } - - private static String loadTemplate(String content, State state) throws IOException { - StringBuilder ret = new StringBuilder(); - int i = 0, j = 0; - while((i = content.indexOf("{%", j)) != -1) { - ret.append(content, j, i); - j = i; - i = content.indexOf("%}", j + 2); - if(i != -1) { - ret.append(processMacro(content.substring(j + 2, i), state)); - j = i + 2; - }else { - break; - } - } - ret.append(content, j, content.length()); - return ret.toString(); - } - - public static class InvalidMacroException extends RuntimeException { - - public InvalidMacroException(String message, Throwable cause) { - super(message, cause); - } - - public InvalidMacroException(String message) { - super(message); - } - - } - - private static String processMacro(String content, State state) throws IOException { - String trimmed = content.trim(); - try { - String[] strs = (new StrTokenizer(trimmed, ' ', '`')).getTokenArray(); - if(strs.length < 1) { - return "{%" + content + "%}"; - } - if(strs[0].equals("disablemacros") && strs.length == 2) { - switch(strs[1]) { - case "on": - if(state.disableMacros) { - return "{%" + content + "%}"; - }else { - state.disableMacros = true; - return ""; - } - case "off": - state.disableMacros = false; - return ""; - default: - if(state.disableMacros) { - return "{%" + content + "%}"; - }else { - throw new InvalidMacroException("Unknown disablemacros mode: " + strs[1] + " (Expected: on, off)"); - } - } - }else if(!state.disableMacros) { - switch(strs[0]) { - case "embed": - argCheck(3, strs.length); - switch(strs[1]) { - case "base64": - return Base64.encodeBase64String(EaglerXBungeeAPIHelper.loadFileToByteArrayServerInfo(new File(state.baseDir, strs[2]))); - case "text": - return escapeMacroResult(EaglerXBungeeAPIHelper.loadFileToStringServerInfo(new File(state.baseDir, strs[2])), state); - case "eval": - if(state.evalAllowed) { - return escapeMacroResult(loadTemplate(EaglerXBungeeAPIHelper.loadFileToStringServerInfo(new File(state.baseDir, strs[2])), state.push()), state); - }else { - throw new InvalidMacroException("Template tried to eval file \"" + strs[2] + "\"! (eval is disabled)"); - } - default: - throw new InvalidMacroException("Unknown embed mode: " + strs[1] + " (Expected: base64, text, eval)"); - } - case "htmlescape": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - state.htmlEscape = true; - return ""; - case "off": - state.htmlEscape = false; - return ""; - default: - throw new InvalidMacroException("Unknown htmlescape mode: " + strs[1] + " (Expected: on, off)"); - } - case "strescape": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - state.strEscape = true; - return ""; - case "off": - state.strEscape = false; - return ""; - default: - throw new InvalidMacroException("Unknown strescape mode: " + strs[1] + " (Expected: on, off)"); - } - case "eval": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - if(!state.evalAllowed) { - throw new InvalidMacroException("Template tried to enable eval! (eval is disabled)"); - } - state.enableEval = true; - return ""; - case "off": - state.enableEval = false; - return ""; - default: - throw new InvalidMacroException("Unknown eval mode: " + strs[1] + " (Expected: on, off)"); - } - case "global": - argCheck(2, 3, strs.length); - String ret = state.globals.get(strs[1]); - if(ret == null) { - if(strs.length == 3) { - ret = strs[2]; - }else { - throw new InvalidMacroException("Unknown global \"" + strs[1] + "\"! (Available: " + String.join(", ", state.globals.keySet()) + ")"); - } - } - return escapeMacroResult(ret, state); - case "property": - argCheck(2, 3, strs.length); - ret = System.getProperty(strs[1]); - if(ret == null) { - if(strs.length == 3) { - ret = strs[2]; - }else { - throw new InvalidMacroException("Unknown system property \"" + strs[1] + "\"!"); - } - } - return escapeMacroResult(ret, state); - case "text": - argCheck(2, strs.length); - return escapeMacroResult(strs[1], state); - case "translate": - argCheckMin(2, strs.length); - String[] additionalArgs = new String[strs.length - 2]; - System.arraycopy(strs, 2, additionalArgs, 0, additionalArgs.length); - return escapeMacroResult(BungeeCord.getInstance().getTranslation(strs[1], (Object[])additionalArgs), state); - default: - return "{%" + content + "%}"; - } - }else { - return "{%" + content + "%}"; - } - }catch(InvalidMacroException ex) { - throw new IOException("Invalid macro: {% " + trimmed + " %}, message: " + ex.getMessage(), ex); - }catch(Throwable th) { - throw new IOException("Error processing: {% " + trimmed + " %}, raised: " + th.toString(), th); - } - } - - private static String escapeMacroResult(String str, State state) throws IOException { - if(str.length() > 0) { - if(state.evalAllowed && state.enableEval) { - str = loadTemplate(str, state.push()); - } - if(state.strEscape) { - str = jsonEscaper.toJson(str); - if(str.length() >= 2) { - str = str.substring(1, str.length() - 1); - } - } - if(state.htmlEscape) { - str = HtmlEscapers.htmlEscaper().escape(str); - } - } - return str; - } - - private static void argCheck(int expect, int actual) { - if(expect != actual) { - throw new InvalidMacroException("Wrong number of arguments (" + actual + ", expected " + expect + ")"); - } - } - - private static void argCheck(int expectMin, int expectMax, int actual) { - if(expectMin > actual || expectMax < actual) { - throw new InvalidMacroException("Wrong number of arguments (" + actual + ", expected " + expectMin + " to " + expectMax + ")"); - } - } - - private static void argCheckMin(int expectMin, int actual) { - if(expectMin > actual) { - throw new InvalidMacroException("Wrong number of arguments (expected " + expectMin + " or more, got " + actual + ")"); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/TestOutputStream.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/TestOutputStream.java deleted file mode 100644 index 26f5c3ff..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/TestOutputStream.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.io.IOException; -import java.io.OutputStream; - -public class TestOutputStream extends OutputStream { - - @Override - public void write(int b) throws IOException { - } - - @Override - public void write(byte[] b, int o, int l) throws IOException { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/VanillaDefaultSkinProfileLoader.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/VanillaDefaultSkinProfileLoader.java deleted file mode 100644 index 7c8ec7cc..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/VanillaDefaultSkinProfileLoader.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.function.Consumer; -import java.util.logging.Level; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.BinaryHttpClient; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.BinaryHttpClient.Response; -import net.md_5.bungee.protocol.Property; - -class VanillaDefaultSkinProfileLoader implements Consumer { - - private class ProfileSkinConsumerImpl implements Consumer { - - private final String uuid; - - private ProfileSkinConsumerImpl(String uuid) { - this.uuid = uuid; - } - - @Override - public void accept(Response response) { - if(response == null) { - EaglerXBungee.logger().severe("Request error (null)"); - doNotify(); - }else if(response.exception != null) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception loading vanilla default profile!", response.exception); - doNotify(); - }else if(response.code != 200) { - EaglerXBungee.logger().severe("Recieved code " + response.code + " while looking up profile of " + uuid); - doNotify(); - }else if (response.data == null) { - EaglerXBungee.logger().severe("Recieved null payload while looking up profile of " + uuid); - doNotify(); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - JsonElement propsElement = json.get("properties"); - if(propsElement != null) { - JsonArray properties = propsElement.getAsJsonArray(); - if(properties.size() > 0) { - for(int i = 0, l = properties.size(); i < l; ++i) { - JsonElement prop = properties.get(i); - if(prop.isJsonObject()) { - JsonObject propObj = prop.getAsJsonObject(); - if(propObj.get("name").getAsString().equals("textures")) { - JsonElement value = propObj.get("value"); - JsonElement signature = propObj.get("signature"); - if(value != null) { - Property newProp = new Property("textures", value.getAsString(), - signature != null ? signature.getAsString() : null); - config.eaglerPlayersVanillaSkinCached = new Property[] { newProp, EaglerBungeeConfig.isEaglerProperty }; - } - EaglerXBungee.logger().info("Loaded vanilla profile: " + config.getEaglerPlayersVanillaSkin()); - doNotify(); - return; - } - } - } - } - } - EaglerXBungee.logger().warning("No skin was found for: " + config.getEaglerPlayersVanillaSkin()); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception processing name to UUID lookup response!", t); - } - doNotify(); - } - } - - } - - private final EaglerBungeeConfig config; - private volatile boolean isLocked = true; - private final Object lock = new Object(); - - private VanillaDefaultSkinProfileLoader(EaglerBungeeConfig config) { - this.config = config; - } - - @Override - public void accept(Response response) { - if(response == null) { - EaglerXBungee.logger().severe("Request error (null)"); - doNotify(); - }else if(response.exception != null) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception loading vanilla default profile!", response.exception); - doNotify(); - }else if(response.code != 200) { - EaglerXBungee.logger().severe("Recieved code " + response.code + " while looking up UUID of " + config.getEaglerPlayersVanillaSkin()); - doNotify(); - }else if (response.data == null) { - EaglerXBungee.logger().severe("Recieved null payload while looking up UUID of " + config.getEaglerPlayersVanillaSkin()); - doNotify(); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String uuid = json.get("id").getAsString(); - URI requestURI = URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); - BinaryHttpClient.asyncRequest("GET", requestURI, new ProfileSkinConsumerImpl(uuid)); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception processing name to UUID lookup response!", t); - doNotify(); - } - } - } - - private void doNotify() { - synchronized(lock) { - if(isLocked) { - isLocked = false; - lock.notify(); - } - } - } - - static void lookupVanillaSkinUser(EaglerBungeeConfig config) { - String user = config.getEaglerPlayersVanillaSkin(); - EaglerXBungee.logger().info("Loading vanilla profile: " + user); - URI requestURI = URI.create("https://api.mojang.com/users/profiles/minecraft/" + user); - VanillaDefaultSkinProfileLoader loader = new VanillaDefaultSkinProfileLoader(config); - synchronized(loader.lock) { - BinaryHttpClient.asyncRequest("GET", requestURI, loader); - if(loader.isLocked) { - try { - loader.lock.wait(5000l); - } catch (InterruptedException e) { - } - if(loader.isLocked) { - EaglerXBungee.logger().warning("Profile load timed out"); - } - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPacketEventListener.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPacketEventListener.java deleted file mode 100644 index 30131544..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPacketEventListener.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers; - -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.logging.Level; - -import org.apache.commons.codec.binary.Base64; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.BackendRPCSessionHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinPackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinService; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.connection.Server; -import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.PluginMessageEvent; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.api.event.ServerConnectedEvent; -import net.md_5.bungee.api.event.ServerDisconnectEvent; -import net.md_5.bungee.api.plugin.Listener; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.event.EventHandler; -import net.md_5.bungee.protocol.Property; - -public class EaglerPacketEventListener implements Listener { - - public static final String GET_DOMAIN_CHANNEL = "EAG|GetDomain"; - - public final EaglerXBungee plugin; - - public EaglerPacketEventListener(EaglerXBungee plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onPluginMessage(final PluginMessageEvent event) { - if(event.getSender() instanceof UserConnection) { - final UserConnection player = (UserConnection)event.getSender(); - String tag = event.getTag(); - if(player.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)player.getPendingConnection(); - GameProtocolMessageController msgController = initialHandler.getEaglerMessageController(); - if(msgController != null) { - try { - if(msgController.handlePacket(tag, event.getData())) { - event.setCancelled(true); - return; - } - } catch (Throwable e) { - event.getSender().disconnect(new TextComponent("Eaglercraft packet error!")); - event.setCancelled(true); - return; - } - } - } - if(tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME) || tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN)) { - event.getSender().disconnect(new TextComponent("Nope!")); - event.setCancelled(true); - return; - } - if(tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME_READY) || tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN)) { - event.setCancelled(true); - return; - } - }else if(event.getSender() instanceof Server && event.getReceiver() instanceof UserConnection) { - UserConnection player = (UserConnection)event.getReceiver(); - String tag = event.getTag(); - if(player.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)player.getPendingConnection(); - if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(tag) || tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN)) { - event.setCancelled(true); - try { - initialHandler.handleBackendRPCPacket((Server)event.getSender(), event.getData()); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + ((UserConnection) event.getReceiver()).getName() - + "]: Caught an exception handling backend RPC packet!", t); - } - }else if(GET_DOMAIN_CHANNEL.equals(tag)) { - event.setCancelled(true); - String domain = initialHandler.getOrigin(); - if(domain != null) { - ((Server)event.getSender()).sendData("EAG|Domain", domain.getBytes(StandardCharsets.UTF_8)); - }else { - ((Server)event.getSender()).sendData("EAG|Domain", new byte[] { 0 }); - } - } - }else { - if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(tag) || tag.equals(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN)) { - event.setCancelled(true); - try { - BackendRPCSessionHandler.handlePacketOnVanilla((Server) event.getSender(), - (UserConnection) event.getReceiver(), event.getData()); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + ((UserConnection) event.getReceiver()).getName() - + "]: Caught an exception handling backend RPC packet!", t); - } - } - } - } - } - - @EventHandler - public void onPostLogin(PostLoginEvent event) { - ProxiedPlayer p = event.getPlayer(); - if(p instanceof UserConnection) { - UserConnection player = (UserConnection)p; - InitialHandler handler = player.getPendingConnection(); - LoginResult res = handler.getLoginProfile(); - if(res != null) { - Property[] props = res.getProperties(); - if(props.length > 0) { - for(int i = 0; i < props.length; ++i) { - Property pp = props[i]; - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = SkinService.sanitizeTextureURL(url.getAsString()); - plugin.getSkinService().registerTextureToPlayerAssociation(urlStr, player.getUniqueId()); - } - } - }catch(Throwable t) { - } - } - } - } - } - EaglerAuthConfig authConf = plugin.getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = plugin.getAuthService(); - if(srv != null) { - srv.handleVanillaLogin(event); - } - } - } - } - - @EventHandler - public void onConnectionLost(PlayerDisconnectEvent event) { - UUID uuid = event.getPlayer().getUniqueId(); - plugin.getSkinService().unregisterPlayer(uuid); - plugin.getCapeService().unregisterPlayer(uuid); - if(event.getPlayer() instanceof UserConnection) { - UserConnection player = (UserConnection)event.getPlayer(); - if((player.getPendingConnection() instanceof EaglerInitialHandler) - && ((EaglerInitialHandler) player.getPendingConnection()).getEaglerListenerConfig() - .getEnableVoiceChat()) { - plugin.getVoiceService().handlePlayerLoggedOut(player); - } - } - } - - @EventHandler - public void onServerConnected(ServerConnectedEvent event) { - if(event.getPlayer() instanceof UserConnection) { - EaglerPipeline.addServerConnectListener((UserConnection)event.getPlayer()); - } - } - - @EventHandler - public void onServerDisconnected(ServerDisconnectEvent event) { - if(event.getPlayer() instanceof UserConnection) { - UserConnection player = (UserConnection)event.getPlayer(); - if(player.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler handler = (EaglerInitialHandler) player.getPendingConnection(); - BackendRPCSessionHandler rpcHandler = handler.getRPCSessionHandler(); - if(rpcHandler != null) { - rpcHandler.handleConnectionLost(event.getTarget()); - } - if(handler.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerDisconnected(player, event.getTarget()); - } - } - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPluginEventListener.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPluginEventListener.java deleted file mode 100644 index af124b0e..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/handlers/EaglerPluginEventListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.handlers; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.md_5.bungee.api.event.ProxyReloadEvent; -import net.md_5.bungee.api.plugin.Listener; -import net.md_5.bungee.event.EventHandler; - -public class EaglerPluginEventListener implements Listener { - - public final EaglerXBungee plugin; - - public EaglerPluginEventListener(EaglerXBungee plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onReload(ProxyReloadEvent evt) { - plugin.reload(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrBuilder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrBuilder.java deleted file mode 100644 index 6ca2cd8a..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrBuilder.java +++ /dev/null @@ -1,3141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.repackage.lang3; - -import java.io.IOException; -import java.io.Reader; -import java.io.Serializable; -import java.io.Writer; -import java.nio.CharBuffer; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -import org.apache.commons.lang3.CharUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.Builder; - -/** - * Builds a string from constituent parts providing a more flexible and powerful - * API than StringBuffer. - *

- * The main differences from StringBuffer/StringBuilder are: - *

- *
    - *
  • Not synchronized
  • - *
  • Not final
  • - *
  • Subclasses have direct access to character array
  • - *
  • Additional methods - *
      - *
    • appendWithSeparators - adds an array of values, with a separator
    • - *
    • appendPadding - adds a length padding characters
    • - *
    • appendFixedLength - adds a fixed width field to the builder
    • - *
    • toCharArray/getChars - simpler ways to get a range of the character - * array
    • - *
    • delete - delete char or string
    • - *
    • replace - search and replace for a char or string
    • - *
    • leftString/rightString/midString - substring without exceptions
    • - *
    • contains - whether the builder contains a char or string
    • - *
    • size/clear/isEmpty - collections style API methods
    • - *
    - *
  • - *
  • Views - *
      - *
    • asTokenizer - uses the internal buffer as the source of a - * StrTokenizer
    • - *
    • asReader - uses the internal buffer as the source of a Reader
    • - *
    • asWriter - allows a Writer to write directly to the internal buffer
    • - *
    - *
  • - *
- *

- * The aim has been to provide an API that mimics very closely what StringBuffer - * provides, but with additional methods. It should be noted that some edge - * cases, with invalid indices or null input, have been altered - see individual - * methods. The biggest of these changes is that by default, null will not - * output the text 'null'. This can be controlled by a property, - * {@link #setNullText(String)}. - *

- * Prior to 3.0, this class implemented Cloneable but did not implement the - * clone method so could not be used. From 3.0 onwards it no longer implements - * the interface. - * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * TextStringBuilder instead - */ -//@Deprecated -public class StrBuilder implements CharSequence, Appendable, Serializable, Builder { - - /** - * The extra capacity for new builders. - */ - static final int CAPACITY = 32; - - /** - * Required for serialization support. - * - * @see java.io.Serializable - */ - private static final long serialVersionUID = 7628716375283629643L; - - /** Internal data storage. */ - protected char[] buffer; // TODO make private? - /** Current size of the buffer. */ - protected int size; // TODO make private? - /** The new line. */ - private String newLine; - /** The null text. */ - private String nullText; - - // ----------------------------------------------------------------------- - /** - * Constructor that creates an empty builder initial capacity 32 characters. - */ - public StrBuilder() { - this(CAPACITY); - } - - /** - * Constructor that creates an empty builder the specified initial capacity. - * - * @param initialCapacity the initial capacity, zero or less will be converted - * to 32 - */ - public StrBuilder(int initialCapacity) { - if (initialCapacity <= 0) { - initialCapacity = CAPACITY; - } - buffer = new char[initialCapacity]; - } - - /** - * Constructor that creates a builder from the string, allocating 32 extra - * characters for growth. - * - * @param str the string to copy, null treated as blank string - */ - public StrBuilder(final String str) { - if (str == null) { - buffer = new char[CAPACITY]; - } else { - buffer = new char[str.length() + CAPACITY]; - append(str); - } - } - - // ----------------------------------------------------------------------- - /** - * Gets the text to be appended when a new line is added. - * - * @return the new line text, null means use system default - */ - public String getNewLineText() { - return newLine; - } - - /** - * Sets the text to be appended when a new line is added. - * - * @param newLine the new line text, null means use system default - * @return this, to enable chaining - */ - public StrBuilder setNewLineText(final String newLine) { - this.newLine = newLine; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the text to be appended when null is added. - * - * @return the null text, null means no append - */ - public String getNullText() { - return nullText; - } - - /** - * Sets the text to be appended when null is added. - * - * @param nullText the null text, null means no append - * @return this, to enable chaining - */ - public StrBuilder setNullText(String nullText) { - if (nullText != null && nullText.isEmpty()) { - nullText = null; - } - this.nullText = nullText; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the length of the string builder. - * - * @return the length - */ - @Override - public int length() { - return size; - } - - /** - * Updates the length of the builder by either dropping the last characters or - * adding filler of Unicode zero. - * - * @param length the length to set to, must be zero or positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the length is negative - */ - public StrBuilder setLength(final int length) { - if (length < 0) { - throw new StringIndexOutOfBoundsException(length); - } - if (length < size) { - size = length; - } else if (length > size) { - ensureCapacity(length); - final int oldEnd = size; - final int newEnd = length; - size = length; - for (int i = oldEnd; i < newEnd; i++) { - buffer[i] = CharUtils.NUL; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the current size of the internal character array buffer. - * - * @return the capacity - */ - public int capacity() { - return buffer.length; - } - - /** - * Checks the capacity and ensures that it is at least the size specified. - * - * @param capacity the capacity to ensure - * @return this, to enable chaining - */ - public StrBuilder ensureCapacity(final int capacity) { - if (capacity > buffer.length) { - final char[] old = buffer; - buffer = new char[capacity * 2]; - System.arraycopy(old, 0, buffer, 0, size); - } - return this; - } - - /** - * Minimizes the capacity to the actual length of the string. - * - * @return this, to enable chaining - */ - public StrBuilder minimizeCapacity() { - if (buffer.length > length()) { - final char[] old = buffer; - buffer = new char[length()]; - System.arraycopy(old, 0, buffer, 0, size); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the length of the string builder. - *

- * This method is the same as {@link #length()} and is provided to match the API - * of Collections. - * - * @return the length - */ - public int size() { - return size; - } - - /** - * Checks is the string builder is empty (convenience Collections API style - * method). - *

- * This method is the same as checking {@link #length()} and is provided to - * match the API of Collections. - * - * @return {@code true} if the size is {@code 0}. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Checks is the string builder is not empty (convenience Collections API style - * method). - *

- * This method is the same as checking {@link #length()} and is provided to - * match the API of Collections. - * - * @return {@code true} if the size is greater than {@code 0}. - * @since 3.12.0 - */ - public boolean isNotEmpty() { - return size > 0; - } - - /** - * Clears the string builder (convenience Collections API style method). - *

- * This method does not reduce the size of the internal character buffer. To do - * that, call {@code clear()} followed by {@link #minimizeCapacity()}. - *

- * This method is the same as {@link #setLength(int)} called with zero and is - * provided to match the API of Collections. - * - * @return this, to enable chaining - */ - public StrBuilder clear() { - size = 0; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the character at the specified index. - * - * @see #setCharAt(int, char) - * @see #deleteCharAt(int) - * @param index the index to retrieve, must be valid - * @return the character at the index - * @throws IndexOutOfBoundsException if the index is invalid - */ - @Override - public char charAt(final int index) { - if (index < 0 || index >= length()) { - throw new StringIndexOutOfBoundsException(index); - } - return buffer[index]; - } - - /** - * Sets the character at the specified index. - * - * @see #charAt(int) - * @see #deleteCharAt(int) - * @param index the index to set - * @param ch the new character - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder setCharAt(final int index, final char ch) { - if (index < 0 || index >= length()) { - throw new StringIndexOutOfBoundsException(index); - } - buffer[index] = ch; - return this; - } - - /** - * Deletes the character at the specified index. - * - * @see #charAt(int) - * @see #setCharAt(int, char) - * @param index the index to delete - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder deleteCharAt(final int index) { - if (index < 0 || index >= size) { - throw new StringIndexOutOfBoundsException(index); - } - deleteImpl(index, index + 1, 1); - return this; - } - - // ----------------------------------------------------------------------- - /** - * Copies the builder's character array into a new character array. - * - * @return a new array that represents the contents of the builder - */ - public char[] toCharArray() { - if (size == 0) { - return new char[0]; - } - final char[] chars = new char[size]; - System.arraycopy(buffer, 0, chars, 0, size); - return chars; - } - - /** - * Copies part of the builder's character array into a new character array. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return a new array that holds part of the contents of the builder - * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is - * invalid (but endIndex greater than size is - * valid) - */ - public char[] toCharArray(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - final int len = endIndex - startIndex; - if (len == 0) { - return new char[0]; - } - final char[] chars = new char[len]; - System.arraycopy(buffer, startIndex, chars, 0, len); - return chars; - } - - /** - * Copies the character array into the specified array. - * - * @param destination the destination array, null will cause an array to be - * created - * @return the input array, unless that was null or too small - */ - public char[] getChars(char[] destination) { - final int len = length(); - if (destination == null || destination.length < len) { - destination = new char[len]; - } - System.arraycopy(buffer, 0, destination, 0, len); - return destination; - } - - /** - * Copies the character array into the specified array. - * - * @param startIndex first index to copy, inclusive, must be valid - * @param endIndex last index, exclusive, must be valid - * @param destination the destination array, must not be null or too small - * @param destinationIndex the index to start copying in destination - * @throws NullPointerException if the array is null - * @throws IndexOutOfBoundsException if any index is invalid - */ - public void getChars(final int startIndex, final int endIndex, final char[] destination, - final int destinationIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex < 0 || endIndex > length()) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException("end < start"); - } - System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex); - } - - // ----------------------------------------------------------------------- - /** - * If possible, reads chars from the provided {@link Readable} directly into - * underlying character buffer without making extra copies. - * - * @param readable object to read from - * @return the number of characters read - * @throws IOException if an I/O error occurs. - * - * @since 3.4 - * @see #appendTo(Appendable) - */ - public int readFrom(final Readable readable) throws IOException { - final int oldSize = size; - if (readable instanceof Reader) { - final Reader r = (Reader) readable; - ensureCapacity(size + 1); - int read; - while ((read = r.read(buffer, size, buffer.length - size)) != -1) { - size += read; - ensureCapacity(size + 1); - } - } else if (readable instanceof CharBuffer) { - final CharBuffer cb = (CharBuffer) readable; - final int remaining = cb.remaining(); - ensureCapacity(size + remaining); - cb.get(buffer, size, remaining); - size += remaining; - } else { - while (true) { - ensureCapacity(size + 1); - final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size); - final int read = readable.read(buf); - if (read == -1) { - break; - } - size += read; - } - } - return size - oldSize; - } - - // ----------------------------------------------------------------------- - /** - * Appends the new line string to this string builder. - *

- * The new line string can be altered using {@link #setNewLineText(String)}. - * This might be used to force the output to always use Unix line endings even - * when on Windows. - * - * @return this, to enable chaining - */ - public StrBuilder appendNewLine() { - if (newLine == null) { - append(System.lineSeparator()); - return this; - } - return append(newLine); - } - - /** - * Appends the text representing {@code null} to this string builder. - * - * @return this, to enable chaining - */ - public StrBuilder appendNull() { - if (nullText == null) { - return this; - } - return append(nullText); - } - - /** - * Appends an object to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param obj the object to append - * @return this, to enable chaining - */ - public StrBuilder append(final Object obj) { - if (obj == null) { - return appendNull(); - } - if (obj instanceof CharSequence) { - return append((CharSequence) obj); - } - return append(obj.toString()); - } - - /** - * Appends a CharSequence to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param seq the CharSequence to append - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final CharSequence seq) { - if (seq == null) { - return appendNull(); - } - if (seq instanceof StrBuilder) { - return append((StrBuilder) seq); - } - if (seq instanceof StringBuilder) { - return append((StringBuilder) seq); - } - if (seq instanceof StringBuffer) { - return append((StringBuffer) seq); - } - if (seq instanceof CharBuffer) { - return append((CharBuffer) seq); - } - return append(seq.toString()); - } - - /** - * Appends part of a CharSequence to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param seq the CharSequence to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final CharSequence seq, final int startIndex, final int length) { - if (seq == null) { - return appendNull(); - } - return append(seq.toString(), startIndex, length); - } - - /** - * Appends a string to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string to append - * @return this, to enable chaining - */ - public StrBuilder append(final String str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a string to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final String str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Calls {@link String#format(String, Object...)} and appends the result. - * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining - * @see String#format(String, Object...) - * @since 3.2 - */ - public StrBuilder append(final String format, final Object... objs) { - return append(String.format(format, objs)); - } - - /** - * Appends the contents of a char buffer to this string builder. Appending null - * will call {@link #appendNull()}. - * - * @param buf the char buffer to append - * @return this, to enable chaining - * @since 3.4 - */ - public StrBuilder append(final CharBuffer buf) { - if (buf == null) { - return appendNull(); - } - if (buf.hasArray()) { - final int length = buf.remaining(); - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length); - size += length; - } else { - append(buf.toString()); - } - return this; - } - - /** - * Appends the contents of a char buffer to this string builder. Appending null - * will call {@link #appendNull()}. - * - * @param buf the char buffer to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.4 - */ - public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) { - if (buf == null) { - return appendNull(); - } - if (buf.hasArray()) { - final int totalLength = buf.remaining(); - if (startIndex < 0 || startIndex > totalLength) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > totalLength) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length); - size += length; - } else { - append(buf.toString(), startIndex, length); - } - return this; - } - - /** - * Appends a string buffer to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string buffer to append - * @return this, to enable chaining - */ - public StrBuilder append(final StringBuffer str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a string buffer to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final StringBuffer str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends a StringBuilder to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the StringBuilder to append - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder append(final StringBuilder str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a StringBuilder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the StringBuilder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder append(final StringBuilder str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends another string builder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - */ - public StrBuilder append(final StrBuilder str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - System.arraycopy(str.buffer, 0, buffer, len, strLen); - size += strLen; - } - return this; - } - - /** - * Appends part of a string builder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final StrBuilder str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends a char array to the string builder. Appending null will call - * {@link #appendNull()}. - * - * @param chars the char array to append - * @return this, to enable chaining - */ - public StrBuilder append(final char[] chars) { - if (chars == null) { - return appendNull(); - } - final int strLen = chars.length; - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - System.arraycopy(chars, 0, buffer, len, strLen); - size += strLen; - } - return this; - } - - /** - * Appends a char array to the string builder. Appending null will call - * {@link #appendNull()}. - * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final char[] chars, final int startIndex, final int length) { - if (chars == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length); - } - if (length < 0 || (startIndex + length) > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid length: " + length); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(chars, startIndex, buffer, len, length); - size += length; - } - return this; - } - - /** - * Appends a boolean value to the string builder. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final boolean value) { - if (value) { - ensureCapacity(size + 4); - buffer[size++] = 't'; - buffer[size++] = 'r'; - buffer[size++] = 'u'; - buffer[size++] = 'e'; - } else { - ensureCapacity(size + 5); - buffer[size++] = 'f'; - buffer[size++] = 'a'; - buffer[size++] = 'l'; - buffer[size++] = 's'; - buffer[size++] = 'e'; - } - return this; - } - - /** - * Appends a char value to the string builder. - * - * @param ch the value to append - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final char ch) { - final int len = length(); - ensureCapacity(len + 1); - buffer[size++] = ch; - return this; - } - - /** - * Appends an int value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final int value) { - return append(String.valueOf(value)); - } - - /** - * Appends a long value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final long value) { - return append(String.valueOf(value)); - } - - /** - * Appends a float value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final float value) { - return append(String.valueOf(value)); - } - - /** - * Appends a double value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final double value) { - return append(String.valueOf(value)); - } - - // ----------------------------------------------------------------------- - /** - * Appends an object followed by a new line to this string builder. Appending - * null will call {@link #appendNull()}. - * - * @param obj the object to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final Object obj) { - return append(obj).appendNewLine(); - } - - /** - * Appends a string followed by a new line to this string builder. Appending - * null will call {@link #appendNull()}. - * - * @param str the string to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final String str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final String str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Calls {@link String#format(String, Object...)} and appends the result. - * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining - * @see String#format(String, Object...) - * @since 3.2 - */ - public StrBuilder appendln(final String format, final Object... objs) { - return append(format, objs).appendNewLine(); - } - - /** - * Appends a string buffer followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string buffer to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StringBuffer str) { - return append(str).appendNewLine(); - } - - /** - * Appends a string builder followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder appendln(final StringBuilder str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string builder followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder appendln(final StringBuilder str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends part of a string buffer followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StringBuffer str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends another string builder followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StrBuilder str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string builder followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends a char array followed by a new line to the string builder. Appending - * null will call {@link #appendNull()}. - * - * @param chars the char array to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char[] chars) { - return append(chars).appendNewLine(); - } - - /** - * Appends a char array followed by a new line to the string builder. Appending - * null will call {@link #appendNull()}. - * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char[] chars, final int startIndex, final int length) { - return append(chars, startIndex, length).appendNewLine(); - } - - /** - * Appends a boolean value followed by a new line to the string builder. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final boolean value) { - return append(value).appendNewLine(); - } - - /** - * Appends a char value followed by a new line to the string builder. - * - * @param ch the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char ch) { - return append(ch).appendNewLine(); - } - - /** - * Appends an int value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final int value) { - return append(value).appendNewLine(); - } - - /** - * Appends a long value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final long value) { - return append(value).appendNewLine(); - } - - /** - * Appends a float value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final float value) { - return append(value).appendNewLine(); - } - - /** - * Appends a double value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final double value) { - return append(value).appendNewLine(); - } - - // ----------------------------------------------------------------------- - /** - * Appends each item in an array to the builder without any separators. - * Appending a null array will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param the element type - * @param array the array to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(@SuppressWarnings("unchecked") final T... array) { - /* - * @SuppressWarnings used to hide warning about vararg usage. We cannot - * use @SafeVarargs, since this method is not final. Using @SuppressWarnings is - * fine, because it isn't inherited by subclasses, so each subclass must vouch - * for itself whether its use of 'array' is safe. - */ - if (array.length > 0) { - for (final Object element : array) { - append(element); - } - } - return this; - } - - /** - * Appends each item in an iterable to the builder without any separators. - * Appending a null iterable will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param iterable the iterable to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(final Iterable iterable) { - if (iterable != null) { - for (final Object o : iterable) { - append(o); - } - } - return this; - } - - /** - * Appends each item in an iterator to the builder without any separators. - * Appending a null iterator will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param it the iterator to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(final Iterator it) { - if (it != null) { - while (it.hasNext()) { - append(it.next()); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends an array placing separators between each value, but not before the - * first or after the last. Appending a null array will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param array the array to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Object[] array, final String separator) { - if (array != null && array.length > 0) { - final String sep = Objects.toString(separator, ""); - append(array[0]); - for (int i = 1; i < array.length; i++) { - append(sep); - append(array[i]); - } - } - return this; - } - - /** - * Appends an iterable placing separators between each value, but not before the - * first or after the last. Appending a null iterable will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param iterable the iterable to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Iterable iterable, final String separator) { - if (iterable != null) { - final String sep = Objects.toString(separator, ""); - final Iterator it = iterable.iterator(); - while (it.hasNext()) { - append(it.next()); - if (it.hasNext()) { - append(sep); - } - } - } - return this; - } - - /** - * Appends an iterator placing separators between each value, but not before the - * first or after the last. Appending a null iterator will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param it the iterator to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Iterator it, final String separator) { - if (it != null) { - final String sep = Objects.toString(separator, ""); - while (it.hasNext()) { - append(it.next()); - if (it.hasNext()) { - append(sep); - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends a separator if the builder is currently non-empty. Appending a null - * separator will have no effect. The separator is appended using - * {@link #append(String)}. - *

- * This method is useful for adding a separator each time around the loop except - * the first. - * - *

-	 * for (Iterator it = list.iterator(); it.hasNext();) {
-	 * 	appendSeparator(",");
-	 * 	append(it.next());
-	 * }
-	 * 
- * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final String separator) { - return appendSeparator(separator, null); - } - - /** - * Appends one of both separators to the StrBuilder. If the builder is currently - * empty it will append the defaultIfEmpty-separator Otherwise it will append - * the standard-separator - * - * Appending a null separator will have no effect. The separator is appended - * using {@link #append(String)}. - *

- * This method is for example useful for constructing queries - * - *

-	 * StrBuilder whereClause = new StrBuilder();
-	 * if (searchCommand.getPriority() != null) {
-	 *  whereClause.appendSeparator(" and", " where");
-	 *  whereClause.append(" priority = ?")
-	 * }
-	 * if (searchCommand.getComponent() != null) {
-	 *  whereClause.appendSeparator(" and", " where");
-	 *  whereClause.append(" component = ?")
-	 * }
-	 * selectClause.append(whereClause)
-	 * 
- * - * @param standard the separator if builder is not empty, null means no - * separator - * @param defaultIfEmpty the separator if builder is empty, null means no - * separator - * @return this, to enable chaining - * @since 2.5 - */ - public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) { - final String str = isEmpty() ? defaultIfEmpty : standard; - if (str != null) { - append(str); - } - return this; - } - - /** - * Appends a separator if the builder is currently non-empty. The separator is - * appended using {@link #append(char)}. - *

- * This method is useful for adding a separator each time around the loop except - * the first. - * - *

-	 * for (Iterator it = list.iterator(); it.hasNext();) {
-	 * 	appendSeparator(',');
-	 * 	append(it.next());
-	 * }
-	 * 
- * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final char separator) { - if (isNotEmpty()) { - append(separator); - } - return this; - } - - /** - * Append one of both separators to the builder If the builder is currently - * empty it will append the defaultIfEmpty-separator Otherwise it will append - * the standard-separator - * - * The separator is appended using {@link #append(char)}. - * - * @param standard the separator if builder is not empty - * @param defaultIfEmpty the separator if builder is empty - * @return this, to enable chaining - * @since 2.5 - */ - public StrBuilder appendSeparator(final char standard, final char defaultIfEmpty) { - if (isNotEmpty()) { - append(standard); - } else { - append(defaultIfEmpty); - } - return this; - } - - /** - * Appends a separator to the builder if the loop index is greater than zero. - * Appending a null separator will have no effect. The separator is appended - * using {@link #append(String)}. - *

- * This method is useful for adding a separator each time around the loop except - * the first. - *

- * - *
-	 * for (int i = 0; i < list.size(); i++) {
-	 * 	appendSeparator(",", i);
-	 * 	append(list.get(i));
-	 * }
-	 * 
- * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use, null means no separator - * @param loopIndex the loop index - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final String separator, final int loopIndex) { - if (separator != null && loopIndex > 0) { - append(separator); - } - return this; - } - - /** - * Appends a separator to the builder if the loop index is greater than zero. - * The separator is appended using {@link #append(char)}. - *

- * This method is useful for adding a separator each time around the loop except - * the first. - *

- * - *
-	 * for (int i = 0; i < list.size(); i++) {
-	 * 	appendSeparator(",", i);
-	 * 	append(list.get(i));
-	 * }
-	 * 
- * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use - * @param loopIndex the loop index - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final char separator, final int loopIndex) { - if (loopIndex > 0) { - append(separator); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends the pad character to the builder the specified number of times. - * - * @param length the length to append, negative means no append - * @param padChar the character to append - * @return this, to enable chaining - */ - public StrBuilder appendPadding(final int length, final char padChar) { - if (length >= 0) { - ensureCapacity(size + length); - for (int i = 0; i < length; i++) { - buffer[size++] = padChar; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends an object to the builder padding on the left to a fixed width. The - * {@code toString} of the object is used. If the object is larger than the - * length, the left hand side is lost. If the object is null, the null text - * value is used. - * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) { - if (width > 0) { - ensureCapacity(size + width); - String str = (obj == null ? getNullText() : obj.toString()); - if (str == null) { - str = StringUtils.EMPTY; - } - final int strLen = str.length(); - if (strLen >= width) { - str.getChars(strLen - width, strLen, buffer, size); - } else { - final int padLen = width - strLen; - for (int i = 0; i < padLen; i++) { - buffer[size + i] = padChar; - } - str.getChars(0, strLen, buffer, size + padLen); - } - size += width; - } - return this; - } - - /** - * Appends an object to the builder padding on the left to a fixed width. The - * {@code String.valueOf} of the {@code int} value is used. If the formatted - * value is larger than the length, the left hand side is lost. - * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) { - return appendFixedWidthPadLeft(String.valueOf(value), width, padChar); - } - - /** - * Appends an object to the builder padding on the right to a fixed length. The - * {@code toString} of the object is used. If the object is larger than the - * length, the right hand side is lost. If the object is null, null text value - * is used. - * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) { - if (width > 0) { - ensureCapacity(size + width); - String str = (obj == null ? getNullText() : obj.toString()); - if (str == null) { - str = StringUtils.EMPTY; - } - final int strLen = str.length(); - if (strLen >= width) { - str.getChars(0, width, buffer, size); - } else { - final int padLen = width - strLen; - str.getChars(0, strLen, buffer, size); - for (int i = 0; i < padLen; i++) { - buffer[size + strLen + i] = padChar; - } - } - size += width; - } - return this; - } - - /** - * Appends an object to the builder padding on the right to a fixed length. The - * {@code String.valueOf} of the {@code int} value is used. If the object is - * larger than the length, the right hand side is lost. - * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) { - return appendFixedWidthPadRight(String.valueOf(value), width, padChar); - } - - // ----------------------------------------------------------------------- - /** - * Inserts the string representation of an object into this builder. Inserting - * null will use the stored null text value. - * - * @param index the index to add at, must be valid - * @param obj the object to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final Object obj) { - if (obj == null) { - return insert(index, nullText); - } - return insert(index, obj.toString()); - } - - /** - * Inserts the string into this builder. Inserting null will use the stored null - * text value. - * - * @param index the index to add at, must be valid - * @param str the string to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, String str) { - validateIndex(index); - if (str == null) { - str = nullText; - } - if (str != null) { - final int strLen = str.length(); - if (strLen > 0) { - final int newSize = size + strLen; - ensureCapacity(newSize); - System.arraycopy(buffer, index, buffer, index + strLen, size - index); - size = newSize; - str.getChars(0, strLen, buffer, index); - } - } - return this; - } - - /** - * Inserts the character array into this builder. Inserting null will use the - * stored null text value. - * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final char[] chars) { - validateIndex(index); - if (chars == null) { - return insert(index, nullText); - } - final int len = chars.length; - if (len > 0) { - ensureCapacity(size + len); - System.arraycopy(buffer, index, buffer, index + len, size - index); - System.arraycopy(chars, 0, buffer, index, len); - size += len; - } - return this; - } - - /** - * Inserts part of the character array into this builder. Inserting null will - * use the stored null text value. - * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @param offset the offset into the character array to start at, must be valid - * @param length the length of the character array part to copy, must be - * positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid - */ - public StrBuilder insert(final int index, final char[] chars, final int offset, final int length) { - validateIndex(index); - if (chars == null) { - return insert(index, nullText); - } - if (offset < 0 || offset > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid offset: " + offset); - } - if (length < 0 || offset + length > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid length: " + length); - } - if (length > 0) { - ensureCapacity(size + length); - System.arraycopy(buffer, index, buffer, index + length, size - index); - System.arraycopy(chars, offset, buffer, index, length); - size += length; - } - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(int index, final boolean value) { - validateIndex(index); - if (value) { - ensureCapacity(size + 4); - System.arraycopy(buffer, index, buffer, index + 4, size - index); - buffer[index++] = 't'; - buffer[index++] = 'r'; - buffer[index++] = 'u'; - buffer[index] = 'e'; - size += 4; - } else { - ensureCapacity(size + 5); - System.arraycopy(buffer, index, buffer, index + 5, size - index); - buffer[index++] = 'f'; - buffer[index++] = 'a'; - buffer[index++] = 'l'; - buffer[index++] = 's'; - buffer[index] = 'e'; - size += 5; - } - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final char value) { - validateIndex(index); - ensureCapacity(size + 1); - System.arraycopy(buffer, index, buffer, index + 1, size - index); - buffer[index] = value; - size++; - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final int value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final long value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final float value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final double value) { - return insert(index, String.valueOf(value)); - } - - // ----------------------------------------------------------------------- - /** - * Internal method to delete a range without validation. - * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param len the length, must be valid - * @throws IndexOutOfBoundsException if any index is invalid - */ - private void deleteImpl(final int startIndex, final int endIndex, final int len) { - System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex); - size -= len; - } - - /** - * Deletes the characters between the two specified indices. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder delete(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - final int len = endIndex - startIndex; - if (len > 0) { - deleteImpl(startIndex, endIndex, len); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes the character wherever it occurs in the builder. - * - * @param ch the character to delete - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final char ch) { - for (int i = 0; i < size; i++) { - if (buffer[i] == ch) { - final int start = i; - while (++i < size) { - if (buffer[i] != ch) { - break; - } - } - final int len = i - start; - deleteImpl(start, i, len); - i -= len; - } - } - return this; - } - - /** - * Deletes the character wherever it occurs in the builder. - * - * @param ch the character to delete - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final char ch) { - for (int i = 0; i < size; i++) { - if (buffer[i] == ch) { - deleteImpl(i, i + 1, 1); - break; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes the string wherever it occurs in the builder. - * - * @param str the string to delete, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final String str) { - final int len = (str == null ? 0 : str.length()); - if (len > 0) { - int index = indexOf(str, 0); - while (index >= 0) { - deleteImpl(index, index + len, len); - index = indexOf(str, index); - } - } - return this; - } - - /** - * Deletes the string wherever it occurs in the builder. - * - * @param str the string to delete, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final String str) { - final int len = (str == null ? 0 : str.length()); - if (len > 0) { - final int index = indexOf(str, 0); - if (index >= 0) { - deleteImpl(index, index + len, len); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes all parts of the builder that the matcher matches. - *

- * Matchers can be used to perform advanced deletion behavior. For example you - * could write a matcher to delete all occurrences where the character 'a' is - * followed by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final StrMatcher matcher) { - return replace(matcher, null, 0, size, -1); - } - - /** - * Deletes the first match within the builder using the specified matcher. - *

- * Matchers can be used to perform advanced deletion behavior. For example you - * could write a matcher to delete where the character 'a' is followed by a - * number. - * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final StrMatcher matcher) { - return replace(matcher, null, 0, size, 1); - } - - // ----------------------------------------------------------------------- - /** - * Internal method to delete a range without validation. - * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param removeLen the length to remove (endIndex - startIndex), must be valid - * @param insertStr the string to replace with, null means delete range - * @param insertLen the length of the insert string, must be valid - * @throws IndexOutOfBoundsException if any index is invalid - */ - private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, - final int insertLen) { - final int newSize = size - removeLen + insertLen; - if (insertLen != removeLen) { - ensureCapacity(newSize); - System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex); - size = newSize; - } - if (insertLen > 0) { - insertStr.getChars(0, insertLen, buffer, startIndex); - } - } - - /** - * Replaces a portion of the string builder with another string. The length of - * the inserted string does not have to match the removed length. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @param replaceStr the string to replace with, null means delete range - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) { - endIndex = validateRange(startIndex, endIndex); - final int insertLen = (replaceStr == null ? 0 : replaceStr.length()); - replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen); - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces the search character with the replace character throughout the - * builder. - * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final char search, final char replace) { - if (search != replace) { - for (int i = 0; i < size; i++) { - if (buffer[i] == search) { - buffer[i] = replace; - } - } - } - return this; - } - - /** - * Replaces the first instance of the search character with the replace - * character in the builder. - * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final char search, final char replace) { - if (search != replace) { - for (int i = 0; i < size; i++) { - if (buffer[i] == search) { - buffer[i] = replace; - break; - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces the search string with the replace string throughout the builder. - * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final String searchStr, final String replaceStr) { - final int searchLen = (searchStr == null ? 0 : searchStr.length()); - if (searchLen > 0) { - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - int index = indexOf(searchStr, 0); - while (index >= 0) { - replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen); - index = indexOf(searchStr, index + replaceLen); - } - } - return this; - } - - /** - * Replaces the first instance of the search string with the replace string. - * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final String searchStr, final String replaceStr) { - final int searchLen = (searchStr == null ? 0 : searchStr.length()); - if (searchLen > 0) { - final int index = indexOf(searchStr, 0); - if (index >= 0) { - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces all matches within the builder with the replace string. - *

- * Matchers can be used to perform advanced replace behavior. For example you - * could write a matcher to replace all occurrences where the character 'a' is - * followed by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) { - return replace(matcher, replaceStr, 0, size, -1); - } - - /** - * Replaces the first match within the builder with the replace string. - *

- * Matchers can be used to perform advanced replace behavior. For example you - * could write a matcher to replace where the character 'a' is followed by a - * number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) { - return replace(matcher, replaceStr, 0, size, 1); - } - - // ----------------------------------------------------------------------- - /** - * Advanced search and replaces within the builder using a matcher. - *

- * Matchers can be used to perform advanced behavior. For example you could - * write a matcher to delete all occurrences where the character 'a' is followed - * by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the string to replace the match with, null is a delete - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if - * too large it is treated as end of string - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if start index is invalid - */ - public StrBuilder replace(final StrMatcher matcher, final String replaceStr, final int startIndex, int endIndex, - final int replaceCount) { - endIndex = validateRange(startIndex, endIndex); - return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount); - } - - /** - * Replaces within the builder using a matcher. - *

- * Matchers can be used to perform advanced behavior. For example you could - * write a matcher to delete all occurrences where the character 'a' is followed - * by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the string to replace the match with, null is a delete - * @param from the start index, must be valid - * @param to the end index (exclusive), must be valid - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid - */ - private StrBuilder replaceImpl(final StrMatcher matcher, final String replaceStr, final int from, int to, - int replaceCount) { - if (matcher == null || size == 0) { - return this; - } - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - for (int i = from; i < to && replaceCount != 0; i++) { - final char[] buf = buffer; - final int removeLen = matcher.isMatch(buf, i, from, to); - if (removeLen > 0) { - replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen); - to = to - removeLen + replaceLen; - i = i + replaceLen - 1; - if (replaceCount > 0) { - replaceCount--; - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Reverses the string builder placing each character in the opposite index. - * - * @return this, to enable chaining - */ - public StrBuilder reverse() { - if (size == 0) { - return this; - } - - final int half = size / 2; - final char[] buf = buffer; - for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) { - final char swap = buf[leftIdx]; - buf[leftIdx] = buf[rightIdx]; - buf[rightIdx] = swap; - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Trims the builder by removing characters less than or equal to a space from - * the beginning and end. - * - * @return this, to enable chaining - */ - public StrBuilder trim() { - if (size == 0) { - return this; - } - int len = size; - final char[] buf = buffer; - int pos = 0; - while (pos < len && buf[pos] <= ' ') { - pos++; - } - while (pos < len && buf[len - 1] <= ' ') { - len--; - } - if (len < size) { - delete(len, size); - } - if (pos > 0) { - delete(0, pos); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Checks whether this builder starts with the specified string. - *

- * Note that this method handles null input quietly, unlike String. - * - * @param str the string to search for, null returns false - * @return true if the builder starts with the string - */ - public boolean startsWith(final String str) { - if (str == null) { - return false; - } - final int len = str.length(); - if (len == 0) { - return true; - } - if (len > size) { - return false; - } - for (int i = 0; i < len; i++) { - if (buffer[i] != str.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Checks whether this builder ends with the specified string. - *

- * Note that this method handles null input quietly, unlike String. - * - * @param str the string to search for, null returns false - * @return true if the builder ends with the string - */ - public boolean endsWith(final String str) { - if (str == null) { - return false; - } - final int len = str.length(); - if (len == 0) { - return true; - } - if (len > size) { - return false; - } - int pos = size - len; - for (int i = 0; i < len; i++, pos++) { - if (buffer[pos] != str.charAt(i)) { - return false; - } - } - return true; - } - - // ----------------------------------------------------------------------- - /** - * {@inheritDoc} - * - * @since 3.0 - */ - @Override - public CharSequence subSequence(final int startIndex, final int endIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex > size) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException(endIndex - startIndex); - } - return substring(startIndex, endIndex); - } - - /** - * Extracts a portion of this string builder as a string. - * - * @param start the start index, inclusive, must be valid - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - public String substring(final int start) { - return substring(start, size); - } - - /** - * Extracts a portion of this string builder as a string. - *

- * Note: This method treats an endIndex greater than the length of the builder - * as equal to the length of the builder, and continues without error, unlike - * StringBuffer or String. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - public String substring(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - return new String(buffer, startIndex, endIndex - startIndex); - } - - /** - * Extracts the leftmost characters from the string builder without throwing an - * exception. - *

- * This method extracts the left {@code length} characters from the builder. If - * this many characters are not available, the whole builder is returned. Thus - * the returned string may be shorter than the length requested. - * - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String leftString(final int length) { - if (length <= 0) { - return StringUtils.EMPTY; - } else if (length >= size) { - return new String(buffer, 0, size); - } else { - return new String(buffer, 0, length); - } - } - - /** - * Extracts the rightmost characters from the string builder without throwing an - * exception. - *

- * This method extracts the right {@code length} characters from the builder. If - * this many characters are not available, the whole builder is returned. Thus - * the returned string may be shorter than the length requested. - * - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String rightString(final int length) { - if (length <= 0) { - return StringUtils.EMPTY; - } else if (length >= size) { - return new String(buffer, 0, size); - } else { - return new String(buffer, size - length, length); - } - } - - /** - * Extracts some characters from the middle of the string builder without - * throwing an exception. - *

- * This method extracts {@code length} characters from the builder at the - * specified index. If the index is negative it is treated as zero. If the index - * is greater than the builder size, it is treated as the builder size. If the - * length is negative, the empty string is returned. If insufficient characters - * are available in the builder, as much as possible is returned. Thus the - * returned string may be shorter than the length requested. - * - * @param index the index to start at, negative means zero - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String midString(int index, final int length) { - if (index < 0) { - index = 0; - } - if (length <= 0 || index >= size) { - return StringUtils.EMPTY; - } - if (size <= index + length) { - return new String(buffer, index, size - index); - } - return new String(buffer, index, length); - } - - // ----------------------------------------------------------------------- - /** - * Checks if the string builder contains the specified char. - * - * @param ch the character to find - * @return true if the builder contains the character - */ - public boolean contains(final char ch) { - final char[] thisBuf = buffer; - for (int i = 0; i < this.size; i++) { - if (thisBuf[i] == ch) { - return true; - } - } - return false; - } - - /** - * Checks if the string builder contains the specified string. - * - * @param str the string to find - * @return true if the builder contains the string - */ - public boolean contains(final String str) { - return indexOf(str, 0) >= 0; - } - - /** - * Checks if the string builder contains a string matched using the specified - * matcher. - *

- * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to search for the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return true if the matcher finds a match in the builder - */ - public boolean contains(final StrMatcher matcher) { - return indexOf(matcher, 0) >= 0; - } - - // ----------------------------------------------------------------------- - /** - * Searches the string builder to find the first reference to the specified - * char. - * - * @param ch the character to find - * @return the first index of the character, or -1 if not found - */ - public int indexOf(final char ch) { - return indexOf(ch, 0); - } - - /** - * Searches the string builder to find the first reference to the specified - * char. - * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index of the character, or -1 if not found - */ - public int indexOf(final char ch, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (startIndex >= size) { - return -1; - } - final char[] thisBuf = buffer; - for (int i = startIndex; i < size; i++) { - if (thisBuf[i] == ch) { - return i; - } - } - return -1; - } - - /** - * Searches the string builder to find the first reference to the specified - * string. - *

- * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @return the first index of the string, or -1 if not found - */ - public int indexOf(final String str) { - return indexOf(str, 0); - } - - /** - * Searches the string builder to find the first reference to the specified - * string starting searching from the given index. - *

- * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index of the string, or -1 if not found - */ - public int indexOf(final String str, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (str == null || startIndex >= size) { - return -1; - } - final int strLen = str.length(); - if (strLen == 1) { - return indexOf(str.charAt(0), startIndex); - } - if (strLen == 0) { - return startIndex; - } - if (strLen > size) { - return -1; - } - final char[] thisBuf = buffer; - final int len = size - strLen + 1; - outer: for (int i = startIndex; i < len; i++) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != thisBuf[i + j]) { - continue outer; - } - } - return i; - } - return -1; - } - - /** - * Searches the string builder using the matcher to find the first match. - *

- * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return the first index matched, or -1 if not found - */ - public int indexOf(final StrMatcher matcher) { - return indexOf(matcher, 0); - } - - /** - * Searches the string builder using the matcher to find the first match - * searching from the given index. - *

- * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index matched, or -1 if not found - */ - public int indexOf(final StrMatcher matcher, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (matcher == null || startIndex >= size) { - return -1; - } - final int len = size; - final char[] buf = buffer; - for (int i = startIndex; i < len; i++) { - if (matcher.isMatch(buf, i, startIndex, len) > 0) { - return i; - } - } - return -1; - } - - // ----------------------------------------------------------------------- - /** - * Searches the string builder to find the last reference to the specified char. - * - * @param ch the character to find - * @return the last index of the character, or -1 if not found - */ - public int lastIndexOf(final char ch) { - return lastIndexOf(ch, size - 1); - } - - /** - * Searches the string builder to find the last reference to the specified char. - * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index of the character, or -1 if not found - */ - public int lastIndexOf(final char ch, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (startIndex < 0) { - return -1; - } - for (int i = startIndex; i >= 0; i--) { - if (buffer[i] == ch) { - return i; - } - } - return -1; - } - - /** - * Searches the string builder to find the last reference to the specified - * string. - *

- * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @return the last index of the string, or -1 if not found - */ - public int lastIndexOf(final String str) { - return lastIndexOf(str, size - 1); - } - - /** - * Searches the string builder to find the last reference to the specified - * string starting searching from the given index. - *

- * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index of the string, or -1 if not found - */ - public int lastIndexOf(final String str, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (str == null || startIndex < 0) { - return -1; - } - final int strLen = str.length(); - if (strLen > 0 && strLen <= size) { - if (strLen == 1) { - return lastIndexOf(str.charAt(0), startIndex); - } - - outer: for (int i = startIndex - strLen + 1; i >= 0; i--) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != buffer[i + j]) { - continue outer; - } - } - return i; - } - - } else if (strLen == 0) { - return startIndex; - } - return -1; - } - - /** - * Searches the string builder using the matcher to find the last match. - *

- * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return the last index matched, or -1 if not found - */ - public int lastIndexOf(final StrMatcher matcher) { - return lastIndexOf(matcher, size); - } - - /** - * Searches the string builder using the matcher to find the last match - * searching from the given index. - *

- * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index matched, or -1 if not found - */ - public int lastIndexOf(final StrMatcher matcher, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (matcher == null || startIndex < 0) { - return -1; - } - final char[] buf = buffer; - final int endIndex = startIndex + 1; - for (int i = startIndex; i >= 0; i--) { - if (matcher.isMatch(buf, i, 0, endIndex) > 0) { - return i; - } - } - return -1; - } - - // ----------------------------------------------------------------------- - /** - * Creates a tokenizer that can tokenize the contents of this builder. - *

- * This method allows the contents of this builder to be tokenized. The - * tokenizer will be setup by default to tokenize on space, tab, newline and - * formfeed (as per StringTokenizer). These values can be changed on the - * tokenizer class, before retrieving the tokens. - *

- * The returned tokenizer is linked to this builder. You may intermix calls to - * the builder and tokenizer within certain limits, however there is no - * synchronization. Once the tokenizer has been used once, it must be - * {@link StrTokenizer#reset() reset} to pickup the latest changes in the - * builder. For example: - * - *

-	 * StrBuilder b = new StrBuilder();
-	 * b.append("a b ");
-	 * StrTokenizer t = b.asTokenizer();
-	 * String[] tokens1 = t.getTokenArray(); // returns a,b
-	 * b.append("c d ");
-	 * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
-	 * t.reset(); // reset causes builder changes to be picked up
-	 * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
-	 * 
- * - * In addition to simply intermixing appends and tokenization, you can also call - * the set methods on the tokenizer to alter how it tokenizes. Just remember to - * call reset when you want to pickup builder changes. - *

- * Calling {@link StrTokenizer#reset(String)} or - * {@link StrTokenizer#reset(char[])} with a non-null value will break the link - * with the builder. - * - * @return a tokenizer that is linked to this builder - */ - public StrTokenizer asTokenizer() { - return new StrBuilderTokenizer(); - } - - // ----------------------------------------------------------------------- - /** - * Gets the contents of this builder as a Reader. - *

- * This method allows the contents of the builder to be read using any standard - * method that expects a Reader. - *

- * To use, simply create a {@code StrBuilder}, populate it with data, call - * {@code asReader}, and then read away. - *

- * The internal character array is shared between the builder and the reader. - * This allows you to append to the builder after creating the reader, and the - * changes will be picked up. Note however, that no synchronization occurs, so - * you must perform all operations with the builder and the reader in one - * thread. - *

- * The returned reader supports marking, and ignores the flush method. - * - * @return a reader that reads from this builder - */ - public Reader asReader() { - return new StrBuilderReader(); - } - - // ----------------------------------------------------------------------- - /** - * Gets this builder as a Writer that can be written to. - *

- * This method allows you to populate the contents of the builder using any - * standard method that takes a Writer. - *

- * To use, simply create a {@code StrBuilder}, call {@code asWriter}, and - * populate away. The data is available at any time using the methods of the - * {@code StrBuilder}. - *

- * The internal character array is shared between the builder and the writer. - * This allows you to intermix calls that append to the builder and write using - * the writer and the changes will be occur correctly. Note however, that no - * synchronization occurs, so you must perform all operations with the builder - * and the writer in one thread. - *

- * The returned writer ignores the close and flush methods. - * - * @return a writer that populates this builder - */ - public Writer asWriter() { - return new StrBuilderWriter(); - } - - /** - * Appends current contents of this {@code StrBuilder} to the provided - * {@link Appendable}. - *

- * This method tries to avoid doing any extra copies of contents. - * - * @param appendable the appendable to append data to - * @throws IOException if an I/O error occurs - * - * @since 3.4 - * @see #readFrom(Readable) - */ - public void appendTo(final Appendable appendable) throws IOException { - if (appendable instanceof Writer) { - ((Writer) appendable).write(buffer, 0, size); - } else if (appendable instanceof StringBuilder) { - ((StringBuilder) appendable).append(buffer, 0, size); - } else if (appendable instanceof StringBuffer) { - ((StringBuffer) appendable).append(buffer, 0, size); - } else if (appendable instanceof CharBuffer) { - ((CharBuffer) appendable).put(buffer, 0, size); - } else { - appendable.append(this); - } - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content ignoring case. - * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - public boolean equalsIgnoreCase(final StrBuilder other) { - if (this == other) { - return true; - } - if (this.size != other.size) { - return false; - } - final char[] thisBuf = this.buffer; - final char[] otherBuf = other.buffer; - for (int i = size - 1; i >= 0; i--) { - final char c1 = thisBuf[i]; - final char c2 = otherBuf[i]; - if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) { - return false; - } - } - return true; - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content. - * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - public boolean equals(final StrBuilder other) { - if (this == other) { - return true; - } - if (other == null) { - return false; - } - if (this.size != other.size) { - return false; - } - final char[] thisBuf = this.buffer; - final char[] otherBuf = other.buffer; - for (int i = size - 1; i >= 0; i--) { - if (thisBuf[i] != otherBuf[i]) { - return false; - } - } - return true; - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content. - * - * @param obj the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - @Override - public boolean equals(final Object obj) { - return obj instanceof StrBuilder && equals((StrBuilder) obj); - } - - /** - * Gets a suitable hash code for this builder. - * - * @return a hash code - */ - @Override - public int hashCode() { - final char[] buf = buffer; - int hash = 0; - for (int i = size - 1; i >= 0; i--) { - hash = 31 * hash + buf[i]; - } - return hash; - } - - // ----------------------------------------------------------------------- - /** - * Gets a String version of the string builder, creating a new instance each - * time the method is called. - *

- * Note that unlike StringBuffer, the string version returned is independent of - * the string builder. - * - * @return the builder as a String - */ - @Override - public String toString() { - return new String(buffer, 0, size); - } - - /** - * Gets a StringBuffer version of the string builder, creating a new instance - * each time the method is called. - * - * @return the builder as a StringBuffer - */ - public StringBuffer toStringBuffer() { - return new StringBuffer(size).append(buffer, 0, size); - } - - /** - * Gets a StringBuilder version of the string builder, creating a new instance - * each time the method is called. - * - * @return the builder as a StringBuilder - * @since 3.2 - */ - public StringBuilder toStringBuilder() { - return new StringBuilder(size).append(buffer, 0, size); - } - - /** - * Implement the {@link Builder} interface. - * - * @return the builder as a String - * @since 3.2 - * @see #toString() - */ - @Override - public String build() { - return toString(); - } - - // ----------------------------------------------------------------------- - /** - * Validates parameters defining a range of the builder. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - protected int validateRange(final int startIndex, int endIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex > size) { - endIndex = size; - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException("end < start"); - } - return endIndex; - } - - /** - * Validates parameters defining a single index in the builder. - * - * @param index the index, must be valid - * @throws IndexOutOfBoundsException if the index is invalid - */ - protected void validateIndex(final int index) { - if (index < 0 || index > size) { - throw new StringIndexOutOfBoundsException(index); - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a tokenizer. - */ - class StrBuilderTokenizer extends StrTokenizer { - - /** - * Default constructor. - */ - StrBuilderTokenizer() { - } - - /** {@inheritDoc} */ - @Override - protected List tokenize(final char[] chars, final int offset, final int count) { - if (chars == null) { - return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size()); - } - return super.tokenize(chars, offset, count); - } - - /** {@inheritDoc} */ - @Override - public String getContent() { - final String str = super.getContent(); - if (str == null) { - return StrBuilder.this.toString(); - } - return str; - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a reader. - */ - class StrBuilderReader extends Reader { - /** The current stream position. */ - private int pos; - /** The last mark position. */ - private int mark; - - /** - * Default constructor. - */ - StrBuilderReader() { - } - - /** {@inheritDoc} */ - @Override - public void close() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public int read() { - if (ready() == false) { - return -1; - } - return StrBuilder.this.charAt(pos++); - } - - /** {@inheritDoc} */ - @Override - public int read(final char[] b, final int off, int len) { - if (off < 0 || len < 0 || off > b.length || (off + len) > b.length || (off + len) < 0) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return 0; - } - if (pos >= StrBuilder.this.size()) { - return -1; - } - if (pos + len > size()) { - len = StrBuilder.this.size() - pos; - } - StrBuilder.this.getChars(pos, pos + len, b, off); - pos += len; - return len; - } - - /** {@inheritDoc} */ - @Override - public long skip(long n) { - if (pos + n > StrBuilder.this.size()) { - n = StrBuilder.this.size() - pos; - } - if (n < 0) { - return 0; - } - pos += n; - return n; - } - - /** {@inheritDoc} */ - @Override - public boolean ready() { - return pos < StrBuilder.this.size(); - } - - /** {@inheritDoc} */ - @Override - public boolean markSupported() { - return true; - } - - /** {@inheritDoc} */ - @Override - public void mark(final int readAheadLimit) { - mark = pos; - } - - /** {@inheritDoc} */ - @Override - public void reset() { - pos = mark; - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a writer. - */ - class StrBuilderWriter extends Writer { - - /** - * Default constructor. - */ - StrBuilderWriter() { - } - - /** {@inheritDoc} */ - @Override - public void close() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public void flush() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public void write(final int c) { - StrBuilder.this.append((char) c); - } - - /** {@inheritDoc} */ - @Override - public void write(final char[] cbuf) { - StrBuilder.this.append(cbuf); - } - - /** {@inheritDoc} */ - @Override - public void write(final char[] cbuf, final int off, final int len) { - StrBuilder.this.append(cbuf, off, len); - } - - /** {@inheritDoc} */ - @Override - public void write(final String str) { - StrBuilder.this.append(str); - } - - /** {@inheritDoc} */ - @Override - public void write(final String str, final int off, final int len) { - StrBuilder.this.append(str, off, len); - } - } - -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrMatcher.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrMatcher.java deleted file mode 100644 index 345c2b24..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrMatcher.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.repackage.lang3; - -import java.util.Arrays; - -import org.apache.commons.lang3.ArraySorter; -import org.apache.commons.lang3.StringUtils; - -/** - * A matcher class that can be queried to determine if a character array portion - * matches. - *

- * This class comes complete with various factory methods. If these do not - * suffice, you can subclass and implement your own matcher. - * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * StringMatcherFactory instead - */ -//@Deprecated -public abstract class StrMatcher { - - /** - * Matches the comma character. - */ - private static final StrMatcher COMMA_MATCHER = new CharMatcher(','); - /** - * Matches the tab character. - */ - private static final StrMatcher TAB_MATCHER = new CharMatcher('\t'); - /** - * Matches the space character. - */ - private static final StrMatcher SPACE_MATCHER = new CharMatcher(' '); - /** - * Matches the same characters as StringTokenizer, namely space, tab, newline, - * formfeed. - */ - private static final StrMatcher SPLIT_MATCHER = new CharSetMatcher(" \t\n\r\f".toCharArray()); - /** - * Matches the String trim() whitespace characters. - */ - private static final StrMatcher TRIM_MATCHER = new TrimMatcher(); - /** - * Matches the double quote character. - */ - private static final StrMatcher SINGLE_QUOTE_MATCHER = new CharMatcher('\''); - /** - * Matches the double quote character. - */ - private static final StrMatcher DOUBLE_QUOTE_MATCHER = new CharMatcher('"'); - /** - * Matches the single or double quote character. - */ - private static final StrMatcher QUOTE_MATCHER = new CharSetMatcher("'\"".toCharArray()); - /** - * Matches no characters. - */ - private static final StrMatcher NONE_MATCHER = new NoMatcher(); - - // ----------------------------------------------------------------------- - - /** - * Returns a matcher which matches the comma character. - * - * @return a matcher for a comma - */ - public static StrMatcher commaMatcher() { - return COMMA_MATCHER; - } - - /** - * Returns a matcher which matches the tab character. - * - * @return a matcher for a tab - */ - public static StrMatcher tabMatcher() { - return TAB_MATCHER; - } - - /** - * Returns a matcher which matches the space character. - * - * @return a matcher for a space - */ - public static StrMatcher spaceMatcher() { - return SPACE_MATCHER; - } - - /** - * Matches the same characters as StringTokenizer, namely space, tab, newline - * and formfeed. - * - * @return the split matcher - */ - public static StrMatcher splitMatcher() { - return SPLIT_MATCHER; - } - - /** - * Matches the String trim() whitespace characters. - * - * @return the trim matcher - */ - public static StrMatcher trimMatcher() { - return TRIM_MATCHER; - } - - /** - * Returns a matcher which matches the single quote character. - * - * @return a matcher for a single quote - */ - public static StrMatcher singleQuoteMatcher() { - return SINGLE_QUOTE_MATCHER; - } - - /** - * Returns a matcher which matches the double quote character. - * - * @return a matcher for a double quote - */ - public static StrMatcher doubleQuoteMatcher() { - return DOUBLE_QUOTE_MATCHER; - } - - /** - * Returns a matcher which matches the single or double quote character. - * - * @return a matcher for a single or double quote - */ - public static StrMatcher quoteMatcher() { - return QUOTE_MATCHER; - } - - /** - * Matches no characters. - * - * @return a matcher that matches nothing - */ - public static StrMatcher noneMatcher() { - return NONE_MATCHER; - } - - /** - * Constructor that creates a matcher from a character. - * - * @param ch the character to match, must not be null - * @return a new Matcher for the given char - */ - public static StrMatcher charMatcher(final char ch) { - return new CharMatcher(ch); - } - - /** - * Constructor that creates a matcher from a set of characters. - * - * @param chars the characters to match, null or empty matches nothing - * @return a new matcher for the given char[] - */ - public static StrMatcher charSetMatcher(final char... chars) { - if (chars == null || chars.length == 0) { - return NONE_MATCHER; - } - if (chars.length == 1) { - return new CharMatcher(chars[0]); - } - return new CharSetMatcher(chars); - } - - /** - * Constructor that creates a matcher from a string representing a set of - * characters. - * - * @param chars the characters to match, null or empty matches nothing - * @return a new Matcher for the given characters - */ - public static StrMatcher charSetMatcher(final String chars) { - if (StringUtils.isEmpty(chars)) { - return NONE_MATCHER; - } - if (chars.length() == 1) { - return new CharMatcher(chars.charAt(0)); - } - return new CharSetMatcher(chars.toCharArray()); - } - - /** - * Constructor that creates a matcher from a string. - * - * @param str the string to match, null or empty matches nothing - * @return a new Matcher for the given String - */ - public static StrMatcher stringMatcher(final String str) { - if (StringUtils.isEmpty(str)) { - return NONE_MATCHER; - } - return new StringMatcher(str); - } - - // ----------------------------------------------------------------------- - /** - * Constructor. - */ - protected StrMatcher() { - } - - /** - * Returns the number of matching characters, zero for no match. - *

- * This method is called to check for a match. The parameter {@code pos} - * represents the current position to be checked in the string {@code buffer} (a - * character array which must not be changed). The API guarantees that - * {@code pos} is a valid index for {@code buffer}. - *

- * The character array may be larger than the active area to be matched. Only - * values in the buffer between the specified indices may be accessed. - *

- * The matching code may check one character or many. It may check characters - * preceding {@code pos} as well as those after, so long as no checks exceed the - * bounds specified. - *

- * It must return zero for no match, or a positive number if a match was found. - * The number indicates the number of characters that matched. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index (exclusive) of the active buffer, valid for - * buffer - * @return the number of matching characters, zero for no match - */ - public abstract int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd); - - /** - * Returns the number of matching characters, zero for no match. - *

- * This method is called to check for a match. The parameter {@code pos} - * represents the current position to be checked in the string {@code buffer} (a - * character array which must not be changed). The API guarantees that - * {@code pos} is a valid index for {@code buffer}. - *

- * The matching code may check one character or many. It may check characters - * preceding {@code pos} as well as those after. - *

- * It must return zero for no match, or a positive number if a match was found. - * The number indicates the number of characters that matched. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @return the number of matching characters, zero for no match - * @since 2.4 - */ - public int isMatch(final char[] buffer, final int pos) { - return isMatch(buffer, pos, 0, buffer.length); - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a set of characters for matching purposes. - */ - static final class CharSetMatcher extends StrMatcher { - /** The set of characters to match. */ - private final char[] chars; - - /** - * Constructor that creates a matcher from a character array. - * - * @param chars the characters to match, must not be null - */ - CharSetMatcher(final char[] chars) { - this.chars = ArraySorter.sort(chars.clone()); - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return Arrays.binarySearch(chars, buffer[pos]) >= 0 ? 1 : 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a character for matching purposes. - */ - static final class CharMatcher extends StrMatcher { - /** The character to match. */ - private final char ch; - - /** - * Constructor that creates a matcher that matches a single character. - * - * @param ch the character to match - */ - CharMatcher(final char ch) { - this.ch = ch; - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return ch == buffer[pos] ? 1 : 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a set of characters for matching purposes. - */ - static final class StringMatcher extends StrMatcher { - /** The string to match, as a character array. */ - private final char[] chars; - - /** - * Constructor that creates a matcher from a String. - * - * @param str the string to match, must not be null - */ - StringMatcher(final String str) { - chars = str.toCharArray(); - } - - /** - * Returns whether or not the given text matches the stored string. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, int pos, final int bufferStart, final int bufferEnd) { - final int len = chars.length; - if (pos + len > bufferEnd) { - return 0; - } - for (int i = 0; i < chars.length; i++, pos++) { - if (chars[i] != buffer[pos]) { - return 0; - } - } - return len; - } - - @Override - public String toString() { - return super.toString() + ' ' + Arrays.toString(chars); - } - - } - - // ----------------------------------------------------------------------- - /** - * Class used to match no characters. - */ - static final class NoMatcher extends StrMatcher { - - /** - * Constructs a new instance of {@code NoMatcher}. - */ - NoMatcher() { - } - - /** - * Always returns {@code false}. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to match whitespace as per trim(). - */ - static final class TrimMatcher extends StrMatcher { - - /** - * Constructs a new instance of {@code TrimMatcher}. - */ - TrimMatcher() { - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return buffer[pos] <= 32 ? 1 : 0; - } - } - -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrTokenizer.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrTokenizer.java deleted file mode 100644 index 66e57050..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/repackage/lang3/StrTokenizer.java +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.repackage.lang3; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; -import java.util.NoSuchElementException; - -import org.apache.commons.lang3.StringUtils; - -/** - * Tokenizes a string based on delimiters (separators) and supporting quoting - * and ignored character concepts. - *

- * This class can split a String into many smaller strings. It aims to do a - * similar job to {@link java.util.StringTokenizer StringTokenizer}, however it - * offers much more control and flexibility including implementing the - * {@code ListIterator} interface. By default, it is set up like - * {@code StringTokenizer}. - *

- * The input String is split into a number of tokens. Each token is - * separated from the next String by a delimiter. One or more delimiter - * characters must be specified. - *

- * Each token may be surrounded by quotes. The quote matcher specifies - * the quote character(s). A quote may be escaped within a quoted section by - * duplicating itself. - *

- * Between each token and the delimiter are potentially characters that need - * trimming. The trimmer matcher specifies these characters. One usage - * might be to trim whitespace characters. - *

- * At any point outside the quotes there might potentially be invalid - * characters. The ignored matcher specifies these characters to be - * removed. One usage might be to remove new line characters. - *

- * Empty tokens may be removed or returned as null. - * - *

- * "a,b,c"         - Three tokens "a","b","c"   (comma delimiter)
- * " a, b , c "    - Three tokens "a","b","c"   (default CSV processing trims whitespace)
- * "a, ", b ,", c" - Three tokens "a, " , " b ", ", c" (quoted text untouched)
- * 
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
StrTokenizer properties and options
PropertyTypeDefault
delimCharSetMatcher{ \t\n\r\f}
quoteNoneMatcher{}
ignoreNoneMatcher{}
emptyTokenAsNullbooleanfalse
ignoreEmptyTokensbooleantrue
- * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * StringTokenizer instead - */ -//@Deprecated -public class StrTokenizer implements ListIterator, Cloneable { - - private static final StrTokenizer CSV_TOKENIZER_PROTOTYPE; - private static final StrTokenizer TSV_TOKENIZER_PROTOTYPE; - static { - CSV_TOKENIZER_PROTOTYPE = new StrTokenizer(); - CSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.commaMatcher()); - CSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher()); - CSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher()); - CSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher()); - CSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false); - CSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false); - - TSV_TOKENIZER_PROTOTYPE = new StrTokenizer(); - TSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.tabMatcher()); - TSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher()); - TSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher()); - TSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher()); - TSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false); - TSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false); - } - - /** The text to work on. */ - private char[] chars; - /** The parsed tokens */ - private String[] tokens; - /** The current iteration position */ - private int tokenPos; - - /** The delimiter matcher */ - private StrMatcher delimMatcher = StrMatcher.splitMatcher(); - /** The quote matcher */ - private StrMatcher quoteMatcher = StrMatcher.noneMatcher(); - /** The ignored matcher */ - private StrMatcher ignoredMatcher = StrMatcher.noneMatcher(); - /** The trimmer matcher */ - private StrMatcher trimmerMatcher = StrMatcher.noneMatcher(); - - /** Whether to return empty tokens as null */ - private boolean emptyAsNull; - /** Whether to ignore empty tokens */ - private boolean ignoreEmptyTokens = true; - - // ----------------------------------------------------------------------- - - /** - * Returns a clone of {@code CSV_TOKENIZER_PROTOTYPE}. - * - * @return a clone of {@code CSV_TOKENIZER_PROTOTYPE}. - */ - private static StrTokenizer getCSVClone() { - return (StrTokenizer) CSV_TOKENIZER_PROTOTYPE.clone(); - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - *

- * You must call a "reset" method to set the string which you want to parse. - * - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance() { - return getCSVClone(); - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance(final String input) { - final StrTokenizer tok = getCSVClone(); - tok.reset(input); - return tok; - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance(final char[] input) { - final StrTokenizer tok = getCSVClone(); - tok.reset(input); - return tok; - } - - /** - * Returns a clone of {@code TSV_TOKENIZER_PROTOTYPE}. - * - * @return a clone of {@code TSV_TOKENIZER_PROTOTYPE}. - */ - private static StrTokenizer getTSVClone() { - return (StrTokenizer) TSV_TOKENIZER_PROTOTYPE.clone(); - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - *

- * You must call a "reset" method to set the string which you want to parse. - * - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance() { - return getTSVClone(); - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - * - * @param input the string to parse - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance(final String input) { - final StrTokenizer tok = getTSVClone(); - tok.reset(input); - return tok; - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - * - * @param input the string to parse - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance(final char[] input) { - final StrTokenizer tok = getTSVClone(); - tok.reset(input); - return tok; - } - - // ----------------------------------------------------------------------- - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer, but with no text to tokenize. - *

- * This constructor is normally used with {@link #reset(String)}. - */ - public StrTokenizer() { - this.chars = null; - } - - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer. - * - * @param input the string which is to be parsed - */ - public StrTokenizer(final String input) { - if (input != null) { - chars = input.toCharArray(); - } else { - chars = null; - } - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character. - * - * @param input the string which is to be parsed - * @param delim the field delimiter character - */ - public StrTokenizer(final String input, final char delim) { - this(input); - setDelimiterChar(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter string. - * - * @param input the string which is to be parsed - * @param delim the field delimiter string - */ - public StrTokenizer(final String input, final String delim) { - this(input); - setDelimiterString(delim); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher. - * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher - */ - public StrTokenizer(final String input, final StrMatcher delim) { - this(input); - setDelimiterMatcher(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character and - * handling quotes using the specified quote character. - * - * @param input the string which is to be parsed - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final String input, final char delim, final char quote) { - this(input, delim); - setQuoteChar(quote); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher and - * handling quotes using the specified quote matcher. - * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher - * @param quote the field quoted string matcher - */ - public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher quote) { - this(input, delim); - setQuoteMatcher(quote); - } - - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer. - * - * @param input the string which is to be parsed, not cloned - */ - public StrTokenizer(final char[] input) { - this.chars = new String(input).toCharArray(); - } - - /** - * Constructs a tokenizer splitting on the specified character. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - */ - public StrTokenizer(final char[] input, final char delim) { - this(input); - setDelimiterChar(delim); - } - - /** - * Constructs a tokenizer splitting on the specified string. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter string - */ - public StrTokenizer(final char[] input, final String delim) { - this(input); - setDelimiterString(delim); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter matcher - */ - public StrTokenizer(final char[] input, final StrMatcher delim) { - this(input); - setDelimiterMatcher(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character and - * handling quotes using the specified quote character. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final char[] input, final char delim, final char quote) { - this(input, delim); - setQuoteChar(quote); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher and - * handling quotes using the specified quote matcher. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final char[] input, final StrMatcher delim, final StrMatcher quote) { - this(input, delim); - setQuoteMatcher(quote); - } - - // API - // ----------------------------------------------------------------------- - /** - * Gets the number of tokens found in the String. - * - * @return the number of matched tokens - */ - public int size() { - checkTokenized(); - return tokens.length; - } - - /** - * Gets the next token from the String. Equivalent to {@link #next()} except it - * returns null rather than throwing {@link NoSuchElementException} when no - * tokens remain. - * - * @return the next sequential token, or null when no more tokens are found - */ - public String nextToken() { - if (hasNext()) { - return tokens[tokenPos++]; - } - return null; - } - - /** - * Gets the previous token from the String. - * - * @return the previous sequential token, or null when no more tokens are found - */ - public String previousToken() { - if (hasPrevious()) { - return tokens[--tokenPos]; - } - return null; - } - - /** - * Gets a copy of the full token list as an independent modifiable array. - * - * @return the tokens as a String array - */ - public String[] getTokenArray() { - checkTokenized(); - return tokens.clone(); - } - - /** - * Gets a copy of the full token list as an independent modifiable list. - * - * @return the tokens as a String array - */ - public List getTokenList() { - checkTokenized(); - final List list = new ArrayList<>(tokens.length); - list.addAll(Arrays.asList(tokens)); - return list; - } - - /** - * Resets this tokenizer, forgetting all parsing and iteration already - * completed. - *

- * This method allows the same tokenizer to be reused for the same String. - * - * @return this, to enable chaining - */ - public StrTokenizer reset() { - tokenPos = 0; - tokens = null; - return this; - } - - /** - * Reset this tokenizer, giving it a new input string to parse. In this manner - * you can re-use a tokenizer with the same settings on multiple input lines. - * - * @param input the new string to tokenize, null sets no text to parse - * @return this, to enable chaining - */ - public StrTokenizer reset(final String input) { - reset(); - if (input != null) { - this.chars = input.toCharArray(); - } else { - this.chars = null; - } - return this; - } - - /** - * Reset this tokenizer, giving it a new input string to parse. In this manner - * you can re-use a tokenizer with the same settings on multiple input lines. - * - * @param input the new character array to tokenize, not cloned, null sets no - * text to parse - * @return this, to enable chaining - */ - public StrTokenizer reset(final char[] input) { - reset(); - this.chars = new String(input).toCharArray(); - return this; - } - - // ListIterator - // ----------------------------------------------------------------------- - /** - * Checks whether there are any more tokens. - * - * @return true if there are more tokens - */ - @Override - public boolean hasNext() { - checkTokenized(); - return tokenPos < tokens.length; - } - - /** - * Gets the next token. - * - * @return the next String token - * @throws NoSuchElementException if there are no more elements - */ - @Override - public String next() { - if (hasNext()) { - return tokens[tokenPos++]; - } - throw new NoSuchElementException(); - } - - /** - * Gets the index of the next token to return. - * - * @return the next token index - */ - @Override - public int nextIndex() { - return tokenPos; - } - - /** - * Checks whether there are any previous tokens that can be iterated to. - * - * @return true if there are previous tokens - */ - @Override - public boolean hasPrevious() { - checkTokenized(); - return tokenPos > 0; - } - - /** - * Gets the token previous to the last returned token. - * - * @return the previous token - */ - @Override - public String previous() { - if (hasPrevious()) { - return tokens[--tokenPos]; - } - throw new NoSuchElementException(); - } - - /** - * Gets the index of the previous token. - * - * @return the previous token index - */ - @Override - public int previousIndex() { - return tokenPos - 1; - } - - /** - * Unsupported ListIterator operation. - * - * @throws UnsupportedOperationException always - */ - @Override - public void remove() { - throw new UnsupportedOperationException("remove() is unsupported"); - } - - /** - * Unsupported ListIterator operation. - * - * @param obj this parameter ignored. - * @throws UnsupportedOperationException always - */ - @Override - public void set(final String obj) { - throw new UnsupportedOperationException("set() is unsupported"); - } - - /** - * Unsupported ListIterator operation. - * - * @param obj this parameter ignored. - * @throws UnsupportedOperationException always - */ - @Override - public void add(final String obj) { - throw new UnsupportedOperationException("add() is unsupported"); - } - - // Implementation - // ----------------------------------------------------------------------- - /** - * Checks if tokenization has been done, and if not then do it. - */ - private void checkTokenized() { - if (tokens == null) { - if (chars == null) { - // still call tokenize as subclass may do some work - final List split = tokenize(null, 0, 0); - tokens = split.toArray(new String[0]); - } else { - final List split = tokenize(chars, 0, chars.length); - tokens = split.toArray(new String[0]); - } - } - } - - /** - * Internal method to performs the tokenization. - *

- * Most users of this class do not need to call this method. This method will be - * called automatically by other (public) methods when required. - *

- * This method exists to allow subclasses to add code before or after the - * tokenization. For example, a subclass could alter the character array, offset - * or count to be parsed, or call the tokenizer multiple times on multiple - * strings. It is also be possible to filter the results. - *

- * {@code StrTokenizer} will always pass a zero offset and a count equal to the - * length of the array to this method, however a subclass may pass other values, - * or even an entirely different array. - * - * @param srcChars the character array being tokenized, may be null - * @param offset the start position within the character array, must be valid - * @param count the number of characters to tokenize, must be valid - * @return the modifiable list of String tokens, unmodifiable if null array or - * zero count - */ - protected List tokenize(final char[] srcChars, final int offset, final int count) { - if (srcChars == null || count == 0) { - return Collections.emptyList(); - } - final StrBuilder buf = new StrBuilder(); - final List tokenList = new ArrayList<>(); - int pos = offset; - - // loop around the entire buffer - while (pos >= 0 && pos < count) { - // find next token - pos = readNextToken(srcChars, pos, count, buf, tokenList); - - // handle case where end of string is a delimiter - if (pos >= count) { - addToken(tokenList, StringUtils.EMPTY); - } - } - return tokenList; - } - - /** - * Adds a token to a list, paying attention to the parameters we've set. - * - * @param list the list to add to - * @param tok the token to add - */ - private void addToken(final List list, String tok) { - if (StringUtils.isEmpty(tok)) { - if (isIgnoreEmptyTokens()) { - return; - } - if (isEmptyTokenAsNull()) { - tok = null; - } - } - list.add(tok); - } - - /** - * Reads character by character through the String to get the next token. - * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @return the starting position of the next field (the character immediately - * after the delimiter), or -1 if end of string found - */ - private int readNextToken(final char[] srcChars, int start, final int len, final StrBuilder workArea, - final List tokenList) { - // skip all leading whitespace, unless it is the - // field delimiter or the quote character - while (start < len) { - final int removeLen = Math.max(getIgnoredMatcher().isMatch(srcChars, start, start, len), - getTrimmerMatcher().isMatch(srcChars, start, start, len)); - if (removeLen == 0 || getDelimiterMatcher().isMatch(srcChars, start, start, len) > 0 - || getQuoteMatcher().isMatch(srcChars, start, start, len) > 0) { - break; - } - start += removeLen; - } - - // handle reaching end - if (start >= len) { - addToken(tokenList, StringUtils.EMPTY); - return -1; - } - - // handle empty token - final int delimLen = getDelimiterMatcher().isMatch(srcChars, start, start, len); - if (delimLen > 0) { - addToken(tokenList, StringUtils.EMPTY); - return start + delimLen; - } - - // handle found token - final int quoteLen = getQuoteMatcher().isMatch(srcChars, start, start, len); - if (quoteLen > 0) { - return readWithQuotes(srcChars, start + quoteLen, len, workArea, tokenList, start, quoteLen); - } - return readWithQuotes(srcChars, start, len, workArea, tokenList, 0, 0); - } - - /** - * Reads a possibly quoted string token. - * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return the starting position of the next field (the character immediately - * after the delimiter, or if end of string found, then the length of - * string - */ - private int readWithQuotes(final char[] srcChars, final int start, final int len, final StrBuilder workArea, - final List tokenList, final int quoteStart, final int quoteLen) { - // Loop until we've found the end of the quoted - // string or the end of the input - workArea.clear(); - int pos = start; - boolean quoting = quoteLen > 0; - int trimStart = 0; - - while (pos < len) { - // quoting mode can occur several times throughout a string - // we must switch between quoting and non-quoting until we - // encounter a non-quoted delimiter, or end of string - if (quoting) { - // In quoting mode - - // If we've found a quote character, see if it's - // followed by a second quote. If so, then we need - // to actually put the quote character into the token - // rather than end the token. - if (isQuote(srcChars, pos, len, quoteStart, quoteLen)) { - if (isQuote(srcChars, pos + quoteLen, len, quoteStart, quoteLen)) { - // matched pair of quotes, thus an escaped quote - workArea.append(srcChars, pos, quoteLen); - pos += quoteLen * 2; - trimStart = workArea.size(); - continue; - } - - // end of quoting - quoting = false; - pos += quoteLen; - continue; - } - - // copy regular character from inside quotes - workArea.append(srcChars[pos++]); - trimStart = workArea.size(); - - } else { - // Not in quoting mode - - // check for delimiter, and thus end of token - final int delimLen = getDelimiterMatcher().isMatch(srcChars, pos, start, len); - if (delimLen > 0) { - // return condition when end of token found - addToken(tokenList, workArea.substring(0, trimStart)); - return pos + delimLen; - } - - // check for quote, and thus back into quoting mode - if (quoteLen > 0 && isQuote(srcChars, pos, len, quoteStart, quoteLen)) { - quoting = true; - pos += quoteLen; - continue; - } - - // check for ignored (outside quotes), and ignore - final int ignoredLen = getIgnoredMatcher().isMatch(srcChars, pos, start, len); - if (ignoredLen > 0) { - pos += ignoredLen; - continue; - } - - // check for trimmed character - // don't yet know if its at the end, so copy to workArea - // use trimStart to keep track of trim at the end - final int trimmedLen = getTrimmerMatcher().isMatch(srcChars, pos, start, len); - if (trimmedLen > 0) { - workArea.append(srcChars, pos, trimmedLen); - pos += trimmedLen; - continue; - } - - // copy regular character from outside quotes - workArea.append(srcChars[pos++]); - trimStart = workArea.size(); - } - } - - // return condition when end of string found - addToken(tokenList, workArea.substring(0, trimStart)); - return -1; - } - - /** - * Checks if the characters at the index specified match the quote already - * matched in readNextToken(). - * - * @param srcChars the character array being tokenized - * @param pos the position to check for a quote - * @param len the length of the character array being tokenized - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return true if a quote is matched - */ - private boolean isQuote(final char[] srcChars, final int pos, final int len, final int quoteStart, - final int quoteLen) { - for (int i = 0; i < quoteLen; i++) { - if (pos + i >= len || srcChars[pos + i] != srcChars[quoteStart + i]) { - return false; - } - } - return true; - } - - // Delimiter - // ----------------------------------------------------------------------- - /** - * Gets the field delimiter matcher. - * - * @return the delimiter matcher in use - */ - public StrMatcher getDelimiterMatcher() { - return this.delimMatcher; - } - - /** - * Sets the field delimiter matcher. - *

- * The delimiter is used to separate one token from another. - * - * @param delim the delimiter matcher to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterMatcher(final StrMatcher delim) { - if (delim == null) { - this.delimMatcher = StrMatcher.noneMatcher(); - } else { - this.delimMatcher = delim; - } - return this; - } - - /** - * Sets the field delimiter character. - * - * @param delim the delimiter character to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterChar(final char delim) { - return setDelimiterMatcher(StrMatcher.charMatcher(delim)); - } - - /** - * Sets the field delimiter string. - * - * @param delim the delimiter string to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterString(final String delim) { - return setDelimiterMatcher(StrMatcher.stringMatcher(delim)); - } - - // Quote - // ----------------------------------------------------------------------- - /** - * Gets the quote matcher currently in use. - *

- * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. The default value is '"' (double quote). - * - * @return the quote matcher in use - */ - public StrMatcher getQuoteMatcher() { - return quoteMatcher; - } - - /** - * Set the quote matcher to use. - *

- * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. - * - * @param quote the quote matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setQuoteMatcher(final StrMatcher quote) { - if (quote != null) { - this.quoteMatcher = quote; - } - return this; - } - - /** - * Sets the quote character to use. - *

- * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. - * - * @param quote the quote character to use - * @return this, to enable chaining - */ - public StrTokenizer setQuoteChar(final char quote) { - return setQuoteMatcher(StrMatcher.charMatcher(quote)); - } - - // Ignored - // ----------------------------------------------------------------------- - /** - * Gets the ignored character matcher. - *

- * These characters are ignored when parsing the String, unless they are within - * a quoted region. The default value is not to ignore anything. - * - * @return the ignored matcher in use - */ - public StrMatcher getIgnoredMatcher() { - return ignoredMatcher; - } - - /** - * Set the matcher for characters to ignore. - *

- * These characters are ignored when parsing the String, unless they are within - * a quoted region. - * - * @param ignored the ignored matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setIgnoredMatcher(final StrMatcher ignored) { - if (ignored != null) { - this.ignoredMatcher = ignored; - } - return this; - } - - /** - * Set the character to ignore. - *

- * This character is ignored when parsing the String, unless it is within a - * quoted region. - * - * @param ignored the ignored character to use - * @return this, to enable chaining - */ - public StrTokenizer setIgnoredChar(final char ignored) { - return setIgnoredMatcher(StrMatcher.charMatcher(ignored)); - } - - // Trimmer - // ----------------------------------------------------------------------- - /** - * Gets the trimmer character matcher. - *

- * These characters are trimmed off on each side of the delimiter until the - * token or quote is found. The default value is not to trim anything. - * - * @return the trimmer matcher in use - */ - public StrMatcher getTrimmerMatcher() { - return trimmerMatcher; - } - - /** - * Sets the matcher for characters to trim. - *

- * These characters are trimmed off on each side of the delimiter until the - * token or quote is found. - * - * @param trimmer the trimmer matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setTrimmerMatcher(final StrMatcher trimmer) { - if (trimmer != null) { - this.trimmerMatcher = trimmer; - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets whether the tokenizer currently returns empty tokens as null. The - * default for this property is false. - * - * @return true if empty tokens are returned as null - */ - public boolean isEmptyTokenAsNull() { - return this.emptyAsNull; - } - - /** - * Sets whether the tokenizer should return empty tokens as null. The default - * for this property is false. - * - * @param emptyAsNull whether empty tokens are returned as null - * @return this, to enable chaining - */ - public StrTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { - this.emptyAsNull = emptyAsNull; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets whether the tokenizer currently ignores empty tokens. The default for - * this property is true. - * - * @return true if empty tokens are not returned - */ - public boolean isIgnoreEmptyTokens() { - return ignoreEmptyTokens; - } - - /** - * Sets whether the tokenizer should ignore and not return empty tokens. The - * default for this property is true. - * - * @param ignoreEmptyTokens whether empty tokens are not returned - * @return this, to enable chaining - */ - public StrTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { - this.ignoreEmptyTokens = ignoreEmptyTokens; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the String content that the tokenizer is parsing. - * - * @return the string content being parsed - */ - public String getContent() { - if (chars == null) { - return null; - } - return new String(chars); - } - - // ----------------------------------------------------------------------- - /** - * Creates a new instance of this Tokenizer. The new instance is reset so that - * it will be at the start of the token list. If a - * {@link CloneNotSupportedException} is caught, return {@code null}. - * - * @return a new instance of this Tokenizer which has been reset. - */ - @Override - public Object clone() { - try { - return cloneReset(); - } catch (final CloneNotSupportedException ex) { - return null; - } - } - - /** - * Creates a new instance of this Tokenizer. The new instance is reset so that - * it will be at the start of the token list. - * - * @return a new instance of this Tokenizer which has been reset. - * @throws CloneNotSupportedException if there is a problem cloning - */ - Object cloneReset() throws CloneNotSupportedException { - // this method exists to enable 100% test coverage - final StrTokenizer cloned = (StrTokenizer) super.clone(); - if (cloned.chars != null) { - cloned.chars = cloned.chars.clone(); - } - cloned.reset(); - return cloned; - } - - // ----------------------------------------------------------------------- - /** - * Gets the String content that the tokenizer is parsing. - * - * @return the string content being parsed - */ - @Override - public String toString() { - if (tokens == null) { - return "StrTokenizer[not tokenized yet]"; - } - return "StrTokenizer" + getTokenList(); - } - -} diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerChannelWrapper.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerChannelWrapper.java deleted file mode 100644 index 8d37fb10..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerChannelWrapper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import io.netty.channel.ChannelHandlerContext; -import net.md_5.bungee.netty.ChannelWrapper; -import net.md_5.bungee.protocol.Protocol; - -public class EaglerChannelWrapper extends ChannelWrapper { - - public EaglerChannelWrapper(ChannelHandlerContext ctx) { - super(ctx); - } - - public void setProtocol(Protocol protocol) { - getHandle().pipeline().get(EaglerMinecraftEncoder.class).setProtocol(protocol); - getHandle().pipeline().get(EaglerMinecraftDecoder.class).setProtocol(protocol); - } - - public void setVersion(int protocol) { - getHandle().pipeline().get(EaglerMinecraftEncoder.class).setProtocolVersion(protocol); - getHandle().pipeline().get(EaglerMinecraftDecoder.class).setProtocolVersion(protocol); - } - - private Protocol lastProtocol = Protocol.GAME; - - public Protocol getEncodeProtocol() { - EaglerMinecraftEncoder enc; - if (this.getHandle() == null || (enc = this.getHandle().pipeline().get(EaglerMinecraftEncoder.class)) == null) return lastProtocol; - return (lastProtocol = enc.getProtocol()); - } - - public void close(Object o) { - super.close(o); - EaglerPipeline.closeChannel(getHandle()); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerConnectionInstance.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerConnectionInstance.java deleted file mode 100644 index 94bb2b3c..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerConnectionInstance.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import io.netty.channel.Channel; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.md_5.bungee.UserConnection; - -public class EaglerConnectionInstance { - - public final Channel channel; - - public final long creationTime; - public boolean hasBeenForwarded = false; - - public long lastServerPingPacket; - public long lastClientPingPacket; - public long lastClientPongPacket; - - public boolean isWebSocket = false; - public boolean isRegularHttp = false; - - public UserConnection userConnection = null; - public HttpServerQueryHandler queryHandler = null; - - public EaglerConnectionInstance(Channel channel) { - this.channel = channel; - this.creationTime = this.lastServerPingPacket = this.lastClientPingPacket = - this.lastClientPongPacket = EaglerXBungeeAPIHelper.steadyTimeMillis(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerInitialHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerInitialHandler.java deleted file mode 100644 index 6cbda2ba..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerInitialHandler.java +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import com.google.common.collect.Collections2; - -import gnu.trove.set.TIntSet; -import gnu.trove.set.hash.TIntHashSet; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumWebViewState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.NotificationBadgeBuilder; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.BackendRPCSessionHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SimpleRateLimiter; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeHideV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsRegisterV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsReleaseV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketRedirectClientV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketSetServerCookieV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketWebViewMessageV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.Server; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.PacketWrapper; -import net.md_5.bungee.protocol.Property; -import net.md_5.bungee.protocol.packet.EncryptionResponse; -import net.md_5.bungee.protocol.packet.Handshake; -import net.md_5.bungee.protocol.packet.LegacyHandshake; -import net.md_5.bungee.protocol.packet.LegacyPing; -import net.md_5.bungee.protocol.packet.LoginPayloadResponse; -import net.md_5.bungee.protocol.packet.LoginRequest; -import net.md_5.bungee.protocol.packet.PingPacket; -import net.md_5.bungee.protocol.packet.PluginMessage; -import net.md_5.bungee.protocol.packet.StatusRequest; - -public class EaglerInitialHandler extends InitialHandler { - - public static class ClientCertificateHolder { - public final byte[] data; - public final int hash; - public ClientCertificateHolder(byte[] data, int hash) { - this.data = data; - this.hash = hash; - } - } - - protected final int clientProtocolVersion; - protected final int gameProtocolVersion; - protected final String clientBrandString; - protected final String clientVersionString; - protected final UUID clientBrandUUID; - protected final String username; - protected final UUID playerUUID; - protected final UUID playerUUIDOffline; - protected final UUID playerUUIDRewrite; - protected final InetSocketAddress eaglerAddress; - protected final InetSocketAddress virtualHost; - protected final Unsafe eaglerUnsafe; - public final SimpleRateLimiter skinLookupRateLimiter; - public final SimpleRateLimiter skinUUIDLookupRateLimiter; - public final SimpleRateLimiter skinTextureDownloadRateLimiter; - public final SimpleRateLimiter capeLookupRateLimiter; - public final SimpleRateLimiter voiceConnectRateLimiter; - protected final String origin; - protected final String userAgent; - public final ClientCertificateHolder clientCertificate; - public final Set certificatesToSend; - public final TIntSet certificatesSent; - public final EaglerChannelWrapper ch; - public final AtomicBoolean currentFNAWSkinEnableStatus = new AtomicBoolean(true); - public final AtomicBoolean currentFNAWSkinForceStatus = new AtomicBoolean(false); - volatile GameProtocolMessageController messageProtocolController = null; - protected final boolean allowCookie; - protected volatile byte[] cookie; - public volatile SkinPacketVersionCache originalSkin = null; - public volatile GameMessagePacket originalCape = null; - protected final Map otherProfileDataFromHanshake; - public boolean isWebViewChannelAllowed = false; - public final AtomicBoolean webViewMessageChannelOpen = new AtomicBoolean(false); - public volatile String webViewMessageChannelName = null; - public final AtomicBoolean hasSentServerInfo = new AtomicBoolean(false); - public final List serverInfoSendBuffer = new LinkedList<>(); - protected BackendRPCSessionHandler backedRPCSessionHandler = null; - protected final AtomicReference lastVoiceState = new AtomicReference<>( - EaglercraftVoiceStatusChangeEvent.EnumVoiceState.SERVER_DISABLE); - - private static final Property[] NO_PROPERTIES = new Property[0]; - - public EaglerInitialHandler(BungeeCord bungee, EaglerListenerConfig listener, final EaglerChannelWrapper ch, - int clientProtocolVersion, int gameProtocolVersion, String clientBrandString, String clientVersionString, - UUID clientBrandUUID, String username, UUID playerUUID, UUID offlineUUID, InetSocketAddress address, - String host, String origin, String userAgent, ClientCertificateHolder clientCertificate, - boolean allowCookie, byte[] cookie, Map otherProfileData) { - super(bungee, listener); - this.ch = ch; - this.clientProtocolVersion = clientProtocolVersion; - this.gameProtocolVersion = gameProtocolVersion; - this.clientBrandString = clientBrandString; - this.clientVersionString = clientVersionString; - this.clientBrandUUID = clientBrandUUID; - this.username = username; - this.playerUUID = playerUUID; - this.playerUUIDOffline = offlineUUID; - this.playerUUIDRewrite = bungee.config.isIpForward() ? playerUUID : offlineUUID; - this.eaglerAddress = address; - this.origin = origin; - this.userAgent = userAgent; - this.skinLookupRateLimiter = new SimpleRateLimiter(); - this.skinUUIDLookupRateLimiter = new SimpleRateLimiter(); - this.skinTextureDownloadRateLimiter = new SimpleRateLimiter(); - this.capeLookupRateLimiter = new SimpleRateLimiter(); - this.voiceConnectRateLimiter = new SimpleRateLimiter(); - this.allowCookie = allowCookie; - this.cookie = cookie; - this.otherProfileDataFromHanshake = otherProfileData; - this.clientCertificate = clientCertificate; - this.certificatesToSend = new HashSet<>(); - this.certificatesSent = new TIntHashSet(); - EaglerBungeeConfig conf = EaglerXBungee.getEagler().getConfig(); - SPacketCustomizePauseMenuV4EAG pkt = conf.getPauseMenuConf().getPacket(); - this.isWebViewChannelAllowed = pkt != null - && (pkt.serverInfoEmbedPerms & SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_MESSAGE_API) != 0; - this.backedRPCSessionHandler = conf.getEnableBackendRPCAPI() - ? BackendRPCSessionHandler.createForPlayer(this) : null; - if(clientCertificate != null) { - this.certificatesSent.add(clientCertificate.hashCode()); - } - if(host == null) host = ""; - int port = 25565; - if(host.contains(":")) { - int ind = host.lastIndexOf(':'); - try { - port = Integer.parseInt(host.substring(ind + 1)); - host = host.substring(0, ind); - } catch (NumberFormatException e) { - // - } - } - this.virtualHost = InetSocketAddress.createUnresolved(host, port); - this.eaglerUnsafe = new Unsafe() { - @Override - public void sendPacket(DefinedPacket arg0) { - ch.getHandle().writeAndFlush(arg0); - } - }; - Property[] profileProperties = NO_PROPERTIES; - if(EaglerXBungee.getEagler().getConfig().getEnableIsEaglerPlayerProperty()) { - profileProperties = new Property[] { EaglerBungeeConfig.isEaglerProperty }; - } - setLoginProfile(new LoginResult(playerUUID.toString(), username, profileProperties)); - try { - super.connected(ch); - } catch (Exception e) { - } - } - - public GameProtocolMessageController getEaglerMessageController() { - return messageProtocolController; - } - - public GamePluginMessageProtocol getEaglerProtocol() { - return messageProtocolController == null ? GamePluginMessageProtocol.getByVersion(clientProtocolVersion) - : messageProtocolController.protocol; - } - - public int getEaglerProtocolHandshake() { - return clientProtocolVersion; - } - - public void sendEaglerMessage(GameMessagePacket pkt) { - if(messageProtocolController != null) { - try { - messageProtocolController.sendPacket(pkt); - } catch (IOException e) { - this.disconnect(new TextComponent("Failed to write eaglercraft packet! (" + e.toString() + ")")); - } - }else { - throw new IllegalStateException("Race condition detected, messageProtocolController is null! (wait until getEaglerMessageController() does not return null before sending the packet)"); - } - } - - public boolean getWebViewSupport() { - return getEaglerProtocol().ver >= 4; - } - - public void setWebViewChannelAllowed(boolean en) { - isWebViewChannelAllowed = en; - } - public boolean getWebViewChannelAllowed() { - return isWebViewChannelAllowed; - } - - public boolean getWebViewMessageChannelOpen() { - return webViewMessageChannelOpen.get(); - } - - public String getWebViewMessageChannelName() { - return webViewMessageChannelName; - } - - public void sendWebViewMessage(int type, byte[] bytes) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(type, bytes)); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to send a webview message to player \"" + username + "\", but the player doesn't have a webview message channel open!"); - } - } - public void sendWebViewMessage(String str) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(str)); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to send a webview message to player \"" + username + "\", but the player doesn't have a webview message channel open!"); - } - } - - public void sendWebViewMessage(byte[] bin) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(bin)); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to send a webview message to player \"" + username + "\", but the player doesn't have a webview message channel open!"); - } - } - - public EnumWebViewState getWebViewState() { - if(!getWebViewSupport()) { - return EnumWebViewState.NOT_SUPPORTED; - } - if(isWebViewChannelAllowed) { - if(webViewMessageChannelOpen.get()) { - return EnumWebViewState.CHANNEL_OPEN; - }else { - return EnumWebViewState.CHANNEL_CLOSED; - } - }else { - return EnumWebViewState.SERVER_DISABLE; - } - } - - public boolean getCookieAllowed() { - return allowCookie; - } - - public byte[] getCookieData() { - return allowCookie ? cookie : null; - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public void setCookieData(byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - if(allowCookie) { - if(expiresAfterSec < 0l) { - expiresAfterSec = 0l; - data = null; - } - if(data == null) { - cookie = null; - sendEaglerMessage(new SPacketSetServerCookieV4EAG(null, 01, false, false)); - return; - } - if(data.length > 255) { - throw new IllegalArgumentException("Cookie cannot be longer than 255 bytes!"); - } - if(expiresAfterSec > 604800l) { - throw new IllegalArgumentException("Cookie cannot be set for longer than 7 days! (tried " + (expiresAfterSec / 604800l) + " days)"); - } - cookie = data; - sendEaglerMessage(new SPacketSetServerCookieV4EAG(data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk)); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to set a cookie for player \"" + username + "\", but the player has cookies disabled!"); - } - } - - public void clearCookieData() { - setCookieData(null, 0, false, false); - } - - public boolean notificationSupported() { - return clientProtocolVersion >= 4; - } - - public void registerNotificationIcon(UUID uuid, PacketImageData imageData) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG( - Arrays.asList(new SPacketNotifIconsRegisterV4EAG.CreateIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), imageData)))); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to register notification icons for player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void registerNotificationIcons(Map imageDatas) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG( - new ArrayList<>(Collections2.transform(imageDatas.entrySet(), (etr) -> { - UUID key = etr.getKey(); - return new SPacketNotifIconsRegisterV4EAG.CreateIcon(key.getMostSignificantBits(), - key.getLeastSignificantBits(), etr.getValue()); - })))); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to register notification icons for player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void showNotificationBadge(NotificationBadgeBuilder badgeBuilder) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(badgeBuilder.buildPacket()); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to show notification badges to player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void showNotificationBadge(SPacketNotifBadgeShowV4EAG badgePacket) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(badgePacket); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to show notification badges to player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void hideNotificationBadge(UUID badgeUUID) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifBadgeHideV4EAG(badgeUUID.getMostSignificantBits(), badgeUUID.getLeastSignificantBits())); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to hide notification badges for player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void releaseNotificationIcon(UUID uuid) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG( - Arrays.asList(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())))); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to release notification icons for player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public void releaseNotificationIcons(Collection uuids) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG(new ArrayList<>(Collections2.transform(uuids, - (etr) -> new SPacketNotifIconsReleaseV4EAG.DestroyIcon(etr.getMostSignificantBits(), - etr.getLeastSignificantBits()))))); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to release notification icons for player \"" + username + "\", but the player has notifications disabled!"); - } - } - - public boolean redirectToWebSocketSupported() { - return clientProtocolVersion >= 4; - } - - public void redirectPlayerToWebSocket(String serverAddress) { - if(getEaglerProtocol().ver >= 4) { - sendEaglerMessage(new SPacketRedirectClientV4EAG(serverAddress)); - }else { - EaglerXBungee.logger().warning("[" + getSocketAddress().toString() + "]: Some plugin tried to redirect player \"" + username + "\" to a different websocket, but that player's client doesn't support this feature!"); - } - } - - public BackendRPCSessionHandler getRPCSessionHandler() { - return backedRPCSessionHandler; - } - - public boolean getRPCEventSubscribed(EnumSubscribedEvent event) { - return backedRPCSessionHandler != null && backedRPCSessionHandler.isSubscribed(event); - } - - public void handleBackendRPCPacket(Server server, byte[] data) { - if(backedRPCSessionHandler != null) { - backedRPCSessionHandler.handleRPCPacket(server, data); - }else { - EaglerXBungee.logger().severe("[" + getSocketAddress().toString() + "]: Server tried to send backend RPC packet to player \"" + username + "\" but this feature is not enabled. Enable it by setting \"enable_backend_rpc_api: true\" in settings.yml"); - } - } - - public void fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState state) { - EaglercraftVoiceStatusChangeEvent.EnumVoiceState oldState = lastVoiceState.getAndSet(state); - if(state != oldState) { - BungeeCord.getInstance().getPluginManager().callEvent(new EaglercraftVoiceStatusChangeEvent( - EaglerXBungeeAPIHelper.getPlayer(this), getEaglerListenerConfig(), this, oldState, state)); - } - } - - public String getEaglerBrandString() { - return clientBrandString; - } - - public String getEaglerVersionString() { - return clientVersionString; - } - - public UUID getClientBrandUUID() { - return clientBrandUUID; - } - - public static UUID generateOfflineUUID(byte[] username) { - String offlinePlayerStr = "OfflinePlayer:"; - byte[] uuidHashGenerator = new byte[offlinePlayerStr.length() + username.length]; - System.arraycopy(offlinePlayerStr.getBytes(StandardCharsets.US_ASCII), 0, uuidHashGenerator, 0, offlinePlayerStr.length()); - System.arraycopy(username, 0, uuidHashGenerator, offlinePlayerStr.length(), username.length); - return UUID.nameUUIDFromBytes(uuidHashGenerator); - } - - private static final Field loginProfileField; - - static { - try { - loginProfileField = InitialHandler.class.getDeclaredField("loginProfile"); - loginProfileField.setAccessible(true); - }catch(Throwable t) { - throw new RuntimeException("Could not access loginProfile field", t); - } - } - - void setLoginProfile(LoginResult obj) { - try { - loginProfileField.set(this, obj); - }catch(Throwable t) { - throw new RuntimeException("Could not perform reflection", t); - } - } - - public byte[] getOtherProfileDataFromHandshake(String name) { - return otherProfileDataFromHanshake.get(name); - } - - @Override - public void handle(PacketWrapper packet) throws Exception { - } - - @Override - public void handle(PluginMessage pluginMessage) throws Exception { - } - - @Override - public void handle(LegacyHandshake legacyHandshake) throws Exception { - } - - @Override - public void handle(LegacyPing ping) throws Exception { - } - - @Override - public void handle(StatusRequest statusRequest) throws Exception { - } - - @Override - public void handle(PingPacket ping) throws Exception { - } - - @Override - public void handle(Handshake handshake) throws Exception { - } - - @Override - public void handle(LoginRequest loginRequest) throws Exception { - } - - @Override - public void handle(EncryptionResponse encryptResponse) throws Exception { - } - - @Override - public void handle(LoginPayloadResponse response) throws Exception { - } - - @Override - public void disconnect(String reason) { - super.disconnect(reason); - } - - @Override - public void disconnect(BaseComponent... reason) { - super.disconnect(reason); - } - - @Override - public void disconnect(BaseComponent reason) { - super.disconnect(reason); - } - - @Override - public String getName() { - return username; - } - - @Override - public int getVersion() { - return gameProtocolVersion; - } - - @Override - public Handshake getHandshake() { - return new Handshake(gameProtocolVersion, virtualHost.getHostName(), virtualHost.getPort(), - gameProtocolVersion); - } - - @Override - public LoginRequest getLoginRequest() { - throw new UnsupportedOperationException("A plugin attempted to retrieve the LoginRequest packet from an EaglercraftX connection, " - + "which is not supported because Eaglercraft does not use online mode encryption. Please analyze the stack trace of this " - + "exception and reconfigure or remove the offending plugin to fix this issue."); - } - - @Override - public PluginMessage getBrandMessage() { - String brand = "EaglercraftX"; - byte[] pkt = new byte[brand.length() + 1]; - pkt[0] = (byte)brand.length(); - System.arraycopy(brand.getBytes(StandardCharsets.US_ASCII), 0, pkt, 1, brand.length()); - return new PluginMessage("MC|Brand", pkt, true); - } - - @Override - public UUID getUniqueId() { - return playerUUID; - } - - @Override - public UUID getOfflineId() { - return playerUUIDOffline; - } - - @Override - public UUID getRewriteId() { - return playerUUIDRewrite; - } - - @Override - public void setUniqueId(UUID uuid) { - throw new UnsupportedOperationException("EaglercraftXBungee does not support changing player UUIDs at login! (yet)"); - } - - @Override - public void setOnlineMode(boolean onlineMode) { - throw new UnsupportedOperationException("EaglercraftXBungee does not support changing player online mode status at login! (yet)"); - } - - @Override - public String getUUID() { - return playerUUID.toString().replace("-", ""); - } - - @Override - public InetSocketAddress getVirtualHost() { - return virtualHost; - } - - @Override - public SocketAddress getSocketAddress() { - return eaglerAddress; - } - - @Override - public Unsafe unsafe() { - return eaglerUnsafe; - } - - public String getOrigin() { - return origin; - } - - public String getUserAgent() { - return userAgent; - } - - public EaglerListenerConfig getEaglerListenerConfig() { - return (EaglerListenerConfig)getListener(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftByteBufEncoder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftByteBufEncoder.java deleted file mode 100644 index 1ef47996..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftByteBufEncoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.util.List; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; - -public class EaglerMinecraftByteBufEncoder extends MessageToMessageEncoder { - - @Override - protected void encode(ChannelHandlerContext var1, ByteBuf var2, List var3) throws Exception { - var3.add(new BinaryWebSocketFrame(var2.retain())); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftDecoder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftDecoder.java deleted file mode 100644 index c6671a96..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftDecoder.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.PacketWrapper; -import net.md_5.bungee.protocol.Protocol; -import net.md_5.bungee.protocol.ProtocolConstants.Direction; - -public class EaglerMinecraftDecoder extends MessageToMessageDecoder { - private Protocol protocol; - private final boolean server; - private int protocolVersion; - private static Constructor packetWrapperConstructor = null; - - @Override - protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List out) throws Exception { - if(!ctx.channel().isActive()) { - return; - } - EaglerConnectionInstance con = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - if(frame instanceof BinaryWebSocketFrame) { - BinaryWebSocketFrame in = (BinaryWebSocketFrame) frame; - ByteBuf buf = in.content(); - buf.markReaderIndex(); - int pktId = DefinedPacket.readVarInt(buf); - DefinedPacket pkt = EaglerProtocolAccessProxy.createPacket(protocol, protocolVersion, pktId, server); - if(pkt != null) { - pkt.read(buf, server ? Direction.TO_CLIENT : Direction.TO_SERVER, protocolVersion); - if(buf.isReadable()) { - EaglerXBungee.logger().severe("[DECODER][" + ctx.channel().remoteAddress() + "] Packet " + - pkt.getClass().getSimpleName() + " had extra bytes! (" + buf.readableBytes() + ")"); - }else { - buf.resetReaderIndex(); - out.add(this.wrapPacket(pkt, buf, protocol)); - } - }else { - buf.resetReaderIndex(); - out.add(this.wrapPacket(null, buf, protocol)); - } - }else if(frame instanceof PingWebSocketFrame) { - if(millis - con.lastClientPingPacket > 500l) { - ctx.write(new PongWebSocketFrame()); - con.lastClientPingPacket = millis; - } - }else if(frame instanceof PongWebSocketFrame) { - con.lastClientPongPacket = millis; - }else { - ctx.close(); - } - } - - public EaglerMinecraftDecoder(Protocol protocol, boolean server, int protocolVersion) { - this.protocol = protocol; - this.server = server; - this.protocolVersion = protocolVersion; - } - - public void setProtocol(Protocol protocol) { - this.protocol = protocol; - } - - public void setProtocolVersion(int protocolVersion) { - this.protocolVersion = protocolVersion; - } - - private PacketWrapper wrapPacket(DefinedPacket packet, ByteBuf buf, Protocol protocol) { - boolean isInputDirect = buf.isDirect(); - if(!isInputDirect) { - int len = buf.readableBytes(); - ByteBuf newBuf = buf.alloc().directBuffer(len); - buf.readBytes(newBuf, len); - buf = newBuf; - } - try { - PacketWrapper pkt; - if (packetWrapperConstructor != null) { - try { - pkt = packetWrapperConstructor.newInstance(packet, buf); - buf.retain(); - return pkt; - } catch (IllegalAccessException | InvocationTargetException | InstantiationException var14) { - throw new RuntimeException(var14); - } - } - - try { - pkt = new PacketWrapper(packet, buf, protocol); - buf.retain(); - return pkt; - } catch (NoSuchMethodError var15) { - try { - packetWrapperConstructor = PacketWrapper.class.getDeclaredConstructor(DefinedPacket.class, ByteBuf.class); - pkt = packetWrapperConstructor.newInstance(packet, buf); - buf.retain(); - return pkt; - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException var13) { - throw new RuntimeException(var13); - } - } - }finally { - if(!isInputDirect) { - buf.release(); - } - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftEncoder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftEncoder.java deleted file mode 100644 index 21251405..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftEncoder.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.lang.reflect.Method; -import java.util.List; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.Protocol; -import net.md_5.bungee.protocol.ProtocolConstants.Direction; - -public class EaglerMinecraftEncoder extends MessageToMessageEncoder { - - private Protocol protocol; - private boolean server; - private int protocolVersion; - private static Method meth = null; - - @Override - protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, List out) throws Exception { - ByteBuf buf = ctx.alloc().buffer(); - int pk = EaglerProtocolAccessProxy.getPacketId(protocol, protocolVersion, msg, server); - DefinedPacket.writeVarInt(pk, buf); - try { - msg.write(buf, protocol, server ? Direction.TO_CLIENT : Direction.TO_SERVER, protocolVersion); - } catch (NoSuchMethodError e) { - try { - if (meth == null) { - meth = DefinedPacket.class.getDeclaredMethod("write", ByteBuf.class, Direction.class, int.class); - } - meth.invoke(msg, buf, server ? Direction.TO_CLIENT : Direction.TO_SERVER, protocolVersion); - } catch (Exception e1) { - buf.release(); - throw new RuntimeException("Could not call DefinedPacket write method!", e1); - } - } catch (Exception e) { - buf.release(); - throw new RuntimeException("Could not call DefinedPacket write method!", e); - } - out.add(new BinaryWebSocketFrame(buf)); - } - - public EaglerMinecraftEncoder(Protocol protocol, boolean server, int protocolVersion) { - this.protocol = protocol; - this.server = server; - this.protocolVersion = protocolVersion; - } - - public void setProtocol(Protocol protocol) { - this.protocol = protocol; - } - - public void setProtocolVersion(int protocolVersion) { - this.protocolVersion = protocolVersion; - } - - public Protocol getProtocol() { - return this.protocol; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftWrappedEncoder.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftWrappedEncoder.java deleted file mode 100644 index 49632c96..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerMinecraftWrappedEncoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.util.List; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import net.md_5.bungee.protocol.PacketWrapper; - -public class EaglerMinecraftWrappedEncoder extends MessageToMessageEncoder { - - @Override - protected void encode(ChannelHandlerContext ctx, PacketWrapper msg, List out) throws Exception { - out.add(new BinaryWebSocketFrame(msg.buf)); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerPipeline.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerPipeline.java deleted file mode 100644 index 7a664d66..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerPipeline.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.commons.lang3.ArrayUtils; - -import io.netty.buffer.PooledByteBufAllocator; -import io.netty.channel.Channel; -import io.netty.channel.ChannelException; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.WriteBufferWaterMark; -import io.netty.handler.codec.compression.ZlibCodecFactory; -import io.netty.handler.codec.haproxy.HAProxyMessageDecoder; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler; -import io.netty.handler.codec.http.websocketx.extensions.compression.DeflateFrameServerExtensionHandshaker; -import io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateServerExtensionHandshaker; -import io.netty.util.AttributeKey; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler.ClientCertificateHolder; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.BackendRPCSessionHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpWebServer; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketEnableFNAWSkinsEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUpdateCertEAG; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ServerConnection; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.scheduler.BungeeScheduler; - -public class EaglerPipeline { - - public static final AttributeKey LISTENER = AttributeKey.valueOf("ListenerInfo"); - public static final AttributeKey LOCAL_ADDRESS = AttributeKey.valueOf("LocalAddress"); - public static final AttributeKey CONNECTION_INSTANCE = AttributeKey.valueOf("EaglerConnectionInstance"); - public static final AttributeKey REAL_ADDRESS = AttributeKey.valueOf("RealAddress"); - public static final AttributeKey HOST = AttributeKey.valueOf("Host"); - public static final AttributeKey ORIGIN = AttributeKey.valueOf("Origin"); - public static final AttributeKey USER_AGENT = AttributeKey.valueOf("UserAgent"); - public static final int LOW_MARK = Integer.getInteger("net.md_5.bungee.low_mark", 524288); - public static final int HIGH_MARK = Integer.getInteger("net.md_5.bungee.high_mark", 2097152); - public static final WriteBufferWaterMark MARK = new WriteBufferWaterMark(LOW_MARK, HIGH_MARK); - - public static final Collection openChannels = new LinkedList<>(); - public static final Set waitingServerConnections = new HashSet<>(); - - public static final String UPDATE_CERT_CHANNEL = "EAG|UpdateCert-1.8"; - - public static final TimerTask closeInactive = new TimerTask() { - - @Override - public void run() { - Logger log = EaglerXBungee.logger(); - try { - EaglerBungeeConfig conf = EaglerXBungee.getEagler().getConfig(); - long handshakeTimeout = conf.getWebsocketHandshakeTimeout(); - long keepAliveTimeout = conf.getWebsocketKeepAliveTimeout(); - long httpTimeout = conf.getBuiltinHttpServerTimeout(); - List channelsList; - synchronized(openChannels) { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - Iterator channelIterator = openChannels.iterator(); - while(channelIterator.hasNext()) { - Channel c = channelIterator.next(); - final EaglerConnectionInstance i = c.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - long handshakeTimeoutForConnection = 500l; - if(i.isRegularHttp) handshakeTimeoutForConnection = httpTimeout; - else if(i.isWebSocket) handshakeTimeoutForConnection = handshakeTimeout; - boolean hasTimeout = !i.hasBeenForwarded; - if(i.queryHandler != null) { - long l = i.queryHandler.getMaxAge(); - hasTimeout = l != -1l; - if(hasTimeout) { - handshakeTimeoutForConnection = l; - } - } - if((hasTimeout && millis - i.creationTime > handshakeTimeoutForConnection) - || millis - i.lastClientPongPacket > keepAliveTimeout || !c.isActive()) { - if(c.isActive()) { - c.close(); - } - channelIterator.remove(); - }else { - long pingRate = 5000l; - if(pingRate + 700l > keepAliveTimeout) { - pingRate = keepAliveTimeout - 500l; - if(pingRate < 500l) { - keepAliveTimeout = 500l; - } - } - if(millis - i.lastServerPingPacket > pingRate) { - i.lastServerPingPacket = millis; - c.write(new PingWebSocketFrame()); - } - } - } - channelsList = new ArrayList<>(openChannels); - } - List readyServerConnections = null; - synchronized(waitingServerConnections) { - Iterator connIterator = waitingServerConnections.iterator(); - while(connIterator.hasNext()) { - UserConnection userCon = connIterator.next(); - if(userCon.isConnected()) { - ServerConnection serverCon = userCon.getServer(); - if(serverCon != null) { - if(readyServerConnections == null) { - readyServerConnections = new ArrayList<>(4); - } - readyServerConnections.add(userCon); - connIterator.remove(); - } - }else { - connIterator.remove(); - } - } - } - if(readyServerConnections != null) { - for(int i = 0, l = readyServerConnections.size(); i < l; ++i) { - handleServerConnectionReady(readyServerConnections.get(i)); - } - } - boolean updateLoop = !conf.getUpdateConfig().isBlockAllClientUpdates(); - final AtomicInteger sizeTracker = updateLoop ? new AtomicInteger(0) : null; - final int rateLimitParam = conf.getUpdateConfig().getCertPacketDataRateLimit() / 4; - final int serverInfoSendRate = Math.max(conf.getPauseMenuConf().getInfoSendRate(), 1); - BungeeScheduler sched = BungeeCord.getInstance().getScheduler(); - for(Channel c : channelsList) { - EaglerConnectionInstance conn = c.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - if(conn.userConnection == null) { - continue; - } - final EaglerInitialHandler i = (EaglerInitialHandler)conn.userConnection.getPendingConnection(); - boolean certToSend = false; - if(updateLoop) { - synchronized(i.certificatesToSend) { - if(!i.certificatesToSend.isEmpty()) { - certToSend = true; - } - } - } - boolean serverInfoToSend = false; - synchronized(i.serverInfoSendBuffer) { - if(!i.serverInfoSendBuffer.isEmpty()) { - serverInfoToSend = true; - } - } - if(certToSend || serverInfoToSend) { - final boolean do_certToSend = certToSend; - final boolean do_serverInfoToSend = serverInfoToSend; - sched.runAsync(EaglerXBungee.getEagler(), () -> { - if(do_certToSend) { - ClientCertificateHolder certHolder = null; - synchronized(i.certificatesToSend) { - if(i.certificatesToSend.size() > 0) { - Iterator itr = i.certificatesToSend.iterator(); - certHolder = itr.next(); - itr.remove(); - } - } - if(certHolder != null && sizeTracker.getAndAdd(certHolder.data.length) < rateLimitParam) { - int identityHash = certHolder.hashCode(); - boolean bb; - synchronized(i.certificatesSent) { - bb = i.certificatesSent.add(identityHash); - } - if(bb) { - i.sendEaglerMessage(new SPacketUpdateCertEAG(certHolder.data)); - } - } - } - if(do_serverInfoToSend) { - List toSend = i.serverInfoSendBuffer; - synchronized(toSend) { - if(!toSend.isEmpty()) { - try { - if(serverInfoSendRate == 1) { - i.getEaglerMessageController().sendPacketImmediately(toSend.remove(0)); - }else { - for(int j = 0; j < serverInfoSendRate; ++j) { - if(!toSend.isEmpty()) { - i.getEaglerMessageController().sendPacketImmediately(toSend.remove(0)); - }else { - break; - } - } - } - }catch(Throwable t) { - log.log(Level.SEVERE, "Exception in thread \"" + Thread.currentThread().getName() + "\"!", t); - } - } - } - } - }); - } - } - for(EaglerListenerConfig lst : conf.getServerListeners()) { - HttpWebServer srv = lst.getWebServer(); - if(srv != null) { - try { - srv.flushCache(); - }catch(Throwable t) { - log.severe("Failed to flush web server cache for: " + lst.getAddress().toString()); - t.printStackTrace(); - } - } - } - }catch(Throwable t) { - log.severe("Exception in thread \"" + Thread.currentThread().getName() + "\"! " + t.toString()); - t.printStackTrace(); - } - } - }; - - public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - channel.config().setAllocator(PooledByteBufAllocator.DEFAULT).setWriteBufferWaterMark(MARK); - try { - channel.config().setOption(ChannelOption.IP_TOS, 24); - } catch (ChannelException var3) { - } - EaglerListenerConfig listener = channel.attr(LISTENER).get(); - ChannelPipeline pipeline = channel.pipeline(); - if(listener.isHAProxyProtocol()) { - pipeline.addLast("HAProxyMessageDecoder", new HAProxyMessageDecoder()); - } - pipeline.addLast("HttpServerCodec", new HttpServerCodec()); - pipeline.addLast("HttpObjectAggregator", new HttpObjectAggregator(65535)); - int compressionLevel = EaglerXBungee.getEagler().getConfig().getHttpWebsocketCompressionLevel(); - if(compressionLevel > 0) { - if(compressionLevel > 9) { - compressionLevel = 9; - } - DeflateFrameServerExtensionHandshaker deflateExtensionHandshaker = new DeflateFrameServerExtensionHandshaker( - compressionLevel); - PerMessageDeflateServerExtensionHandshaker perMessageDeflateExtensionHandshaker = new PerMessageDeflateServerExtensionHandshaker( - compressionLevel, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), - PerMessageDeflateServerExtensionHandshaker.MAX_WINDOW_SIZE, false, false); - pipeline.addLast("HttpCompressionHandler", new WebSocketServerExtensionHandler(deflateExtensionHandshaker, - perMessageDeflateExtensionHandshaker)); - } - pipeline.addLast("HttpHandshakeHandler", new HttpHandshakeHandler(listener)); - channel.attr(CONNECTION_INSTANCE).set(new EaglerConnectionInstance(channel)); - synchronized(openChannels) { - openChannels.add(channel); - } - } - - }; - - public static void closeChannel(Channel channel) { - synchronized(openChannels) { - openChannels.remove(channel); - } - } - - public static void addServerConnectListener(UserConnection player) { - synchronized(waitingServerConnections) { - waitingServerConnections.add(player); - } - } - - private static void handleServerConnectionReady(UserConnection userConnection) { - try { - ServerConnection server = userConnection.getServer(); - server.sendData(BackendRPCSessionHandler.getReadyChNameFor(server), ArrayUtils.EMPTY_BYTE_ARRAY); - if(userConnection.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler handler = (EaglerInitialHandler) userConnection.getPendingConnection(); - ServerInfo sv = server.getInfo(); - EaglerXBungee plugin = EaglerXBungee.getEagler(); - boolean fnawSkins = !plugin.getConfig().getDisableFNAWSkinsEverywhere() - && !plugin.getConfig().getDisableFNAWSkinsOnServersSet().contains(sv.getName()); - if(fnawSkins != handler.currentFNAWSkinEnableStatus.getAndSet(fnawSkins)) { - handler.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(fnawSkins, false)); - } - if(handler.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerConnected(userConnection, sv); - } - } - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Failed to process server connection ready handler for player \"" - + userConnection.getName() + "\"", t); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerProtocolAccessProxy.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerProtocolAccessProxy.java deleted file mode 100644 index a56f9c81..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerProtocolAccessProxy.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.Protocol; - -public class EaglerProtocolAccessProxy { - - private static final Field fieldToClient; - private static final Field fieldToServer; - private static final Method methodGetId; - private static final Method methodCreatePacket; - - static { - try { - fieldToClient = Protocol.class.getDeclaredField("TO_CLIENT"); - fieldToClient.setAccessible(true); - fieldToServer = Protocol.class.getDeclaredField("TO_SERVER"); - fieldToServer.setAccessible(true); - methodGetId = Protocol.DirectionData.class.getDeclaredMethod("getId", Class.class, int.class); - methodGetId.setAccessible(true); - methodCreatePacket = Protocol.DirectionData.class.getDeclaredMethod("createPacket", int.class, int.class); - methodCreatePacket.setAccessible(true); - }catch(Throwable t) { - throw new RuntimeException(t); - } - } - - public static int getPacketId(Protocol protocol, int protocolVersion, DefinedPacket pkt, boolean server) { - try { - Object prot = server ? fieldToClient.get(protocol) : fieldToServer.get(protocol); - return (int)methodGetId.invoke(prot, pkt.getClass(), protocolVersion); - }catch(Throwable t) { - throw new RuntimeException(t); - } - } - - public static DefinedPacket createPacket(Protocol protocol, int protocolVersion, int packetId, boolean server) { - try { - Object prot = server ? fieldToClient.get(protocol) : fieldToServer.get(protocol); - return (DefinedPacket) methodCreatePacket.invoke(prot, packetId, protocolVersion); - }catch(Throwable t) { - throw new RuntimeException(t); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerUpdateSvc.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerUpdateSvc.java deleted file mode 100644 index a3981596..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/EaglerUpdateSvc.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.SHA1Digest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerUpdateConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler.ClientCertificateHolder; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.ProxiedPlayer; - -public class EaglerUpdateSvc { - - private static final List certs = new ArrayList<>(); - private static final Map certsCache = new HashMap<>(); - private static final Set deadURLS = new HashSet<>(); - - private static class CachedClientCertificate { - private final ClientCertificateHolder cert; - private final long lastModified; - public CachedClientCertificate(ClientCertificateHolder cert, long lastModified) { - this.cert = cert; - this.lastModified = lastModified; - } - } - - private static long lastDownload = 0l; - private static long lastEnumerate = 0l; - - public static void updateTick() { - Logger log = EaglerXBungee.logger(); - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - EaglerUpdateConfig conf = EaglerXBungee.getEagler().getConfig().getUpdateConfig(); - if(conf.isDownloadLatestCerts() && millis - lastDownload > (long)conf.getCheckForUpdatesEvery() * 1000l) { - lastDownload = millis; - lastEnumerate = 0l; - try { - downloadUpdates(); - }catch(Throwable t) { - log.severe("Uncaught exception downloading certificates!"); - t.printStackTrace(); - } - millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - } - if(conf.isEnableEagcertFolder() && millis - lastEnumerate > 5000l) { - lastEnumerate = millis; - try { - enumerateEagcertDirectory(); - }catch(Throwable t) { - log.severe("Uncaught exception reading eagcert directory!"); - t.printStackTrace(); - } - } - } - - private static void downloadUpdates() throws Throwable { - Logger log = EaglerXBungee.logger(); - EaglerUpdateConfig conf = EaglerXBungee.getEagler().getConfig().getUpdateConfig(); - File eagcert = new File(EaglerXBungee.getEagler().getDataFolder(), "eagcert"); - if(!eagcert.isDirectory()) { - if(!eagcert.mkdirs()) { - log.severe("Could not create directory: " + eagcert.getAbsolutePath()); - return; - } - } - Set filenames = new HashSet<>(); - for(String str : conf.getDownloadCertURLs()) { - try { - URL url = new URL(str); - HttpURLConnection con = (HttpURLConnection)url.openConnection(); - con.setDoInput(true); - con.setDoOutput(false); - con.setRequestMethod("GET"); - con.setConnectTimeout(30000); - con.setReadTimeout(30000); - con.setRequestProperty("User-Agent", "Mozilla/5.0 EaglerXBungee/" + EaglerXBungee.getEagler().getDescription().getVersion()); - con.connect(); - int code = con.getResponseCode(); - if(code / 100 != 2) { - con.disconnect(); - throw new IOException("Response code was " + code); - }else { - deadURLS.remove(str); - } - ByteArrayOutputStream bao = new ByteArrayOutputStream(32767); - try(InputStream is = con.getInputStream()) { - byte[] readBuffer = new byte[1024]; - int c; - while((c = is.read(readBuffer, 0, 1024)) != -1) { - bao.write(readBuffer, 0, c); - } - } - byte[] done = bao.toByteArray(); - SHA1Digest digest = new SHA1Digest(); - digest.update(done, 0, done.length); - byte[] hash = new byte[20]; - digest.doFinal(hash, 0); - char[] hexchars = new char[40]; - for(int i = 0; i < 20; ++i) { - hexchars[i << 1] = hex[(hash[i] >> 4) & 15]; - hexchars[(i << 1) + 1] = hex[hash[i] & 15]; - } - String strr = "$dl." + new String(hexchars) + ".cert"; - filenames.add(strr); - File cacheFile = new File(eagcert, strr); - if(cacheFile.exists()) { - continue; // no change - } - try(OutputStream os = new FileOutputStream(cacheFile)) { - os.write(done); - } - log.info("Downloading new certificate: " + str); - }catch(Throwable t) { - if(deadURLS.add(str)) { - log.severe("Failed to download certificate: " + str); - log.severe("Reason: " + t.toString()); - } - } - } - long millis = System.currentTimeMillis(); - File[] dirList = eagcert.listFiles(); - for(int i = 0; i < dirList.length; ++i) { - File f = dirList[i]; - String n = f.getName(); - if(!n.startsWith("$dl.")) { - continue; - } - if(millis - f.lastModified() > 86400000l && !filenames.contains(n)) { - log.warning("Deleting stale certificate: " + n); - if(!f.delete()) { - log.severe("Failed to delete: " + n); - } - } - } - } - - private static final char[] hex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - private static void enumerateEagcertDirectory() throws Throwable { - Logger log = EaglerXBungee.logger(); - File eagcert = new File(EaglerXBungee.getEagler().getDataFolder(), "eagcert"); - if(!eagcert.isDirectory()) { - if(!eagcert.mkdirs()) { - log.severe("Could not create directory: " + eagcert.getAbsolutePath()); - return; - } - } - boolean dirty = false; - File[] dirList = eagcert.listFiles(); - Set existingFiles = new HashSet<>(); - for(int i = 0; i < dirList.length; ++i) { - File f = dirList[i]; - String n = f.getName(); - long lastModified = f.lastModified(); - existingFiles.add(n); - CachedClientCertificate cc = certsCache.get(n); - if(cc != null) { - if(cc.lastModified != lastModified) { - try { - byte[] fileData = new byte[(int)f.length()]; - if(fileData.length > 0xFFFF) { - throw new IOException("File is too long! Max: 65535 bytes"); - } - try(FileInputStream fis = new FileInputStream(f)) { - for(int j = 0, k; (k = fis.read(fileData, j, fileData.length - j)) != -1 && j < fileData.length; j += k); - } - certsCache.remove(n); - ClientCertificateHolder ch = tryMakeHolder(fileData); - certsCache.put(n, new CachedClientCertificate(ch, lastModified)); - dirty = true; - sendCertificateToPlayers(ch); - log.info("Reloaded certificate: " + f.getAbsolutePath()); - }catch(IOException ex) { - log.severe("Failed to read: " + f.getAbsolutePath()); - log.severe("Reason: " + ex.toString()); - } - } - continue; - } - try { - byte[] fileData = new byte[(int)f.length()]; - if(fileData.length > 0xFFFF) { - throw new IOException("File is too long! Max: 65535 bytes"); - } - try(FileInputStream fis = new FileInputStream(f)) { - for(int j = 0, k; j < fileData.length && (k = fis.read(fileData, j, fileData.length - j)) != -1; j += k); - } - ClientCertificateHolder ch = tryMakeHolder(fileData); - certsCache.put(n, new CachedClientCertificate(ch, lastModified)); - dirty = true; - sendCertificateToPlayers(ch); - log.info("Loaded certificate: " + f.getAbsolutePath()); - }catch(IOException ex) { - log.severe("Failed to read: " + f.getAbsolutePath()); - log.severe("Reason: " + ex.toString()); - } - } - Iterator itr = certsCache.keySet().iterator(); - while(itr.hasNext()) { - String etr = itr.next(); - if(!existingFiles.contains(etr)) { - itr.remove(); - dirty = true; - log.warning("Certificate was deleted: " + etr); - } - } - if(dirty) { - remakeCertsList(); - } - } - - private static void remakeCertsList() { - synchronized(certs) { - certs.clear(); - for(CachedClientCertificate cc : certsCache.values()) { - certs.add(cc.cert); - } - } - } - - public static List getCertList() { - return certs; - } - - public static ClientCertificateHolder tryMakeHolder(byte[] data) { - int hash = Arrays.hashCode(data); - ClientCertificateHolder ret = tryGetHolder(data, hash); - if(ret == null) { - ret = new ClientCertificateHolder(data, hash); - } - return ret; - } - - public static ClientCertificateHolder tryGetHolder(byte[] data, int hash) { - synchronized(certs) { - for(ClientCertificateHolder cc : certs) { - if(cc.hash == hash && Arrays.equals(cc.data, data)) { - return cc; - } - } - } - for(ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) { - if(p.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler pp = (EaglerInitialHandler)p.getPendingConnection(); - if(pp.clientCertificate != null && pp.clientCertificate.hash == hash && Arrays.equals(pp.clientCertificate.data, data)) { - return pp.clientCertificate; - } - } - } - return null; - } - - public static void sendCertificateToPlayers(ClientCertificateHolder holder) { - for(ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) { - if(p.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler pp = (EaglerInitialHandler)p.getPendingConnection(); - boolean bb; - synchronized(pp.certificatesSent) { - bb = pp.certificatesSent.contains(holder.hashCode()); - } - if(!bb) { - Set set = pp.certificatesToSend; - synchronized(set) { - set.add(holder); - } - } - } - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HandshakePacketTypes.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HandshakePacketTypes.java deleted file mode 100644 index 7a3942b7..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HandshakePacketTypes.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -public class HandshakePacketTypes { - - public static final String AUTHENTICATION_REQUIRED = "Authentication Required:"; - - public static final int PROTOCOL_CLIENT_VERSION = 0x01; - public static final int PROTOCOL_SERVER_VERSION = 0x02; - public static final int PROTOCOL_VERSION_MISMATCH = 0x03; - public static final int PROTOCOL_CLIENT_REQUEST_LOGIN = 0x04; - public static final int PROTOCOL_SERVER_ALLOW_LOGIN = 0x05; - public static final int PROTOCOL_SERVER_DENY_LOGIN = 0x06; - public static final int PROTOCOL_CLIENT_PROFILE_DATA = 0x07; - public static final int PROTOCOL_CLIENT_FINISH_LOGIN = 0x08; - public static final int PROTOCOL_SERVER_FINISH_LOGIN = 0x09; - public static final int PROTOCOL_SERVER_ERROR = 0xFF; - - public static final int STATE_OPENED = 0x00; - public static final int STATE_CLIENT_VERSION = 0x01; - public static final int STATE_CLIENT_LOGIN = 0x02; - public static final int STATE_CLIENT_COMPLETE = 0x03; - public static final int STATE_STALLING = 0xFF; - - public static final int SERVER_ERROR_UNKNOWN_PACKET = 0x01; - public static final int SERVER_ERROR_INVALID_PACKET = 0x02; - public static final int SERVER_ERROR_WRONG_PACKET = 0x03; - public static final int SERVER_ERROR_EXCESSIVE_PROFILE_DATA = 0x04; - public static final int SERVER_ERROR_DUPLICATE_PROFILE_DATA = 0x05; - public static final int SERVER_ERROR_RATELIMIT_BLOCKED = 0x06; - public static final int SERVER_ERROR_RATELIMIT_LOCKED = 0x07; - public static final int SERVER_ERROR_CUSTOM_MESSAGE = 0x08; - public static final int SERVER_ERROR_AUTHENTICATION_REQUIRED = 0x09; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpHandshakeHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpHandshakeHandler.java deleted file mode 100644 index f1f716d2..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpHandshakeHandler.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.util.logging.Level; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; -import io.netty.util.ReferenceCountUtil; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftWebSocketOpenEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerRateLimiter; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.RateLimitStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpMemoryCache; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web.HttpWebServer; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.api.event.ClientConnectEvent; - -public class HttpHandshakeHandler extends ChannelInboundHandlerAdapter { - - private static final byte[] error429Bytes = "

429 Too Many Requests
(Try again later)

".getBytes(StandardCharsets.UTF_8); - - private final EaglerListenerConfig conf; - private boolean logExceptions; - private boolean healthCheck; - private InetSocketAddress haproxyRemoteAddr; - - public HttpHandshakeHandler(EaglerListenerConfig conf) { - this.conf = conf; - } - - public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if (msg instanceof HttpRequest) { - logExceptions = true; - EaglerConnectionInstance pingTracker = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - HttpRequest req = (HttpRequest) msg; - HttpHeaders headers = req.headers(); - - String rateLimitHost = null; - - SocketAddress addr; - if(conf.isForwardIp()) { - String str = headers.get(conf.getForwardIpHeader()); - if(str != null) { - rateLimitHost = str.split(",", 2)[0]; - try { - InetAddress inetAddr = InetAddress.getByName(rateLimitHost); - if(haproxyRemoteAddr != null) { - addr = new InetSocketAddress(inetAddr, haproxyRemoteAddr.getPort()); - }else { - addr = ctx.channel().remoteAddress(); - if(addr instanceof InetSocketAddress) { - addr = new InetSocketAddress(inetAddr, ((InetSocketAddress)addr).getPort()); - }else { - addr = new InetSocketAddress(inetAddr, 0); - } - } - ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).set(inetAddr); - }catch(UnknownHostException ex) { - EaglerXBungee.logger().warning("[" + ctx.channel().remoteAddress() + "]: Connected with an invalid '" + conf.getForwardIpHeader() + "' header, disconnecting..."); - ctx.close(); - return; - } - }else { - EaglerXBungee.logger().warning("[" + ctx.channel().remoteAddress() + "]: Connected without a '" + conf.getForwardIpHeader() + "' header, disconnecting..."); - ctx.close(); - return; - } - }else if(haproxyRemoteAddr != null) { - addr = haproxyRemoteAddr; - ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).set(haproxyRemoteAddr.getAddress()); - }else { - addr = ctx.channel().remoteAddress(); - if(addr instanceof InetSocketAddress) { - rateLimitHost = ((InetSocketAddress) addr).getAddress().getHostAddress(); - } - } - - EaglerRateLimiter ipRateLimiter = conf.getRatelimitIp(); - RateLimitStatus ipRateLimit = RateLimitStatus.OK; - - if(ipRateLimiter != null && rateLimitHost != null) { - ipRateLimit = ipRateLimiter.rateLimit(rateLimitHost); - } - - if(ipRateLimit == RateLimitStatus.LOCKED_OUT) { - ctx.close(); - return; - } - - ClientConnectEvent evt = BungeeCord.getInstance().getPluginManager().callEvent(new ClientConnectEvent(addr, conf)); - if(evt.isCancelled()) { - ctx.close(); - return; - } - - if(headers.get(HttpHeaderNames.CONNECTION) != null && headers.get(HttpHeaderNames.CONNECTION).toLowerCase().contains("upgrade") && - "websocket".equalsIgnoreCase(headers.get(HttpHeaderNames.UPGRADE))) { - - String origin = headers.get(HttpHeaderNames.ORIGIN); - if(origin != null) { - ctx.channel().attr(EaglerPipeline.ORIGIN).set(origin); - } - String userAgent = headers.get(HttpHeaderNames.USER_AGENT); - if(userAgent != null) { - ctx.channel().attr(EaglerPipeline.USER_AGENT).set(userAgent); - } - - if(ipRateLimit == RateLimitStatus.OK) { - EaglercraftWebSocketOpenEvent evt2 = new EaglercraftWebSocketOpenEvent(ctx.channel(), conf, rateLimitHost, origin, userAgent); - BungeeCord.getInstance().getPluginManager().callEvent(evt2); - if(evt2.isCancelled()) { - ctx.close(); - return; - } - ctx.channel().attr(EaglerPipeline.HOST).set(headers.get(HttpHeaderNames.HOST)); - ctx.pipeline().replace(this, "HttpWebSocketHandler", new HttpWebSocketHandler(conf)); - } - - WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( - "ws://" + headers.get(HttpHeaderNames.HOST) + req.uri(), null, true, 0xFFFFF); - WebSocketServerHandshaker hs = wsFactory.newHandshaker(req); - if(hs != null) { - pingTracker.isWebSocket = true; - ChannelFuture future = hs.handshake(ctx.channel(), req); - if(ipRateLimit != RateLimitStatus.OK) { - final RateLimitStatus rateLimitTypeFinal = ipRateLimit; - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture paramF) throws Exception { - ctx.writeAndFlush(new TextWebSocketFrame( - rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "LOCKED" : "BLOCKED")) - .addListener(ChannelFutureListener.CLOSE); - } - }); - } - }else { - WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()).addListener(ChannelFutureListener.CLOSE); - } - }else { - if(ipRateLimit != RateLimitStatus.OK) { - ByteBuf error429Buffer = ctx.alloc().buffer(error429Bytes.length, error429Bytes.length); - error429Buffer.writeBytes(error429Bytes); - DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.TOO_MANY_REQUESTS, error429Buffer); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); - return; - } - pingTracker.isRegularHttp = true; - HttpWebServer srv = conf.getWebServer(); - if(srv != null) { - String uri = req.uri(); - if(uri.startsWith("/")) { - uri = uri.substring(1); - } - int j = uri.indexOf('?'); - if(j != -1) { - uri = uri.substring(0, j); - } - HttpMemoryCache ch = srv.retrieveFile(uri); - if(ch != null) { - ctx.writeAndFlush(ch.createHTTPResponse()).addListener(ChannelFutureListener.CLOSE); - }else { - ctx.writeAndFlush(HttpWebServer.getWebSocket404().createHTTPResponse(HttpResponseStatus.NOT_FOUND)) - .addListener(ChannelFutureListener.CLOSE); - } - }else { - ctx.writeAndFlush(HttpWebServer.getWebSocket404().createHTTPResponse(HttpResponseStatus.NOT_FOUND)) - .addListener(ChannelFutureListener.CLOSE); - } - } - }else if(msg instanceof HAProxyMessage) { - logExceptions = true; - HAProxyMessage proxy = (HAProxyMessage) msg; - if(proxy.sourceAddress() != null) { - if(!conf.isForwardIp()) { - try { - haproxyRemoteAddr = new InetSocketAddress(proxy.sourceAddress(), proxy.sourcePort()); - }catch(IllegalArgumentException t) { - } - } - }else { - healthCheck = true; - } - }else { - ctx.close(); - } - }finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - if(logExceptions && !healthCheck) { - EaglerXBungee.logger().log(Level.WARNING, "[Pre][" + ctx.channel().remoteAddress() + "]: Exception Caught: " + cause.toString(), cause); - } - ctx.close(); - } - } - - public void channelInactive(ChannelHandlerContext ctx) { - EaglerPipeline.closeChannel(ctx.channel()); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpServerQueryHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpServerQueryHandler.java deleted file mode 100644 index dfd9db2a..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpServerQueryHandler.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.util.ReferenceCountUtil; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.QueryManager; - -public abstract class HttpServerQueryHandler extends ChannelInboundHandlerAdapter { - - public static class UnexpectedDataException extends RuntimeException { - public UnexpectedDataException() { - } - public UnexpectedDataException(String message, Throwable cause) { - super(message, cause); - } - public UnexpectedDataException(String message) { - super(message); - } - public UnexpectedDataException(Throwable cause) { - super(cause); - } - } - - private static final InetAddress localhost; - - static { - try { - localhost = InetAddress.getLocalHost(); - }catch(Throwable t) { - throw new RuntimeException("localhost doesn't exist?!", t); - } - } - - private EaglerListenerConfig conf; - private ChannelHandlerContext context; - private String accept; - private boolean acceptTextPacket = false; - private boolean acceptBinaryPacket = false; - private boolean hasClosed = false; - private boolean keepAlive = false; - private long maxAge = -1l; - - public void beginHandleQuery(EaglerListenerConfig conf, ChannelHandlerContext context, String accept) { - this.conf = conf; - this.context = context; - this.accept = accept; - begin(accept); - } - - protected void acceptText() { - acceptText(true); - } - - protected void acceptText(boolean bool) { - acceptTextPacket = bool; - } - - protected void acceptBinary() { - acceptBinary(true); - } - - protected void acceptBinary(boolean bool) { - acceptBinaryPacket = bool; - } - - public void close() { - context.close(); - hasClosed = true; - } - - public boolean isClosed() { - return hasClosed; - } - - public InetAddress getAddress() { - InetAddress addr = context.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr != null) { - return addr; - }else { - SocketAddress sockAddr = context.channel().remoteAddress(); - return sockAddr instanceof InetSocketAddress ? ((InetSocketAddress) sockAddr).getAddress() : localhost; - } - } - - public ChannelHandlerContext getContext() { - return context; - } - - public EaglerListenerConfig getListener() { - return conf; - } - - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if(msg instanceof WebSocketFrame) { - if(msg instanceof BinaryWebSocketFrame) { - handleBinary(ctx, ((BinaryWebSocketFrame)msg).content()); - }else if(msg instanceof TextWebSocketFrame) { - handleText(ctx, ((TextWebSocketFrame)msg).text()); - }else if(msg instanceof PingWebSocketFrame) { - ctx.writeAndFlush(new PongWebSocketFrame()); - }else if(msg instanceof CloseWebSocketFrame) { - ctx.close(); - } - }else if(msg instanceof HAProxyMessage) { - EaglerXBungee.logger().warning("[" + ctx.channel().remoteAddress() + "]: Ignoring HAProxyMessage because the WebSocket connection has already been established"); - }else { - EaglerXBungee.logger().severe("Unexpected Packet: " + msg.getClass().getSimpleName()); - } - }finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - EaglerXBungee.logger().warning("[" + ctx.channel().remoteAddress() + "]: Exception Caught: " + cause.toString()); - } - } - - private void handleBinary(ChannelHandlerContext ctx, ByteBuf buffer) { - if(!acceptBinaryPacket) { - ctx.close(); - return; - } - byte[] packet = new byte[buffer.readableBytes()]; - buffer.readBytes(packet); - processBytes(packet); - } - - private void handleText(ChannelHandlerContext ctx, String str) { - if(!acceptTextPacket) { - ctx.close(); - return; - } - JsonObject obj = null; - if(str.indexOf('{') == 0) { - try { - obj = JsonParser.parseString(str).getAsJsonObject(); - }catch(JsonParseException ex) { - } - } - if(obj != null) { - processJson(obj); - }else { - processString(str); - } - } - - public void channelInactive(ChannelHandlerContext ctx) { - EaglerPipeline.closeChannel(ctx.channel()); - hasClosed = true; - closed(); - } - - public String getAccept() { - return accept; - } - - public String getOrigin() { - return context.channel().attr(EaglerPipeline.ORIGIN).get(); - } - - public String getUserAgent() { - return context.channel().attr(EaglerPipeline.USER_AGENT).get(); - } - - public void sendStringResponse(String type, String str) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createStringResponse(accept, str).toString())); - } - - public void sendStringResponseAndClose(String type, String str) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createStringResponse(accept, str).toString())).addListener(ChannelFutureListener.CLOSE); - } - - public void sendJsonResponse(String type, JsonObject obj) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createJsonObjectResponse(accept, obj).toString())); - } - - public void sendJsonResponseAndClose(String type, JsonObject obj) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createJsonObjectResponse(accept, obj).toString())).addListener(ChannelFutureListener.CLOSE); - } - - public void sendBinaryResponse(byte[] bytes) { - context.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(bytes))); - } - - public void sendBinaryResponseAndClose(byte[] bytes) { - context.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(bytes))).addListener(ChannelFutureListener.CLOSE); - } - - public void setKeepAlive(boolean enable) { - keepAlive = enable; - } - - public boolean shouldKeepAlive() { - return keepAlive; - } - - public long getMaxAge() { - return maxAge; - } - - public void setMaxAge(long millis) { - this.maxAge = millis; - } - - protected abstract void begin(String queryType); - - protected abstract void processString(String str); - - protected abstract void processJson(JsonObject obj); - - protected abstract void processBytes(byte[] bytes); - - protected abstract void closed(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpWebSocketHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpWebSocketHandler.java deleted file mode 100644 index f745d8eb..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/HttpWebSocketHandler.java +++ /dev/null @@ -1,1448 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; - -import org.apache.commons.codec.binary.Base64; - -import com.google.common.collect.Sets; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import io.netty.util.ReferenceCountUtil; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftClientBrandEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftHandleAuthCookieEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftHandleAuthPasswordEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftIsAuthRequiredEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftMOTDEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftRegisterCapeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftRegisterSkinEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.command.CommandConfirmCode; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerRateLimiter; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerUpdateConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.RateLimitStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler.ClientCertificateHolder; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.MOTDQueryHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query.QueryManager; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.CapePackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinPackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.SkinService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.AbstractReconnectHandler; -import net.md_5.bungee.api.Callback; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.LoginEvent; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.api.event.PreLoginEvent; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.connection.UpstreamBridge; -import net.md_5.bungee.netty.HandlerBoss; -import net.md_5.bungee.protocol.Property; -import net.md_5.bungee.protocol.Protocol; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.event.ServerConnectEvent; - -public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { - - private final EaglerListenerConfig conf; - - private int clientLoginState = HandshakePacketTypes.STATE_OPENED; - private int clientProtocolVersion = -1; - private boolean isProtocolExchanged = false; - private int gameProtocolVersion = -1; - private String clientBrandString; - private String clientVersionString; - private String clientUsername; - private UUID clientUUID; - private UUID offlineUUID; - private String clientRequestedServer; - private boolean clientAuth; - private byte[] clientAuthUsername; - private byte[] clientAuthPassword; - private boolean clientEnableCookie; - private byte[] clientCookieData; - private EaglercraftIsAuthRequiredEvent authRequireEvent; - private final Map profileData = new HashMap<>(); - private boolean hasFirstPacket = false; - private boolean hasBinaryConnection = false; - private boolean connectionClosed = false; - private InetAddress remoteAddress; - private String localAddrString; - private Property texturesOverrideProperty; - private boolean overrideEaglerToVanillaSkins; - - private static final Set profileDataStandard = Sets.newHashSet( - "skin_v1", "skin_v2", "cape_v1", "update_cert_v1", "brand_uuid_v1"); - - public HttpWebSocketHandler(EaglerListenerConfig conf) { - this.conf = conf; - } - - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if(msg instanceof WebSocketFrame) { - if(msg instanceof BinaryWebSocketFrame) { - handleBinary(ctx, ((BinaryWebSocketFrame)msg).content()); - }else if(msg instanceof TextWebSocketFrame) { - handleText(ctx, ((TextWebSocketFrame)msg).text()); - }else if(msg instanceof PingWebSocketFrame) { - ctx.writeAndFlush(new PongWebSocketFrame()); - }else if(msg instanceof CloseWebSocketFrame) { - connectionClosed = true; - ctx.close(); - } - }else if(msg instanceof HAProxyMessage) { - EaglerXBungee.logger().warning("[" + ctx.channel().remoteAddress() + "]: Ignoring HAProxyMessage because the WebSocket connection has already been established"); - }else { - EaglerXBungee.logger().severe("Unexpected Packet: " + msg.getClass().getSimpleName()); - } - }finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - EaglerXBungee.logger().warning("[Yee][" + ctx.channel().remoteAddress() + "]: Exception Caught: " + cause.toString()); - } - } - - private void handleBinary(ChannelHandlerContext ctx, ByteBuf buffer) { - if(connectionClosed) { - return; - } - if(!hasFirstPacket) { - if(buffer.readableBytes() >= 2) { - if(buffer.getByte(0) == (byte)2 && buffer.getByte(1) == (byte)69) { - handleLegacyClient(ctx, buffer); - return; - } - } - hasFirstPacket = true; - hasBinaryConnection = true; - - BungeeCord bungus = BungeeCord.getInstance(); - int limit = bungus.config.getPlayerLimit(); - if (limit > 0 && bungus.getOnlineCount() >= limit) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, bungus.getTranslation("proxy_full")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(conf.getMaxPlayer() > 0) { - int i = 0; - for(ProxiedPlayer p : bungus.getPlayers()) { - if(p.getPendingConnection().getListener() == conf) { - ++i; - } - } - - if (i >= conf.getMaxPlayer()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, bungus.getTranslation("proxy_full")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - } - - SocketAddress localSocketAddr = ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - - String limiterAddress = null; - RateLimitStatus loginRateLimit = RateLimitStatus.OK; - if(addr != null) { - remoteAddress = addr; - limiterAddress = addr.getHostAddress(); - }else { - if(localSocketAddr instanceof InetSocketAddress) { - remoteAddress = ((InetSocketAddress)localSocketAddr).getAddress(); - limiterAddress = remoteAddress.getHostAddress(); - }else { - remoteAddress = InetAddress.getLoopbackAddress(); - } - } - - EaglerRateLimiter limiter = conf.getRatelimitLogin(); - if(limiterAddress != null && limiter != null) { - loginRateLimit = limiter.rateLimit(limiterAddress); - } - - if(loginRateLimit == RateLimitStatus.LOCKED_OUT) { - ctx.close(); - connectionClosed = true; - return; - } - - if (loginRateLimit != RateLimitStatus.OK) { - sendErrorCode(ctx, - loginRateLimit == RateLimitStatus.LIMITED_NOW_LOCKED_OUT - ? HandshakePacketTypes.SERVER_ERROR_RATELIMIT_LOCKED - : HandshakePacketTypes.SERVER_ERROR_RATELIMIT_BLOCKED, - "Too many logins!").addListener(ChannelFutureListener.CLOSE); - return; - } - - localAddrString = localSocketAddr.toString(); - EaglerXBungee.logger().info("[" + localAddrString + "]: Connected via websocket"); - if(addr != null) { - EaglerXBungee.logger().info("[" + localAddrString + "]: Real address is " + addr.getHostAddress()); - } - String origin = ctx.channel().attr(EaglerPipeline.ORIGIN).get(); - if(origin != null) { - EaglerXBungee.logger().info("[" + localAddrString + "]: Origin header is " + origin); - }else { - EaglerXBungee.logger().info("[" + localAddrString + "]: No origin header is present!"); - } - }else if(!hasBinaryConnection) { - connectionClosed = true; - ctx.close(); - return; - } - int op = -1; - try { - op = buffer.readUnsignedByte(); - switch(op) { - case HandshakePacketTypes.PROTOCOL_CLIENT_VERSION: { - if(clientLoginState == HandshakePacketTypes.STATE_OPENED) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - EaglerXBungee eaglerXBungee = EaglerXBungee.getEagler(); - EaglerAuthConfig authConfig = eaglerXBungee.getConfig().getAuthConfig(); - - int eaglerLegacyProtocolVersion = buffer.readUnsignedByte(); - - if(eaglerLegacyProtocolVersion == 1) { - if(authConfig.isEnableAuthentication()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Please update your client to register on this server!") - .addListener(ChannelFutureListener.CLOSE); - return; - }else if(buffer.readUnsignedByte() != 47 || 47 < conf.getMinMCProtocol() - || 47 > conf.getMaxMCProtocol() || !conf.isAllowV3()) { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); - buf.writeByte(1); - buf.writeByte(1); - buf.writeByte(eaglerLegacyProtocolVersion); - String str = "Outdated Client"; - buf.writeByte(str.length()); - buf.writeCharSequence(str, StandardCharsets.US_ASCII); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(ChannelFutureListener.CLOSE); - return; - } - }else if(eaglerLegacyProtocolVersion == 2) { - - //make sure to update VersionQueryHandler too - int minServerSupported = conf.isAllowV3() ? 2 : 4; - int maxServerSupported = conf.isAllowV4() ? 4 : 3; - int minAvailableProtVers = Integer.MAX_VALUE; - int maxAvailableProtVers = Integer.MIN_VALUE; - int protVers = -1; - - int cnt = buffer.readUnsignedShort(); - for(int i = 0; i < cnt; ++i) { - int j = buffer.readUnsignedShort(); - if(j > maxAvailableProtVers) { - maxAvailableProtVers = j; - } - if(j < minAvailableProtVers) { - minAvailableProtVers = j; - } - if(j >= minServerSupported && j <= maxServerSupported && j > protVers) { - protVers = j; - } - } - - int minGameVers = conf.getMinMCProtocol(); - int maxGameVers = conf.getMaxMCProtocol(); - int minAvailableGameVers = Integer.MAX_VALUE; - int maxAvailableGameVers = Integer.MIN_VALUE; - int gameVers = -1; - - cnt = buffer.readUnsignedShort(); - for(int i = 0; i < cnt; ++i) { - int j = buffer.readUnsignedShort(); - if(j > maxAvailableGameVers) { - maxAvailableGameVers = j; - } - if(j < minAvailableGameVers) { - minAvailableGameVers = j; - } - if(j >= minGameVers && j <= maxGameVers && j > gameVers) { - gameVers = j; - } - } - - if(maxAvailableProtVers == Integer.MIN_VALUE || maxAvailableGameVers == Integer.MIN_VALUE) { - throw new IOException(); - } - - boolean versMisMatch = false; - boolean isServerProbablyOutdated = false; - boolean isClientProbablyOutdated = false; - if(protVers == -1) { - clientProtocolVersion = maxAvailableProtVers < 3 ? 2 : 3; - versMisMatch = true; - isServerProbablyOutdated = minAvailableProtVers > maxServerSupported && maxAvailableProtVers > maxServerSupported; - isClientProbablyOutdated = minAvailableProtVers < minServerSupported && maxAvailableProtVers < minServerSupported; - }else { - clientProtocolVersion = protVers; - if(gameVers == -1) { - versMisMatch = true; - isServerProbablyOutdated = minAvailableGameVers > maxGameVers && maxAvailableGameVers > maxGameVers; - isClientProbablyOutdated = minAvailableGameVers < minGameVers && maxAvailableGameVers < minGameVers; - }else { - gameProtocolVersion = gameVers; - } - } - - if(versMisMatch) { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); - - buf.writeShort((conf.isAllowV3() ? 2 : 0) + (conf.isAllowV4() ? 1 : 0)); - if(conf.isAllowV3()) { - buf.writeShort(2); - buf.writeShort(3); - } - if(conf.isAllowV4()) { - buf.writeShort(4); - } - - buf.writeShort(2); - buf.writeShort(minGameVers); - buf.writeShort(maxGameVers); - - String str = isClientProbablyOutdated ? "Outdated Client" : (isServerProbablyOutdated ? "Outdated Server" : "Unsupported Client Version"); - buf.writeByte(str.length()); - buf.writeCharSequence(str, StandardCharsets.US_ASCII); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(ChannelFutureListener.CLOSE); - return; - } - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Legacy protocol version should always be '2' on post-snapshot clients") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - int strlen = buffer.readUnsignedByte(); - String eaglerBrand = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedByte(); - String eaglerVersionString = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - - if(eaglerLegacyProtocolVersion >= 2) { - clientAuth = buffer.readBoolean(); - strlen = buffer.readUnsignedByte(); - clientAuthUsername = new byte[strlen]; - buffer.readBytes(clientAuthUsername); - } - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - boolean useSnapshotFallbackProtocol = false; - if(eaglerLegacyProtocolVersion == 1 && !authConfig.isEnableAuthentication()) { - clientProtocolVersion = 2; - gameProtocolVersion = 47; - useSnapshotFallbackProtocol = true; - clientAuth = false; - clientAuthUsername = null; - } - - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr == null) { - SocketAddress remoteSocketAddr = ctx.channel().remoteAddress(); - if(remoteSocketAddr instanceof InetSocketAddress) { - addr = ((InetSocketAddress)remoteSocketAddr).getAddress(); - }else { - addr = InetAddress.getLoopbackAddress(); - } - } - - EaglercraftClientBrandEvent brandEvent = new EaglercraftClientBrandEvent(eaglerBrand, eaglerVersionString, - ctx.channel().attr(EaglerPipeline.ORIGIN).get(), clientProtocolVersion, addr); - eaglerXBungee.getProxy().getPluginManager().callEvent(brandEvent); - if(brandEvent.isCancelled()) { - BaseComponent kickReason = brandEvent.getMessage(); - if(kickReason == null) { - kickReason = new TextComponent("End of stream"); - } - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, kickReason) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final boolean final_useSnapshotFallbackProtocol = useSnapshotFallbackProtocol; - Runnable continueThread = () -> { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_VERSION; - clientBrandString = eaglerBrand; - clientVersionString = eaglerVersionString; - - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_VERSION); - - if(final_useSnapshotFallbackProtocol) { - buf.writeByte(1); - }else { - buf.writeShort(clientProtocolVersion); - buf.writeShort(gameProtocolVersion); - } - - String brandStr = eaglerXBungee.getDescription().getName(); - buf.writeByte(brandStr.length()); - buf.writeCharSequence(brandStr, StandardCharsets.US_ASCII); - - String versStr = eaglerXBungee.getDescription().getVersion(); - buf.writeByte(versStr.length()); - buf.writeCharSequence(versStr, StandardCharsets.US_ASCII); - - if(!authConfig.isEnableAuthentication() || !clientAuth) { - buf.writeByte(0); - buf.writeShort(0); - }else { - int meth = getAuthMethodId(authRequireEvent.getUseAuthType()); - - if(meth == -1) { - buf.release(); - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, unsupported AuthMethod: " + authRequireEvent.getUseAuthType()); - return; - } - - buf.writeByte(meth); - - byte[] saltingData = authRequireEvent.getSaltingData(); - if(saltingData != null) { - buf.writeShort(saltingData.length); - buf.writeBytes(saltingData); - }else { - buf.writeShort(0); - } - } - - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - isProtocolExchanged = true; - }; - - authRequireEvent = null; - if(authConfig.isEnableAuthentication()) { - String origin = ctx.channel().attr(EaglerPipeline.ORIGIN).get(); - try { - authRequireEvent = new EaglercraftIsAuthRequiredEvent(conf, remoteAddress, origin, - clientAuth, clientAuthUsername, (reqAuthEvent) -> { - if(authRequireEvent.shouldKickUser()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, authRequireEvent.getKickMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - EaglercraftIsAuthRequiredEvent.AuthResponse resp = authRequireEvent.getAuthRequired(); - if(resp == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, no installed authentication system handled: " + authRequireEvent.toString()); - return; - } - - if(resp == EaglercraftIsAuthRequiredEvent.AuthResponse.DENY) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, authRequireEvent.getKickMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - EaglercraftIsAuthRequiredEvent.AuthMethod type = authRequireEvent.getUseAuthType(); - if(type == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not fully handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, no authentication method provided by handler"); - return; - } - - int typeId = getAuthMethodId(type); - if(typeId == -1) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, unsupported AuthMethod: " + type); - return; - } - - if(!clientAuth && resp == EaglercraftIsAuthRequiredEvent.AuthResponse.REQUIRE) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_AUTHENTICATION_REQUIRED, - HandshakePacketTypes.AUTHENTICATION_REQUIRED + " [" + typeId + "] " + authRequireEvent.getAuthMessage()) - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().info("[" + localAddrString + "]: Displaying authentication screen"); - return; - }else { - if(authRequireEvent.getUseAuthType() == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not fully handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, no authentication method provided by handler"); - return; - } - } - continueThread.run(); - }); - - if(authConfig.isUseBuiltInAuthentication()) { - DefaultAuthSystem authSystem = eaglerXBungee.getAuthService(); - if(authSystem != null) { - authSystem.handleIsAuthRequiredEvent(authRequireEvent); - } - }else { - eaglerXBungee.getProxy().getPluginManager().callEvent(authRequireEvent); - } - - if(!authRequireEvent.isAsyncContinue()) { - authRequireEvent.doDirectContinue(); - } - }catch(Throwable t) { - throw new EventException(t); - } - }else { - continueThread.run(); - } - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_OPENED").addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_REQUEST_LOGIN: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_VERSION) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - - int strlen = buffer.readUnsignedByte(); - clientUsername = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - - if(!clientUsername.equals(clientUsername.replaceAll("[^A-Za-z0-9_]", "_"))) { - sendLoginDenied(ctx, "Invalid characters in username") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientUsername.length() < 3) { - sendLoginDenied(ctx, "Username must be at least 3 characters") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientUsername.length() > 16) { - sendLoginDenied(ctx, "Username must be under 16 characters") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientAuthUsername == null) { - clientAuthUsername = new byte[strlen]; - for(int i = 0; i < strlen; ++i) { - clientAuthUsername[i] = (byte)clientUsername.charAt(i); - } - } - - clientUUID = offlineUUID = EaglerInitialHandler.generateOfflineUUID(clientAuthUsername); - - strlen = buffer.readUnsignedByte(); - clientRequestedServer = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedByte(); - clientAuthPassword = new byte[strlen]; - buffer.readBytes(clientAuthPassword); - - if(clientProtocolVersion >= 4) { - clientEnableCookie = buffer.readBoolean(); - strlen = buffer.readUnsignedByte(); - if(clientEnableCookie && strlen > 0) { - clientCookieData = new byte[strlen]; - buffer.readBytes(clientCookieData); - }else { - if(strlen > 0) { - throw new IllegalArgumentException("Unexpected cookie"); - } - clientCookieData = null; - } - }else { - clientEnableCookie = false; - clientCookieData = null; - } - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - Runnable continueThread = () -> { - - final BungeeCord bungee = BungeeCord.getInstance(); - final ProxiedPlayer oldName = bungee.getPlayer(clientUsername); - if (oldName != null) { - sendLoginDenied(ctx, bungee.getTranslation("already_connected_proxy")).addListener(ChannelFutureListener.CLOSE); - return; - } - - clientLoginState = HandshakePacketTypes.STATE_CLIENT_LOGIN; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ALLOW_LOGIN); - buf.writeByte(clientUsername.length()); - buf.writeCharSequence(clientUsername, StandardCharsets.US_ASCII); - buf.writeLong(clientUUID.getMostSignificantBits()); - buf.writeLong(clientUUID.getLeastSignificantBits()); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - }; - - EaglerXBungee eaglerXBungee = EaglerXBungee.getEagler(); - EaglerAuthConfig authConfig = eaglerXBungee.getConfig().getAuthConfig(); - - if(authConfig.isEnableAuthentication()) { - if(clientAuth && clientAuthPassword.length > 0) { - EaglercraftHandleAuthPasswordEvent handleEvent = new EaglercraftHandleAuthPasswordEvent( - conf, remoteAddress, authRequireEvent.getOriginHeader(), clientAuthUsername, - authRequireEvent.getSaltingData(), clientUsername, clientUUID, - clientAuthPassword, clientEnableCookie, clientCookieData, - authRequireEvent.getUseAuthType(), authRequireEvent.getAuthMessage(), - (Object) authRequireEvent.getAuthAttachment(), clientRequestedServer, - (handleAuthEvent) -> { - - if(handleAuthEvent.getLoginAllowed() != EaglercraftHandleAuthPasswordEvent.AuthResponse.ALLOW) { - sendLoginDenied(ctx, handleAuthEvent.getLoginDeniedMessage()).addListener(ChannelFutureListener.CLOSE); - return; - } - - clientUsername = handleAuthEvent.getProfileUsername(); - clientUUID = handleAuthEvent.getProfileUUID(); - - String texPropOverrideValue = handleAuthEvent.getApplyTexturesPropertyValue(); - if(texPropOverrideValue != null) { - String texPropOverrideSig = handleAuthEvent.getApplyTexturesPropertySignature(); - texturesOverrideProperty = new Property("textures", texPropOverrideValue, texPropOverrideSig); - } - - overrideEaglerToVanillaSkins = handleAuthEvent.isOverrideEaglerToVanillaSkins(); - - continueThread.run(); - }); - - if(authConfig.isUseBuiltInAuthentication()) { - DefaultAuthSystem authSystem = eaglerXBungee.getAuthService(); - if(authSystem != null) { - authSystem.handleAuthPasswordEvent(handleEvent); - } - }else { - eaglerXBungee.getProxy().getPluginManager().callEvent(handleEvent); - } - - if(!handleEvent.isAsyncContinue()) { - handleEvent.doDirectContinue(); - } - }else if(authRequireEvent.getEnableCookieAuth()) { - EaglercraftHandleAuthCookieEvent handleEvent = new EaglercraftHandleAuthCookieEvent( - conf, remoteAddress, authRequireEvent.getOriginHeader(), clientAuthUsername, - clientUsername, clientUUID, clientEnableCookie, clientCookieData, - authRequireEvent.getUseAuthType(), authRequireEvent.getAuthMessage(), - (Object) authRequireEvent.getAuthAttachment(), - clientRequestedServer, (handleAuthEvent) -> { - - EaglercraftHandleAuthCookieEvent.AuthResponse resp = handleAuthEvent.getLoginAllowed(); - - if(resp == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "EaglercraftHandleAuthCookieEvent was not handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().severe("[" + localAddrString + "]: Disconnecting, no installed authentication system handled: " + handleAuthEvent.toString()); - return; - } - - if(resp == EaglercraftHandleAuthCookieEvent.AuthResponse.DENY) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, handleAuthEvent.getLoginDeniedMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - clientUsername = handleAuthEvent.getProfileUsername(); - clientUUID = handleAuthEvent.getProfileUUID(); - - String texPropOverrideValue = handleAuthEvent.getApplyTexturesPropertyValue(); - if(texPropOverrideValue != null) { - String texPropOverrideSig = handleAuthEvent.getApplyTexturesPropertySignature(); - texturesOverrideProperty = new Property("textures", texPropOverrideValue, texPropOverrideSig); - } - - overrideEaglerToVanillaSkins = handleAuthEvent.isOverrideEaglerToVanillaSkins(); - - if(resp == EaglercraftHandleAuthCookieEvent.AuthResponse.ALLOW) { - continueThread.run(); - return; - } - - if(!clientAuth && resp == EaglercraftHandleAuthCookieEvent.AuthResponse.REQUIRE_AUTH) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_AUTHENTICATION_REQUIRED, HandshakePacketTypes.AUTHENTICATION_REQUIRED - + " [" + getAuthMethodId(authRequireEvent.getUseAuthType()) + "] " + authRequireEvent.getAuthMessage()) - .addListener(ChannelFutureListener.CLOSE); - EaglerXBungee.logger().info("[" + localAddrString + "]: Displaying authentication screen"); - return; - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Failed to handle authentication!") - .addListener(ChannelFutureListener.CLOSE); - return; - } - }); - - eaglerXBungee.getProxy().getPluginManager().callEvent(handleEvent); - - if(!handleEvent.isAsyncContinue()) { - handleEvent.doDirectContinue(); - } - }else { - if(authRequireEvent.getAuthRequired() != EaglercraftIsAuthRequiredEvent.AuthResponse.SKIP) { - sendLoginDenied(ctx, "Client provided no authentication code").addListener(ChannelFutureListener.CLOSE); - return; - }else { - continueThread.run(); - } - } - }else { - continueThread.run(); - } - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_CLIENT_VERSION").addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_LOGIN) { - if(clientProtocolVersion <= 3) { - if(profileData.size() >= 12) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_EXCESSIVE_PROFILE_DATA, "Too many profile data packets recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - int strlen = buffer.readUnsignedByte(); - String dataType = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedShort(); - byte[] readData = new byte[strlen]; - buffer.readBytes(readData); - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - if(!profileData.containsKey(dataType)) { - profileData.put(dataType, readData); - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_DUPLICATE_PROFILE_DATA, "Multiple profile data packets of the same type recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - }else { - int count = buffer.readUnsignedByte(); - if(profileData.size() + count > 12) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_EXCESSIVE_PROFILE_DATA, "Too many profile data packets recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - for(int i = 0; i < count; ++i) { - int strlen = buffer.readUnsignedByte(); - String dataType = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedShort(); - byte[] readData = new byte[strlen]; - buffer.readBytes(readData); - if(!profileData.containsKey(dataType)) { - profileData.put(dataType, readData); - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_DUPLICATE_PROFILE_DATA, "Multiple profile data packets of the same type recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - } - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - } - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_CLIENT_LOGIN").addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_FINISH_LOGIN: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_LOGIN) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - finish(ctx); - - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - }else { - sendErrorWrong(ctx, op, "STATE_CLIENT_LOGIN").addListener(ChannelFutureListener.CLOSE); - } - } - break; - default: - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_UNKNOWN_PACKET, "Unknown Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); - break; - } - }catch(Throwable ex) { - if(ex instanceof EventException) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + localAddrString + "]: Hanshake packet " + op + " caught an exception", ex.getCause()); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_INVALID_PACKET, op == -1 ? - "Invalid Packet" : "Invalid Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); - } - } - - private void finish(final ChannelHandlerContext ctx) { - final BungeeCord bungee = BungeeCord.getInstance(); - - // verify player counts a second time after handshake just to be safe - int limit = bungee.config.getPlayerLimit(); - if (limit > 0 && bungee.getOnlineCount() >= limit) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, bungee.getTranslation("proxy_full")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(conf.getMaxPlayer() > 0) { - int i = 0; - for(ProxiedPlayer p : bungee.getPlayers()) { - if(p.getPendingConnection().getListener() == conf) { - ++i; - } - } - - if (i >= conf.getMaxPlayer()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, bungee.getTranslation("proxy_full")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - } - - final String usernameStr = clientUsername.toString(); - final ProxiedPlayer oldName = bungee.getPlayer(usernameStr); - if (oldName != null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - bungee.getTranslation("already_connected_proxy")).addListener(ChannelFutureListener.CLOSE); - return; - } - final EaglerChannelWrapper ch = new EaglerChannelWrapper(ctx); - InetSocketAddress baseAddress = (InetSocketAddress)ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr != null) { - baseAddress = new InetSocketAddress(addr, baseAddress.getPort()); - ch.setRemoteAddress(baseAddress); - } - - EaglerUpdateConfig updateconf = EaglerXBungee.getEagler().getConfig().getUpdateConfig(); - boolean blockUpdate = updateconf.isBlockAllClientUpdates(); - ClientCertificateHolder cert = null; - if(!blockUpdate && !updateconf.isDiscardLoginPacketCerts()) { - byte[] b = profileData.get("update_cert_v1"); - if(b != null && b.length < 32759) { - EaglerUpdateSvc.sendCertificateToPlayers(cert = EaglerUpdateSvc.tryMakeHolder(b)); - } - } - UUID clientBrandUUID = null; - String clientBrandAsString = clientBrandString.toString(); - byte[] brandUUIDBytes = profileData.get("brand_uuid_v1"); - if(brandUUIDBytes != null) { - if(brandUUIDBytes.length == 16) { - ByteBuf buf = Unpooled.wrappedBuffer(brandUUIDBytes); - clientBrandUUID = new UUID(buf.readLong(), buf.readLong()); - if (clientBrandUUID.equals(EaglerXBungeeAPIHelper.BRAND_NULL_UUID) - || clientBrandUUID.equals(EaglerXBungeeAPIHelper.BRAND_PENDING_UUID) - || clientBrandUUID.equals(EaglerXBungeeAPIHelper.BRAND_VANILLA_UUID)) { - clientBrandUUID = null; - } - } - }else { - clientBrandUUID = EaglerXBungeeAPIHelper.makeClientBrandUUIDLegacy(clientBrandAsString); - } - Map otherProfileData = new HashMap<>(); - for(Entry etr2 : profileData.entrySet()) { - String str = etr2.getKey(); - if(!profileDataStandard.contains(str)) { - otherProfileData.put(str, etr2.getValue()); - } - } - final EaglerInitialHandler initialHandler = new EaglerInitialHandler(bungee, conf, ch, clientProtocolVersion, - gameProtocolVersion, clientBrandAsString, clientVersionString.toString(), clientBrandUUID, - usernameStr, clientUUID, offlineUUID, baseAddress, ctx.channel().attr(EaglerPipeline.HOST).get(), - ctx.channel().attr(EaglerPipeline.ORIGIN).get(), ctx.channel().attr(EaglerPipeline.USER_AGENT).get(), - cert, clientEnableCookie, clientCookieData, otherProfileData); - if(!blockUpdate) { - List set = EaglerUpdateSvc.getCertList(); - synchronized(set) { - initialHandler.certificatesToSend.addAll(set); - } - for(ProxiedPlayer p : bungee.getPlayers()) { - if(p.getPendingConnection() instanceof EaglerInitialHandler) { - EaglerInitialHandler pp = (EaglerInitialHandler)p.getPendingConnection(); - if(pp.clientCertificate != null && pp.clientCertificate != cert) { - initialHandler.certificatesToSend.add(pp.clientCertificate); - } - } - } - } - final Callback complete = (Callback) new Callback() { - public void done(final LoginEvent result, final Throwable error) { - if (result.isCancelled()) { - final BaseComponent reason = result.getReason(); - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - reason != null ? reason : TextComponent.fromLegacy(bungee.getTranslation("kick_message"))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - if (!ctx.channel().isActive()) { - return; - } - - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_FINISH_LOGIN); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(new GenericFutureListener>() { - - @Override - public void operationComplete(Future var1) throws Exception { - EaglerConnectionInstance eaglerCon = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - - EaglerXBungee.logger().info("[" + ctx.channel().remoteAddress() + "]: Logged in as '" + usernameStr + "'"); - - final UserConnection userCon = new UserConnection(bungee, ch, usernameStr, initialHandler); - userCon.setCompressionThreshold(-1); - initialHandler.messageProtocolController = new GameProtocolMessageController(userCon, - GamePluginMessageProtocol.getByVersion(clientProtocolVersion), - GameProtocolMessageController.createServerHandler(clientProtocolVersion, userCon, - EaglerXBungee.getEagler()), conf.getDefragSendDelay()); - try { - if (!userCon.init()) { - userCon.disconnect(bungee.getTranslation("already_connected_proxy")); - EaglerPipeline.closeChannel(ctx.channel()); - return; - } - } catch (NoSuchMethodError e) { - UserConnection.class.getDeclaredMethod("init").invoke(userCon); - } - - ChannelPipeline pp = ctx.channel().pipeline(); - - HandlerBoss handler = new HandlerBoss() { - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - EaglerPipeline.closeChannel(ctx.channel()); - } - }; - handler.setHandler(new UpstreamBridge(bungee, userCon)); - try { - handler.channelActive(ctx); - } catch (Exception e) { - } - - pp.replace(HttpWebSocketHandler.this, "HandlerBoss", handler); - - pp.addBefore("HandlerBoss", "ReadTimeoutHandler", new ReadTimeoutHandler((BungeeCord.getInstance()).config.getTimeout(), TimeUnit.MILLISECONDS)); - - pp.addBefore("HandlerBoss", "EaglerMinecraftDecoder", new EaglerMinecraftDecoder(Protocol.GAME, false, gameProtocolVersion)); - - pp.addBefore("HandlerBoss", "EaglerMinecraftByteBufEncoder", new EaglerMinecraftByteBufEncoder()); - - pp.addBefore("HandlerBoss", "EaglerMinecraftWrappedEncoder", new EaglerMinecraftWrappedEncoder()); - - pp.addBefore("HandlerBoss", "EaglerMinecraftEncoder", new EaglerMinecraftEncoder(Protocol.GAME, true, gameProtocolVersion)); - - boolean doRegisterSkins = true; - boolean doForceSkins = false; - - EaglercraftRegisterSkinEvent registerSkinEvent = new EaglercraftRegisterSkinEvent(usernameStr, clientUUID, authRequireEvent != null ? authRequireEvent.getAuthAttachment() : null); - - bungee.getPluginManager().callEvent(registerSkinEvent); - - Property prop = registerSkinEvent.getForceUseMojangProfileProperty(); - boolean useExistingProp = registerSkinEvent.getForceUseLoginResultObjectTextures(); - if(prop != null) { - texturesOverrideProperty = prop; - overrideEaglerToVanillaSkins = true; - if(clientProtocolVersion >= 4 && (EaglerXBungee.getEagler().getSkinService() instanceof SkinService)) { - doForceSkins = true; - } - }else { - if(useExistingProp) { - overrideEaglerToVanillaSkins = true; - }else { - byte[] custom = registerSkinEvent.getForceSetUseCustomPacket(); - if(custom != null) { - profileData.remove("skin_v2"); - profileData.put("skin_v1", custom); - overrideEaglerToVanillaSkins = false; - if(clientProtocolVersion >= 4) { - doForceSkins = true; - } - } - } - } - - EaglerBungeeConfig eaglerConf = EaglerXBungee.getEagler().getConfig(); - - if(texturesOverrideProperty != null) { - LoginResult oldProfile = initialHandler.getLoginProfile(); - if(oldProfile == null) { - oldProfile = new LoginResult(initialHandler.getUniqueId().toString(), initialHandler.getName(), null); - initialHandler.setLoginProfile(oldProfile); - } - oldProfile.setProperties(eaglerConf.getEnableIsEaglerPlayerProperty() ? new Property[] { texturesOverrideProperty, EaglerBungeeConfig.isEaglerProperty } : new Property[] { texturesOverrideProperty }); - }else { - if(!useExistingProp) { - String vanillaSkin = eaglerConf.getEaglerPlayersVanillaSkin(); - if(vanillaSkin != null) { - LoginResult oldProfile = initialHandler.getLoginProfile(); - if(oldProfile == null) { - oldProfile = new LoginResult(initialHandler.getUniqueId().toString(), initialHandler.getName(), null); - initialHandler.setLoginProfile(oldProfile); - } - oldProfile.setProperties(eaglerConf.getEaglerPlayersVanillaSkinProperties()); - } - } - } - - if(overrideEaglerToVanillaSkins) { - LoginResult res = initialHandler.getLoginProfile(); - if(res != null) { - Property[] props = res.getProperties(); - if(props != null) { - for(int i = 0; i < props.length; ++i) { - if("textures".equals(props[i].getName())) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(props[i].getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = SkinService.sanitizeTextureURL(url.getAsString()); - EaglerXBungee.getEagler().getSkinService().registerTextureToPlayerAssociation(urlStr, initialHandler.getUniqueId()); - } - } - doRegisterSkins = false; - if(clientProtocolVersion >= 4) { - doForceSkins = true; - } - }catch(Throwable t) { - } - break; - } - } - } - } - } - - if(doRegisterSkins) { - if(clientProtocolVersion >= 4 && profileData.containsKey("skin_v2")) { - try { - SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v2"), - EaglerXBungee.getEagler().getSkinService(), 4); - } catch (Throwable ex) { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXBungee.getEagler().getSkinService()); - EaglerXBungee.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid skin packet: " + ex.toString()); - } - }else if(profileData.containsKey("skin_v1")) { - try { - SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v1"), - EaglerXBungee.getEagler().getSkinService(), 3); - } catch (Throwable ex) { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXBungee.getEagler().getSkinService()); - EaglerXBungee.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid skin packet: " + ex.toString()); - } - }else { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXBungee.getEagler().getSkinService()); - } - } - if(doForceSkins) { - EaglerXBungee.getEagler().getSkinService().processForceSkin(clientUUID, initialHandler); - } - - EaglercraftRegisterCapeEvent registerCapeEvent = new EaglercraftRegisterCapeEvent(usernameStr, clientUUID, authRequireEvent != null ? authRequireEvent.getAuthAttachment() : null); - - bungee.getPluginManager().callEvent(registerCapeEvent); - - byte[] forceCape = registerCapeEvent.getForceSetUseCustomPacket(); - if(forceCape != null) { - profileData.put("cape_v1", forceCape); - } - - if(profileData.containsKey("cape_v1")) { - try { - CapePackets.registerEaglerPlayer(clientUUID, profileData.get("cape_v1"), - EaglerXBungee.getEagler().getCapeService()); - } catch (Throwable ex) { - CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXBungee.getEagler().getCapeService()); - EaglerXBungee.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid cape packet: " + ex.toString()); - } - }else { - CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXBungee.getEagler().getCapeService()); - } - if(forceCape != null && clientProtocolVersion >= 4) { - EaglerXBungee.getEagler().getCapeService().processForceCape(clientUUID, initialHandler); - } - - if(conf.getEnableVoiceChat()) { - EaglerXBungee.getEagler().getVoiceService().handlePlayerLoggedIn(userCon); - } - - if(clientProtocolVersion >= 4) { - GameMessagePacket pauseMenuPkt = EaglerXBungee.getEagler().getConfig().getPauseMenuConf().getPacket(); - if(pauseMenuPkt != null) { - initialHandler.sendEaglerMessage(pauseMenuPkt); - } - } - - ServerInfo server; - if (bungee.getReconnectHandler() != null) { - server = bungee.getReconnectHandler().getServer((ProxiedPlayer) userCon); - } else { - server = AbstractReconnectHandler.getForcedHost(initialHandler); - } - - if (server == null) { - server = bungee.getServerInfo(conf.getDefaultServer()); - } - - final ServerInfo server2 = server; - Callback complete = new Callback() { - @Override - public void done(PostLoginEvent result, Throwable error) { - eaglerCon.userConnection = userCon; - eaglerCon.hasBeenForwarded = true; - if (ch.isClosed()) { - return; - } - userCon.connect(server2, null, true, ServerConnectEvent.Reason.JOIN_PROXY); - } - }; - - try { - bungee.getPluginManager().callEvent(new PostLoginEvent(userCon, server, complete)); - }catch(NoSuchMethodError err) { - PostLoginEvent login = PostLoginEvent.class.getDeclaredConstructor(ProxiedPlayer.class).newInstance(userCon); - bungee.getPluginManager().callEvent(login); - complete.done(login, null); - } - } - - }); - } - }; - final Callback completePre = new Callback() { - public void done(PreLoginEvent var1, Throwable var2) { - if (var1.isCancelled()) { - final BaseComponent reason = var1.getReason(); - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - reason != null ? reason : TextComponent.fromLegacy(bungee.getTranslation("kick_message"))) - .addListener(ChannelFutureListener.CLOSE); - }else { - bungee.getPluginManager().callEvent(new LoginEvent(initialHandler, complete)); - } - } - }; - bungee.getPluginManager().callEvent(new PreLoginEvent(initialHandler, completePre)); - } - - private static class EventException extends RuntimeException { - public EventException(Throwable t) { - super(t.toString(), t); - } - } - - private void handleText(ChannelHandlerContext ctx, String str) { - if(connectionClosed) { - return; - } - if (!hasFirstPacket && (conf.isAllowMOTD() || conf.isAllowQuery()) && str.length() < 128 - && (str = str.toLowerCase()).startsWith("accept:")) { - str = str.substring(7).trim(); - hasFirstPacket = true; - hasBinaryConnection = false; - - if(CommandConfirmCode.confirmHash != null && str.equalsIgnoreCase(CommandConfirmCode.confirmHash)) { - connectionClosed = true; - ctx.writeAndFlush(new TextWebSocketFrame("OK")).addListener(ChannelFutureListener.CLOSE); - CommandConfirmCode.confirmHash = null; - return; - } - - boolean isMOTD = str.startsWith("motd"); - - SocketAddress localSocketAddr = ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - - String limiterAddress = null; - RateLimitStatus queryRateLimit = RateLimitStatus.OK; - if(addr != null) { - limiterAddress = addr.getHostAddress(); - }else { - if(localSocketAddr instanceof InetSocketAddress) { - limiterAddress = ((InetSocketAddress)localSocketAddr).getAddress().getHostAddress(); - } - } - - EaglerRateLimiter limiter = isMOTD ? conf.getRatelimitMOTD() : conf.getRatelimitQuery(); - if(limiterAddress != null && limiter != null) { - queryRateLimit = limiter.rateLimit(limiterAddress); - } - - if(queryRateLimit == RateLimitStatus.LOCKED_OUT) { - connectionClosed = true; - ctx.close(); - return; - } - - if(queryRateLimit != RateLimitStatus.OK) { - connectionClosed = true; - final RateLimitStatus rateLimitTypeFinal = queryRateLimit; - ctx.writeAndFlush(new TextWebSocketFrame( - rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "{\"type\":\"locked\"}" : "{\"type\":\"blocked\"}")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - HttpServerQueryHandler handler = null; - if(isMOTD) { - if(conf.isAllowMOTD()) { - handler = new MOTDQueryHandler(); - } - }else if(conf.isAllowQuery()) { - handler = QueryManager.createQueryHandler(str); - } - if(handler != null) { - ctx.pipeline().replace(HttpWebSocketHandler.this, "HttpServerQueryHandler", handler); - ctx.pipeline().addBefore("HttpServerQueryHandler", "WriteTimeoutHandler", new WriteTimeoutHandler(5l, TimeUnit.SECONDS)); - ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().hasBeenForwarded = true; - handler.beginHandleQuery(conf, ctx, str); - if(handler instanceof MOTDQueryHandler) { - EaglercraftMOTDEvent evt = new EaglercraftMOTDEvent((MOTDQueryHandler)handler); - BungeeCord.getInstance().getPluginManager().callEvent(evt); - if(!handler.isClosed()) { - ((MOTDQueryHandler)handler).sendToUser(); - } - } - if(!handler.isClosed() && !handler.shouldKeepAlive()) { - connectionClosed = true; - handler.close(); - }else { - ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().queryHandler = handler; - } - }else { - connectionClosed = true; - ctx.close(); - } - }else { - connectionClosed = true; - ctx.close(); - return; - } - } - - private int getAuthMethodId(EaglercraftIsAuthRequiredEvent.AuthMethod meth) { - switch(meth) { - case PLAINTEXT: - return 255; // plaintext authentication - case EAGLER_SHA256: - return 1; // eagler_sha256 authentication - case AUTHME_SHA256: - return 2; // authme_sha256 authentication - default: - return -1; - } - } - - private ChannelFuture sendLoginDenied(ChannelHandlerContext ctx, String reason) { - if((!isProtocolExchanged || clientProtocolVersion == 2) && reason.length() > 255) { - reason = reason.substring(0, 255); - }else if(reason.length() > 65535) { - reason = reason.substring(0, 65535); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_DENY_LOGIN); - byte[] msg = reason.getBytes(StandardCharsets.UTF_8); - if(!isProtocolExchanged || clientProtocolVersion == 2) { - buf.writeByte(msg.length); - }else { - buf.writeShort(msg.length); - } - buf.writeBytes(msg); - return ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - } - - private ChannelFuture sendErrorWrong(ChannelHandlerContext ctx, int op, String state) { - return sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_WRONG_PACKET, "Wrong Packet #" + op + " in state '" + state + "'"); - } - - private ChannelFuture sendErrorCode(ChannelHandlerContext ctx, int code, BaseComponent comp) { - if((!isProtocolExchanged || clientProtocolVersion == 2)) { - return sendErrorCode(ctx, code, ComponentSerializer.toString(comp)); - }else { - return sendErrorCode(ctx, code, comp.toLegacyText()); - } - } - - private ChannelFuture sendErrorCode(ChannelHandlerContext ctx, int code, String str) { - if((!isProtocolExchanged || clientProtocolVersion == 2) && str.length() > 255) { - str = str.substring(0, 255); - }else if(str.length() > 65535) { - str = str.substring(0, 65535); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ERROR); - buf.writeByte(code); - byte[] msg = str.getBytes(StandardCharsets.UTF_8); - if(!isProtocolExchanged || clientProtocolVersion == 2) { - buf.writeByte(msg.length); - }else { - buf.writeShort(msg.length); - } - buf.writeBytes(msg); - return ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - } - - public void channelInactive(ChannelHandlerContext ctx) { - connectionClosed = true; - EaglerPipeline.closeChannel(ctx.channel()); - } - - private void handleLegacyClient(ChannelHandlerContext ctx, ByteBuf buffer) { - connectionClosed = true; - ByteBuf kickMsg = ctx.alloc().buffer(); - final String redir = conf.redirectLegacyClientsTo(); - if(redir != null) { - writeLegacyRedirect(kickMsg, redir); - }else { - writeLegacyKick(kickMsg, "This is an EaglercraftX 1.8 server, it is not compatible with 1.5.2!"); - } - ctx.writeAndFlush(new BinaryWebSocketFrame(kickMsg)).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture var1) throws Exception { - ctx.channel().eventLoop().schedule(new Runnable() { - @Override - public void run() { - ctx.close(); - } - }, redir != null ? 100l : 500l, TimeUnit.MILLISECONDS); - } - }); - } - - public static void writeLegacyKick(ByteBuf buffer, String message) { - buffer.writeByte(0xFF); - buffer.writeShort(message.length()); - for(int i = 0, l = message.length(), j; i < l; ++i) { - j = message.charAt(i); - buffer.writeByte((j >>> 8) & 0xFF); - buffer.writeByte(j & 0xFF); - } - } - - public static void writeLegacyRedirect(ByteBuf buffer, String redirect) { - buffer.writeBytes(legacyRedirectHeader); - byte[] redirect_ = redirect.getBytes(StandardCharsets.UTF_8); - buffer.writeByte((redirect_.length >>> 8) & 0xFF); - buffer.writeByte(redirect_.length & 0xFF); - buffer.writeBytes(redirect_); - } - - private static final byte[] legacyRedirectHeader; - - static { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bao); - try { - // Packet1Login - dos.writeByte(0x01); - dos.writeInt(0); - dos.writeShort(0); - dos.writeByte(0); - dos.writeByte(0); - dos.writeByte(0xFF); - dos.writeByte(0); - dos.writeByte(0); - // Packet250CustomPayload - dos.writeByte(0xFA); - String channel = "EAG|Reconnect"; - int cl = channel.length(); - dos.writeShort(cl); - for(int i = 0; i < cl; ++i) { - dos.writeChar(channel.charAt(i)); - } - }catch(IOException ex) { - throw new ExceptionInInitializerError(ex); - } - legacyRedirectHeader = bao.toByteArray(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/BackendRPCSessionHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/BackendRPCSessionHandler.java deleted file mode 100644 index 6c6337bd..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/BackendRPCSessionHandler.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; - -import org.apache.commons.lang3.ArrayUtils; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.WrongRPCPacketException; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCEnabled; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCSubscribeEvents; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledFailure; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledSuccess; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewOpenClose; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayInputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayOutputStream; -import net.md_5.bungee.ServerConnection; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.connection.Server; - -public class BackendRPCSessionHandler { - - public static BackendRPCSessionHandler createForPlayer(EaglerInitialHandler eaglerHandler) { - return new BackendRPCSessionHandler(eaglerHandler); - } - - protected final EaglerInitialHandler eaglerHandler; - private Server currentServer = null; - private String channelName = null; - private EaglerBackendRPCProtocol currentProtocol = null; - private EaglerBackendRPCHandler currentHandler = null; - private int subscribedEvents = 0; - private final AtomicInteger currentVoiceState = new AtomicInteger(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - private final ReentrantLock inputStreamLock = new ReentrantLock(); - private final ReentrantLock outputStreamLock = new ReentrantLock(); - private final ReusableByteArrayInputStream reusableInputStream = new ReusableByteArrayInputStream(); - private final ReusableByteArrayOutputStream reusableOutputStream = new ReusableByteArrayOutputStream(); - private final DataInputStream dataInputStream = new DataInputStream(reusableInputStream); - private final DataOutputStream dataOutputStream = new DataOutputStream(reusableOutputStream); - - private BackendRPCSessionHandler(EaglerInitialHandler eaglerHandler) { - this.eaglerHandler = eaglerHandler; - } - - public void handleRPCPacket(Server server, byte[] data) { - synchronized(this) { - if(currentServer != null) { - if(currentServer != server) { - return; - } - }else { - handleCreateContext(server, data); - return; - } - } - EaglerBackendRPCPacket packet; - try { - packet = decodeRPCPacket(currentProtocol, data); - } catch (IOException e) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + eaglerHandler.getSocketAddress() - + "]: Recieved invalid backend RPC protocol packet for user \"" + eaglerHandler.getName() + "\"", e); - return; - } - packet.handlePacket(currentHandler); - } - - protected EaglerBackendRPCPacket decodeRPCPacket(EaglerBackendRPCProtocol protocol, byte[] data) throws IOException { - EaglerBackendRPCPacket ret; - if(inputStreamLock.tryLock()) { - try { - reusableInputStream.feedBuffer(data); - ret = protocol.readPacket(dataInputStream, EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - }finally { - inputStreamLock.unlock(); - } - }else { - ReusableByteArrayInputStream bai = new ReusableByteArrayInputStream(); - bai.feedBuffer(data); - ret = protocol.readPacket(new DataInputStream(bai), EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - } - return ret; - } - - public void sendRPCPacket(EaglerBackendRPCPacket packet) { - if(currentServer != null) { - sendRPCPacket(currentProtocol, currentServer, packet); - }else { - EaglerXBungee.logger() - .warning("[" + eaglerHandler.getSocketAddress() - + "]: Failed to write backend RPC protocol version for user \"" + eaglerHandler.getName() - + "\", the RPC connection is not initialized!"); - } - } - - protected void sendRPCPacket(EaglerBackendRPCProtocol protocol, Server server, EaglerBackendRPCPacket packet) { - byte[] ret; - int len = packet.length() + 1; - if(outputStreamLock.tryLock()) { - try { - reusableOutputStream.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(dataOutputStream, EaglerBackendRPCProtocol.SERVER_TO_CLIENT, packet); - }catch(IOException ex) { - throw new IllegalStateException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = reusableOutputStream.returnBuffer(); - }finally { - outputStreamLock.unlock(); - } - }else { - ReusableByteArrayOutputStream bao = new ReusableByteArrayOutputStream(); - bao.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(new DataOutputStream(bao), EaglerBackendRPCProtocol.SERVER_TO_CLIENT, packet); - }catch(IOException ex) { - throw new IllegalStateException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = bao.returnBuffer(); - } - if(len > 0 && len != ret.length) { - EaglerXBungee.logger() - .warning("[" + eaglerHandler.getSocketAddress() + "]: Backend RPC packet type " - + packet.getClass().getSimpleName() + " was the wrong length for user \"" - + eaglerHandler.getName() + "\" after serialization: " + ret.length + " != " + len); - } - server.sendData(channelName, ret); - } - - public void handleConnectionLost(ServerInfo server) { - if(currentServer != null) { - handleDestroyContext(); - } - } - - private void handleDestroyContext() { - currentServer = null; - channelName = null; - currentProtocol = null; - currentHandler = null; - subscribedEvents = 0; - } - - private void handleCreateContext(Server server, byte[] data) { - EaglerBackendRPCPacket packet; - try { - packet = decodeRPCPacket(EaglerBackendRPCProtocol.INIT, data); - } catch (IOException e) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + eaglerHandler.getSocketAddress() - + "]: Recieved invalid backend RPC protocol handshake for user \"" + eaglerHandler.getName() + "\"", e); - return; - } - if(!(packet instanceof CPacketRPCEnabled)) { - throw new WrongRPCPacketException(); - } - channelName = getChNameFor((ServerConnection)server); - if(!ArrayUtils.contains(((CPacketRPCEnabled)packet).supportedProtocols, EaglerBackendRPCProtocol.V1.vers)) { - EaglerXBungee.logger().severe("[" + eaglerHandler.getSocketAddress() - + "]: Unsupported backend RPC protocol version for user \"" + eaglerHandler.getName() + "\""); - sendRPCPacket(EaglerBackendRPCProtocol.INIT, server, new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_SERVER)); - return; - } - sendRPCPacket(EaglerBackendRPCProtocol.INIT, server, new SPacketRPCEnabledSuccess(EaglerBackendRPCProtocol.V1.vers, eaglerHandler.getEaglerProtocolHandshake())); - currentServer = server; - currentProtocol = EaglerBackendRPCProtocol.V1; - currentHandler = new ServerV1RPCProtocolHandler(this, server, eaglerHandler); - } - - public static void handlePacketOnVanilla(Server server, UserConnection player, byte[] data) { - EaglerBackendRPCPacket packet; - try { - packet = EaglerBackendRPCProtocol.INIT.readPacket(new DataInputStream(new ByteArrayInputStream(data)), EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - } catch (IOException e) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + player.getSocketAddress() - + "]: Recieved invalid backend RPC protocol handshake for user \"" + player.getName() + "\"", e); - EaglerXBungee.logger().severe("(Note: this player is not using Eaglercraft!)"); - return; - } - if(!(packet instanceof CPacketRPCEnabled)) { - throw new WrongRPCPacketException(); - } - if(!ArrayUtils.contains(((CPacketRPCEnabled)packet).supportedProtocols, EaglerBackendRPCProtocol.V1.vers)) { - EaglerXBungee.logger().severe("[" + player.getSocketAddress() - + "]: Unsupported backend RPC protocol version for user \"" + player.getName() + "\""); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - EaglerBackendRPCProtocol.INIT.writePacket(new DataOutputStream(bao), - EaglerBackendRPCProtocol.SERVER_TO_CLIENT, - new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_SERVER)); - }catch(IOException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + player.getSocketAddress() - + "]: Failed to write backend RPC protocol version for user \"" + player.getName() + "\"", ex); - EaglerXBungee.logger().severe("(Note: this player is not using Eaglercraft!)"); - return; - } - server.sendData(getChNameFor((ServerConnection)server), bao.toByteArray()); - return; - } - EaglerXBungee.logger().warning("[" + player.getSocketAddress() - + "]: Tried to open backend RPC protocol connection for non-eagler player \"" + player.getName() + "\""); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - EaglerBackendRPCProtocol.INIT.writePacket(new DataOutputStream(bao), - EaglerBackendRPCProtocol.SERVER_TO_CLIENT, - new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_NOT_EAGLER_PLAYER)); - }catch(IOException ex) { - EaglerXBungee.logger().log(Level.SEVERE, "[" + player.getSocketAddress() - + "]: Failed to write backend RPC protocol version for user \"" + player.getName() + "\"", ex); - return; - } - server.sendData(getChNameFor((ServerConnection)server), bao.toByteArray()); - } - - public void setSubscribedEvents(int eventsToEnable) { - int oldSubscribedEvents = subscribedEvents; - subscribedEvents = eventsToEnable; - if ((oldSubscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) == 0 - && (eventsToEnable & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0) { - currentVoiceState.set(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - VoiceService svc = EaglerXBungee.getEagler().getVoiceService(); - if(svc != null && eaglerHandler.getEaglerListenerConfig().getEnableVoiceChat()) { - EnumVoiceState state = svc.getPlayerVoiceState(eaglerHandler.getUniqueId(), currentServer.getInfo()); - if(state == EnumVoiceState.DISABLED) { - handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - }else if(state == EnumVoiceState.ENABLED) { - handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_ENABLED); - } - } - } - if ((oldSubscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) == 0 - && (eventsToEnable & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) != 0) { - if(eaglerHandler.webViewMessageChannelOpen.get()) { - sendRPCPacket(new SPacketRPCEventWebViewOpenClose(true, eaglerHandler.webViewMessageChannelName)); - } - } - if ((eventsToEnable & ~(CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE - | CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_MESSAGE - | CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE)) != 0) { - EaglerXBungee.logger() - .severe("[" + eaglerHandler.getSocketAddress() + "]: Unsupported events were subscribed to for \"" - + eaglerHandler.getName() + "\" via backend RPC protocol, bitfield: " + subscribedEvents); - } - } - - public boolean isSubscribed(EnumSubscribedEvent eventType) { - switch(eventType) { - case WEBVIEW_OPEN_CLOSE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) != 0; - case WEBVIEW_MESSAGE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_MESSAGE) != 0; - case TOGGLE_VOICE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0; - default: - return false; - } - } - - public void handleDisabled() { - handleDestroyContext(); - } - - public void handleVoiceStateTransition(int voiceState) { - if((subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0) { - int oldState = currentVoiceState.getAndSet(voiceState); - if(oldState != voiceState) { - sendRPCPacket(new SPacketRPCEventToggledVoice(oldState, voiceState)); - } - } - } - - private static int getVerSafe(ServerConnection server) { - try { - return server.getCh().getEncodeVersion(); - }catch(Throwable t) { - return -1; - } - } - - public static String getChNameFor(ServerConnection server) { - return (EaglerXBungee.getEagler().getConfig().getUseModernizedChannelNames() || getVerSafe(server) >= 393) - ? EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN - : EaglerBackendRPCProtocol.CHANNEL_NAME; - } - - public static String getReadyChNameFor(ServerConnection server) { - return (EaglerXBungee.getEagler().getConfig().getUseModernizedChannelNames() || getVerSafe(server) >= 393) - ? EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN - : EaglerBackendRPCProtocol.CHANNEL_NAME_READY; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/EnumSubscribedEvent.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/EnumSubscribedEvent.java deleted file mode 100644 index 4bc09ea7..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/EnumSubscribedEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol; - -public enum EnumSubscribedEvent { - WEBVIEW_OPEN_CLOSE, - WEBVIEW_MESSAGE, - TOGGLE_VOICE; -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java deleted file mode 100644 index ae79c5bf..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.RandomAccess; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumWebViewState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerPauseMenuConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeHideV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsRegisterV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsReleaseV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.api.connection.Server; - -public class ServerV1RPCProtocolHandler implements EaglerBackendRPCHandler { - - protected final BackendRPCSessionHandler sessionHandler; - protected final Server server; - protected final EaglerInitialHandler eaglerHandler; - - public ServerV1RPCProtocolHandler(BackendRPCSessionHandler sessionHandler, Server server, EaglerInitialHandler eaglerHandler) { - this.sessionHandler = sessionHandler; - this.server = server; - this.eaglerHandler = eaglerHandler; - } - - public void handleClient(CPacketRPCRequestPlayerInfo packet) { - switch(packet.requestType) { - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_UUID: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeUUID(packet.requestID, eaglerHandler.getUniqueId())); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_IP: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, ((InetSocketAddress)eaglerHandler.getSocketAddress()).getAddress().getHostAddress())); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_ORIGIN: { - String origin = eaglerHandler.getOrigin(); - if(origin != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, origin)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_USER_AGENT: { - String userAgent = eaglerHandler.getUserAgent(); - if(userAgent != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, userAgent)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_SKIN_DATA: { - SkinPacketVersionCache skinData = EaglerXBungee.getEagler().getSkinService().getSkin(eaglerHandler.getUniqueId()); - if(skinData != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeBytes(packet.requestID, skinData.getV3HandshakeData())); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CAPE_DATA: { - byte[] capeData = EaglerXBungee.getEagler().getCapeService().getCapeHandshakeData(eaglerHandler.getUniqueId()); - if(capeData != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeBytes(packet.requestID, capeData)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_COOKIE: { - boolean cookieEnabled = eaglerHandler.getCookieAllowed(); - byte[] cookieData = cookieEnabled ? eaglerHandler.getCookieData() : null; - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeCookie(packet.requestID, cookieEnabled, cookieData)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_STR: { - String clientBrandStr = eaglerHandler.getEaglerBrandString(); - if(clientBrandStr != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, clientBrandStr)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VERSION_STR: { - String clientVersionStr = eaglerHandler.getEaglerVersionString(); - if(clientVersionStr != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, clientVersionStr)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_VERSION_STR: { - String clientBrandStr = eaglerHandler.getEaglerBrandString(); - String clientVersionStr = eaglerHandler.getEaglerVersionString(); - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, "" + clientBrandStr + " " + clientVersionStr)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_UUID: { - UUID brandUUID = eaglerHandler.getClientBrandUUID(); - if(brandUUID != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeUUID(packet.requestID, brandUUID)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VOICE_STATUS: { - int voiceState; - VoiceService svc = EaglerXBungee.getEagler().getVoiceService(); - if(svc != null && eaglerHandler.getEaglerListenerConfig().getEnableVoiceChat()) { - EnumVoiceState enumVoiceState = svc.getPlayerVoiceState(eaglerHandler.getUniqueId(), server.getInfo()); - switch(enumVoiceState) { - case SERVER_DISABLE: - default: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_SERVER_DISABLE; - break; - case DISABLED: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_DISABLED; - break; - case ENABLED: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_ENABLED; - break; - } - }else { - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_SERVER_DISABLE; - } - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeVoiceStatus(packet.requestID, voiceState)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_WEBVIEW_STATUS: { - EnumWebViewState enumWebViewState = eaglerHandler.getWebViewState(); - int webViewStatus; - String webViewChannel; - switch(enumWebViewState) { - case NOT_SUPPORTED: - default: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_NOT_SUPPORTED; - webViewChannel = null; - break; - case SERVER_DISABLE: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_SERVER_DISABLE; - webViewChannel = null; - break; - case CHANNEL_CLOSED: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_CLOSED; - webViewChannel = null; - break; - case CHANNEL_OPEN: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_OPEN; - webViewChannel = eaglerHandler.getWebViewMessageChannelName(); - break; - } - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeWebViewStatus(packet.requestID, webViewStatus, webViewChannel)); - } - break; - default: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeError(packet.requestID, "Unknown request type: " + packet.requestType)); - } - break; - } - } - - public void handleClient(CPacketRPCSubscribeEvents packet) { - sessionHandler.setSubscribedEvents(packet.eventsToEnable); - } - - public void handleClient(CPacketRPCSetPlayerSkin packet) { - try { - byte[] bs = packet.skinPacket; - if(bs.length < 5) { - throw new IOException(); - } - if(bs[0] == (byte)1) { - if(bs.length != 5) { - throw new IOException(); - } - EaglerXBungeeAPIHelper.changePlayerSkinPreset(EaglerXBungeeAPIHelper.getPlayer(eaglerHandler), - (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF), packet.notifyOthers); - }else if(bs[0] == (byte)2) { - if(bs.length < 2) { - throw new IOException(); - } - byte[] cust = new byte[bs.length - 2]; - System.arraycopy(bs, 2, cust, 0, cust.length); - EaglerXBungeeAPIHelper.changePlayerSkinCustom(EaglerXBungeeAPIHelper.getPlayer(eaglerHandler), - bs[1] & 0xFF, cust, packet.notifyOthers); - }else { - throw new IOException(); - } - }catch(IOException ex) { - EaglerXBungee.logger().severe("[" + eaglerHandler.getSocketAddress() + "]: Invalid CPacketRPCSetPlayerSkin packet recieved for player \"" - + eaglerHandler.getName() + "\" from backend RPC protocol!"); - return; - } - } - - public void handleClient(CPacketRPCSetPlayerCape packet) { - try { - byte[] bs = packet.capePacket; - if(bs.length < 5) { - throw new IOException(); - } - if(bs[0] == (byte)1) { - if(bs.length != 5) { - throw new IOException(); - } - EaglerXBungeeAPIHelper.changePlayerCapePreset(EaglerXBungeeAPIHelper.getPlayer(eaglerHandler), - (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF), packet.notifyOthers); - }else if(bs[0] == (byte)2) { - if(bs.length != 1174) { - throw new IOException(); - } - byte[] cust = new byte[bs.length - 1]; - System.arraycopy(bs, 1, cust, 0, cust.length); - EaglerXBungeeAPIHelper.changePlayerCapeCustom(EaglerXBungeeAPIHelper.getPlayer(eaglerHandler), - cust, true, packet.notifyOthers); - }else { - throw new IOException(); - } - }catch(IOException ex) { - EaglerXBungee.logger().severe("[" + eaglerHandler.getSocketAddress() + "]: Invalid CPacketRPCSetPlayerCape packet recieved for player \"" - + eaglerHandler.getName() + "\" from backend RPC protocol!"); - return; - } - } - - public void handleClient(CPacketRPCSetPlayerCookie packet) { - eaglerHandler.setCookieData(packet.cookieData, packet.expires, packet.revokeQuerySupported, packet.saveToDisk); - } - - public void handleClient(CPacketRPCSetPlayerFNAWEn packet) { - EaglerXBungeeAPIHelper.setEnableForceFNAWSkins(eaglerHandler, packet.enable, packet.force); - } - - public void handleClient(CPacketRPCRedirectPlayer packet) { - eaglerHandler.redirectPlayerToWebSocket(packet.redirectURI); - } - - public void handleClient(CPacketRPCResetPlayerMulti packet) { - EaglerXBungeeAPIHelper.resetPlayerMulti(EaglerXBungeeAPIHelper.getPlayer(eaglerHandler), packet.resetSkin, - packet.resetCape, packet.resetFNAWForce, packet.notifyOtherPlayers); - } - - public void handleClient(CPacketRPCSendWebViewMessage packet) { - eaglerHandler.sendWebViewMessage(packet.messageType, packet.messageContent); - } - - public void handleClient(CPacketRPCSetPauseMenuCustom packet) { - if(eaglerHandler.getEaglerProtocol().ver >= 4) { - EaglerPauseMenuConfig defaultConf = EaglerXBungee.getEagler().getConfig().getPauseMenuConf(); - SPacketCustomizePauseMenuV4EAG defaultPacket = defaultConf.getPacket(); - int serverInfoMode = packet.serverInfoMode; - String serverInfoButtonText; - String serverInfoURL; - byte[] serverInfoHash; - int serverInfoEmbedPerms; - String serverInfoEmbedTitle; - if(serverInfoMode == CPacketRPCSetPauseMenuCustom.SERVER_INFO_MODE_INHERIT_DEFAULT) { - serverInfoMode = defaultPacket.serverInfoMode; - serverInfoButtonText = defaultPacket.serverInfoButtonText; - serverInfoURL = defaultPacket.serverInfoURL; - serverInfoHash = defaultPacket.serverInfoHash; - serverInfoEmbedPerms = defaultPacket.serverInfoEmbedPerms; - serverInfoEmbedTitle = defaultPacket.serverInfoEmbedTitle; - }else { - serverInfoButtonText = packet.serverInfoButtonText; - serverInfoURL = packet.serverInfoURL; - serverInfoHash = packet.serverInfoHash; - serverInfoEmbedPerms = packet.serverInfoEmbedPerms; - serverInfoEmbedTitle = packet.serverInfoEmbedTitle; - } - int discordButtonMode = packet.discordButtonMode; - String discordButtonText; - String discordInviteURL; - if(discordButtonMode == CPacketRPCSetPauseMenuCustom.DISCORD_MODE_INHERIT_DEFAULT) { - discordButtonMode = defaultPacket.discordButtonMode; - discordButtonText = defaultPacket.discordButtonText; - discordInviteURL = defaultPacket.discordInviteURL; - }else { - discordButtonText = packet.discordButtonText; - discordInviteURL = packet.discordInviteURL; - } - Map imageMappings = packet.imageMappings; - List imageData = packet.imageData; - List imageDataConv = imageData != null - ? new ArrayList<>(imageData.size()) : null; - if(imageDataConv != null) { - for(int i = 0, l = imageData.size(); i < l; ++i) { - PacketImageData etr = imageData.get(i); - imageDataConv.add(new net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData - (etr.width, etr.height, etr.rgba)); - } - } - eaglerHandler.sendEaglerMessage(new SPacketCustomizePauseMenuV4EAG(serverInfoMode, serverInfoButtonText, - serverInfoURL, serverInfoHash, serverInfoEmbedPerms, serverInfoEmbedTitle, discordButtonMode, - discordButtonText, discordInviteURL, imageMappings, imageDataConv)); - }else { - EaglerXBungee.logger().warning("[" + eaglerHandler.getSocketAddress() - + "]: Recieved packet CPacketRPCSetPauseMenuCustom for player \"" + eaglerHandler.getName() - + "\" from backend RPC protocol, but their client does not support pause menu customization!"); - } - } - - public void handleClient(CPacketRPCNotifIconRegister packet) { - if(eaglerHandler.notificationSupported()) { - List createIconsConv = new ArrayList<>(packet.notifIcons.size()); - for(Entry etr : packet.notifIcons.entrySet()) { - UUID uuid = etr.getKey(); - PacketImageData imgData = etr.getValue(); - createIconsConv.add(new SPacketNotifIconsRegisterV4EAG.CreateIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), new net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData - (imgData.width, imgData.height, imgData.rgba))); - } - eaglerHandler.sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG(createIconsConv)); - }else { - EaglerXBungee.logger().warning("[" + eaglerHandler.getSocketAddress() - + "]: Recieved packet CPacketRPCNotifIconRegister for player \"" + eaglerHandler.getName() - + "\" from backend RPC protocol, but their client does not support notifications!"); - } - } - - public void handleClient(CPacketRPCNotifIconRelease packet) { - if(eaglerHandler.notificationSupported()) { - List destroyIconsConv = new ArrayList<>(packet.iconsToRelease.size()); - if(packet.iconsToRelease instanceof RandomAccess) { - List lst = (List)packet.iconsToRelease; - for(int i = 0, l = lst.size(); i < l; ++i) { - UUID uuid = lst.get(i); - destroyIconsConv.add(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())); - } - }else { - for(UUID uuid : packet.iconsToRelease) { - destroyIconsConv.add(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())); - } - } - eaglerHandler.sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG(destroyIconsConv)); - }else { - EaglerXBungee.logger().warning("[" + eaglerHandler.getSocketAddress() - + "]: Recieved packet CPacketRPCNotifIconRelease for player \"" + eaglerHandler.getName() - + "\" from backend RPC protocol, but their client does not support notifications!"); - } - } - - public void handleClient(CPacketRPCNotifBadgeShow packet) { - if(eaglerHandler.notificationSupported()) { - SPacketNotifBadgeShowV4EAG.EnumBadgePriority translatedEnum; - switch(packet.priority) { - case LOW: - default: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.LOW; - break; - case NORMAL: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.NORMAL; - break; - case HIGHER: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.HIGHER; - break; - case HIGHEST: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.HIGHEST; - break; - } - eaglerHandler.sendEaglerMessage(new SPacketNotifBadgeShowV4EAG(packet.badgeUUID.getMostSignificantBits(), - packet.badgeUUID.getLeastSignificantBits(), packet.bodyComponent, packet.titleComponent, - packet.sourceComponent, packet.originalTimestampSec, packet.silent, translatedEnum, - (packet.mainIconUUID != null ? packet.mainIconUUID.getMostSignificantBits() : 0l), - (packet.mainIconUUID != null ? packet.mainIconUUID.getLeastSignificantBits() : 0l), - (packet.titleIconUUID != null ? packet.titleIconUUID.getMostSignificantBits() : 0l), - (packet.titleIconUUID != null ? packet.titleIconUUID.getLeastSignificantBits() : 0l), - packet.hideAfterSec, packet.expireAfterSec, packet.backgroundColor, packet.bodyTxtColor, - packet.titleTxtColor, packet.sourceTxtColor)); - }else { - EaglerXBungee.logger().warning("[" + eaglerHandler.getSocketAddress() - + "]: Recieved packet CPacketRPCNotifBadgeShow for player \"" + eaglerHandler.getName() - + "\" from backend RPC protocol, but their client does not support notifications!"); - } - } - - public void handleClient(CPacketRPCNotifBadgeHide packet) { - if(eaglerHandler.notificationSupported()) { - eaglerHandler.sendEaglerMessage(new SPacketNotifBadgeHideV4EAG(packet.badgeUUID.getMostSignificantBits(), - packet.badgeUUID.getLeastSignificantBits())); - }else { - EaglerXBungee.logger().warning("[" + eaglerHandler.getSocketAddress() - + "]: Recieved packet CPacketRPCNotifBadgeHide for player \"" + eaglerHandler.getName() - + "\" from backend RPC protocol, but their client does not support notifications!"); - } - } - - public void handleClient(CPacketRPCDisabled packet) { - sessionHandler.handleDisabled(); - } - - public void handleClient(CPacketRPCSendRawMessage packet) { - eaglerHandler.getEaglerMessageController().getUserConnection().sendData(packet.messageChannel, packet.messageData); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java deleted file mode 100644 index 4b898ebe..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol; - -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.concurrent.ScheduledFuture; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePacketOutputBuffer; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayInputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayOutputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleInputBufferImpl; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleOutputBufferImpl; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.protocol.DefinedPacket; - -public class GameProtocolMessageController { - - public final GamePluginMessageProtocol protocol; - public final GameMessageHandler handler; - private final ReusableByteArrayInputStream byteInputStreamSingleton = new ReusableByteArrayInputStream(); - private final ReusableByteArrayOutputStream byteOutputStreamSingleton = new ReusableByteArrayOutputStream(); - private final SimpleInputBufferImpl inputStreamSingleton = new SimpleInputBufferImpl(byteInputStreamSingleton); - private final SimpleOutputBufferImpl outputStreamSingleton = new SimpleOutputBufferImpl(byteOutputStreamSingleton); - private final ReentrantLock inputStreamLock = new ReentrantLock(); - private final ReentrantLock outputStreamLock = new ReentrantLock(); - private final UserConnection owner; - private int defagSendDelay; - - private final List sendQueueV4 = new LinkedList<>(); - private volatile int sendQueueByteLengthV4 = 0; - private volatile Callable futureSendCallableV4 = null; - private volatile ScheduledFuture futureSendTaskV4 = null; - - public GameProtocolMessageController(UserConnection owner, GamePluginMessageProtocol protocol, - GameMessageHandler handler, int defagSendDelay) { - this.owner = owner; - this.protocol = protocol; - this.handler = handler; - this.defagSendDelay = defagSendDelay; - } - - public boolean handlePacket(String channel, byte[] data) throws IOException { - GameMessagePacket pkt; - if(inputStreamLock.tryLock()) { - try { - byteInputStreamSingleton.feedBuffer(data); - if(protocol.ver >= 4 && data.length > 0 && data[0] == (byte)0xFF && channel.equals(GamePluginMessageConstants.V4_CHANNEL)) { - inputStreamSingleton.readByte(); - int count = inputStreamSingleton.readVarInt(); - for(int i = 0, j, k; i < count; ++i) { - j = inputStreamSingleton.readVarInt(); - k = byteInputStreamSingleton.getReaderIndex() + j; - if(j > inputStreamSingleton.available()) { - throw new IOException("Packet fragment is too long: " + j + " > " + inputStreamSingleton.available()); - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputStreamSingleton); - if(pkt != null) { - pkt.handlePacket(handler); - }else { - throw new IOException("Unknown packet type in fragment!"); - } - if(byteInputStreamSingleton.getReaderIndex() != k) { - throw new IOException("Packet fragment was the wrong length: " + (j + byteInputStreamSingleton.getReaderIndex() - k) + " != " + j); - } - } - if(inputStreamSingleton.available() > 0) { - throw new IOException("Leftover data after reading multi-packet! (" + inputStreamSingleton.available() + " bytes)"); - } - return true; - } - inputStreamSingleton.setToByteArrayReturns(data); - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputStreamSingleton); - if(pkt != null && byteInputStreamSingleton.available() != 0) { - throw new IOException("Packet was the wrong length: " + pkt.getClass().getSimpleName()); - } - }finally { - byteInputStreamSingleton.feedBuffer(null); - inputStreamSingleton.setToByteArrayReturns(null); - inputStreamLock.unlock(); - } - }else { - // slow version that makes multiple new objects - ReusableByteArrayInputStream inputStream = new ReusableByteArrayInputStream(); - inputStream.feedBuffer(data); - SimpleInputBufferImpl inputBuffer = new SimpleInputBufferImpl(inputStream, data); - if(protocol.ver >= 4 && channel.equals(GamePluginMessageConstants.V4_CHANNEL)) { - inputBuffer.setToByteArrayReturns(null); - inputBuffer.readByte(); - int count = inputBuffer.readVarInt(); - for(int i = 0, j, k; i < count; ++i) { - j = inputBuffer.readVarInt(); - k = inputStream.getReaderIndex() + j; - if(j > inputBuffer.available()) { - throw new IOException("Packet fragment is too long: " + j + " > " + inputBuffer.available()); - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputBuffer); - if(pkt != null) { - pkt.handlePacket(handler); - }else { - throw new IOException("Unknown packet type in fragment!"); - } - if(inputStream.getReaderIndex() != k) { - throw new IOException("Packet fragment was the wrong length: " + (j + inputStream.getReaderIndex() - k) + " != " + j); - } - } - if(inputBuffer.available() > 0) { - throw new IOException("Leftover data after reading multi-packet! (" + inputBuffer.available() + " bytes)"); - } - return true; - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputBuffer); - if(pkt != null && inputStream.available() != 0) { - throw new IOException("Packet was the wrong length: " + pkt.getClass().getSimpleName()); - } - } - if(pkt != null) { - pkt.handlePacket(handler); - return true; - }else { - return false; - } - } - - public void sendPacketImmediately(GameMessagePacket packet) throws IOException { - sendPacket(packet, true); - } - - public void sendPacket(GameMessagePacket packet) throws IOException { - sendPacket(packet, false); - } - - protected void sendPacket(GameMessagePacket packet, boolean immediately) throws IOException { - int len = packet.length() + 1; - String chan; - byte[] data; - if(outputStreamLock.tryLock()) { - try { - byteOutputStreamSingleton.feedBuffer(new byte[len == 0 ? 64 : len]); - chan = protocol.writePacket(GamePluginMessageConstants.SERVER_TO_CLIENT, outputStreamSingleton, packet); - data = byteOutputStreamSingleton.returnBuffer(); - }finally { - byteOutputStreamSingleton.feedBuffer(null); - outputStreamLock.unlock(); - } - }else { - // slow version that makes multiple new objects - ReusableByteArrayOutputStream bao = new ReusableByteArrayOutputStream(); - bao.feedBuffer(new byte[len == 0 ? 64 : len]); - SimpleOutputBufferImpl outputStream = new SimpleOutputBufferImpl(bao); - chan = protocol.writePacket(GamePluginMessageConstants.SERVER_TO_CLIENT, outputStream, packet); - data = bao.returnBuffer(); - } - if(len != 0 && data.length != len && data.length + 1 != len) { - EaglerXBungee.logger().warning("Packet " + packet.getClass().getSimpleName() - + " was the wrong length after serialization, " + data.length + " != " + len); - } - if(defagSendDelay > 0 && protocol.ver >= 4 && chan.equals(GamePluginMessageConstants.V4_CHANNEL)) { - synchronized(sendQueueV4) { - int varIntLen = GamePacketOutputBuffer.getVarIntSize(data.length); - if(immediately || sendQueueByteLengthV4 + data.length + varIntLen > 32760) { - if(futureSendTaskV4 != null && !futureSendTaskV4.isDone()) { - futureSendTaskV4.cancel(false); - futureSendTaskV4 = null; - futureSendCallableV4 = null; - } - if(!sendQueueV4.isEmpty()) { - flushQueue(); - } - } - if(immediately) { - owner.sendData(chan, data); - }else { - sendQueueV4.add(data); - if(futureSendTaskV4 == null || futureSendTaskV4.isDone()) { - futureSendTaskV4 = ((EaglerInitialHandler) owner.getPendingConnection()).ch.getHandle() - .eventLoop().schedule(futureSendCallableV4 = new Callable() { - @Override - public Void call() throws Exception { - synchronized (sendQueueV4) { - if (futureSendCallableV4 != this) { - return null; - } - futureSendTaskV4 = null; - futureSendCallableV4 = null; - if(!sendQueueV4.isEmpty()) { - flushQueue(); - } - } - return null; - } - }, defagSendDelay, TimeUnit.MILLISECONDS); - } - } - } - }else { - owner.sendData(chan, data); - } - } - - private void flushQueue() { - if(!owner.isConnected()) { - sendQueueV4.clear(); - return; - } - byte[] pkt; - if(sendQueueV4.size() == 1) { - pkt = sendQueueV4.remove(0); - owner.sendData(GamePluginMessageConstants.V4_CHANNEL, pkt); - }else { - int i, j, sendCount, totalLen, lastLen; - while(!sendQueueV4.isEmpty()) { - sendCount = 0; - totalLen = 0; - Iterator itr = sendQueueV4.iterator(); - do { - i = itr.next().length; - lastLen = GamePacketOutputBuffer.getVarIntSize(i) + i; - totalLen += lastLen; - ++sendCount; - }while(totalLen < 32760 && itr.hasNext()); - if(totalLen >= 32760) { - --sendCount; - totalLen -= lastLen; - } - if(sendCount <= 1) { - pkt = sendQueueV4.remove(0); - owner.sendData(GamePluginMessageConstants.V4_CHANNEL, pkt); - continue; - } - byte[] toSend = new byte[1 + totalLen + GamePacketOutputBuffer.getVarIntSize(sendCount)]; - ByteBuf sendBuffer = Unpooled.wrappedBuffer(toSend); - sendBuffer.writerIndex(0); - sendBuffer.writeByte(0xFF); - DefinedPacket.writeVarInt(sendCount, sendBuffer); - for(j = 0; j < sendCount; ++j) { - pkt = sendQueueV4.remove(0); - DefinedPacket.writeVarInt(pkt.length, sendBuffer); - sendBuffer.writeBytes(pkt); - } - owner.sendData(GamePluginMessageConstants.V4_CHANNEL, toSend); - } - } - } - - public static GameMessageHandler createServerHandler(int protocolVersion, UserConnection conn, EaglerXBungee plugin) { - switch(protocolVersion) { - case 2: - case 3: - return new ServerV3MessageHandler(conn, plugin); - case 4: - return new ServerV4MessageHandler(conn, plugin); - default: - throw new IllegalArgumentException("Unknown protocol verison: " + protocolVersion); - } - } - - public static void sendHelper(UserConnection conn, GameMessagePacket packet) { - PendingConnection p = conn.getPendingConnection(); - if(p instanceof EaglerInitialHandler) { - ((EaglerInitialHandler)p).sendEaglerMessage(packet); - }else { - throw new UnsupportedOperationException("Tried to send eagler packet on a non-eagler connection!"); - } - } - - public UserConnection getUserConnection() { - return owner; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV3MessageHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV3MessageHandler.java deleted file mode 100644 index 11117967..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV3MessageHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.*; -import net.md_5.bungee.UserConnection; - -public class ServerV3MessageHandler implements GameMessageHandler { - - private final UserConnection conn; - private final EaglerXBungee plugin; - - public ServerV3MessageHandler(UserConnection conn, EaglerXBungee plugin) { - this.conn = conn; - this.plugin = plugin; - } - - public void handleClient(CPacketGetOtherCapeEAG packet) { - plugin.getCapeService().processGetOtherCape(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - - public void handleClient(CPacketGetOtherSkinEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - - public void handleClient(CPacketGetSkinByURLEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), packet.url, conn); - } - - public void handleClient(CPacketVoiceSignalConnectEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeConnect(conn); - } - } - - public void handleClient(CPacketVoiceSignalDescEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDesc(new UUID(packet.uuidMost, packet.uuidLeast), packet.desc, conn); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectV3EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - if(packet.isPeerType) { - svc.handleVoiceSignalPacketTypeDisconnectPeer(new UUID(packet.uuidMost, packet.uuidLeast), conn); - }else { - svc.handleVoiceSignalPacketTypeDisconnect(conn); - } - } - } - - public void handleClient(CPacketVoiceSignalICEEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeICE(new UUID(packet.uuidMost, packet.uuidLeast), packet.ice, conn); - } - } - - public void handleClient(CPacketVoiceSignalRequestEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeRequest(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV4MessageHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV4MessageHandler.java deleted file mode 100644 index abff5b90..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/ServerV4MessageHandler.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol; - -import java.util.Arrays; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewMessage; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewOpenClose; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftWebViewChannelEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftWebViewMessageEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerPauseMenuConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.*; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.connection.ProxiedPlayer; - -public class ServerV4MessageHandler implements GameMessageHandler { - - private final UserConnection conn; - private final EaglerXBungee plugin; - - public ServerV4MessageHandler(UserConnection conn, EaglerXBungee plugin) { - this.conn = conn; - this.plugin = plugin; - } - - public void handleClient(CPacketGetOtherCapeEAG packet) { - plugin.getCapeService().processGetOtherCape(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - - public void handleClient(CPacketGetOtherSkinEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - - public void handleClient(CPacketGetSkinByURLEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), packet.url, conn); - } - - public void handleClient(CPacketVoiceSignalConnectEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeConnect(conn); - } - } - - public void handleClient(CPacketVoiceSignalDescEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDesc(new UUID(packet.uuidMost, packet.uuidLeast), packet.desc, conn); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectV4EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDisconnect(conn); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectPeerV4EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDisconnectPeer(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - } - - public void handleClient(CPacketVoiceSignalICEEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeICE(new UUID(packet.uuidMost, packet.uuidLeast), packet.ice, conn); - } - } - - public void handleClient(CPacketVoiceSignalRequestEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && ((EaglerInitialHandler)conn.getPendingConnection()).getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeRequest(new UUID(packet.uuidMost, packet.uuidLeast), conn); - } - } - - public void handleClient(CPacketGetOtherClientUUIDV4EAG packet) { - ProxiedPlayer player = plugin.getProxy().getPlayer(new UUID(packet.playerUUIDMost, packet.playerUUIDLeast)); - if(player != null) { - PendingConnection conn2 = player.getPendingConnection(); - if(conn2 instanceof EaglerInitialHandler) { - UUID uuid = ((EaglerInitialHandler)conn2).getClientBrandUUID(); - if (uuid != null) { - ((EaglerInitialHandler) conn.getPendingConnection()) - .sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits())); - return; - } - }else { - ((EaglerInitialHandler) conn.getPendingConnection()) - .sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, - EaglerXBungeeAPIHelper.BRAND_VANILLA_UUID.getMostSignificantBits(), - EaglerXBungeeAPIHelper.BRAND_VANILLA_UUID.getLeastSignificantBits())); - return; - } - } - ((EaglerInitialHandler) conn.getPendingConnection()).sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, 0l, 0l)); - } - - public void handleClient(CPacketRequestServerInfoV4EAG packet) { - EaglerPauseMenuConfig conf = plugin.getConfig().getPauseMenuConf(); - if (conf != null && conf.getEnabled() - && conf.getPacket().serverInfoMode == SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS - && Arrays.equals(conf.getServerInfoHash(), packet.requestHash)) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)conn.getPendingConnection(); - synchronized(eaglerHandler.serverInfoSendBuffer) { - if(eaglerHandler.hasSentServerInfo.getAndSet(true)) { - conn.disconnect(new TextComponent("Duplicate server info request")); - return; - } - eaglerHandler.serverInfoSendBuffer.clear(); - eaglerHandler.serverInfoSendBuffer.addAll(conf.getServerInfo()); - } - }else { - conn.disconnect(new TextComponent("Invalid server info request")); - } - } - - public void handleClient(CPacketWebViewMessageV4EAG packet) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)conn.getPendingConnection(); - if(eaglerHandler.isWebViewChannelAllowed) { - if(eaglerHandler.webViewMessageChannelOpen.get()) { - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.WEBVIEW_MESSAGE)) { - eaglerHandler.getRPCSessionHandler().sendRPCPacket(new SPacketRPCEventWebViewMessage( - eaglerHandler.webViewMessageChannelName, packet.type, packet.data)); - } - BungeeCord.getInstance().getPluginManager().callEvent(new EaglercraftWebViewMessageEvent(conn, - eaglerHandler.getEaglerListenerConfig(), eaglerHandler.webViewMessageChannelName, packet)); - } - }else { - conn.disconnect(new TextComponent("Webview channel permissions have not been enabled!")); - } - } - - public void handleClient(CPacketWebViewMessageEnV4EAG packet) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)conn.getPendingConnection(); - if(eaglerHandler.isWebViewChannelAllowed) { - eaglerHandler.webViewMessageChannelOpen.set(packet.messageChannelOpen); - String oldChannelName = eaglerHandler.webViewMessageChannelName; - eaglerHandler.webViewMessageChannelName = packet.messageChannelOpen ? packet.channelName : null; - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.WEBVIEW_OPEN_CLOSE)) { - eaglerHandler.getRPCSessionHandler().sendRPCPacket(new SPacketRPCEventWebViewOpenClose( - packet.messageChannelOpen, packet.messageChannelOpen ? packet.channelName : oldChannelName)); - } - BungeeCord.getInstance().getPluginManager() - .callEvent(new EaglercraftWebViewChannelEvent(conn, eaglerHandler.getEaglerListenerConfig(), - packet.messageChannelOpen ? eaglerHandler.webViewMessageChannelName : oldChannelName, - packet.messageChannelOpen ? EaglercraftWebViewChannelEvent.EventType.CHANNEL_OPEN - : EaglercraftWebViewChannelEvent.EventType.CHANNEL_CLOSE)); - }else { - conn.disconnect(new TextComponent("Webview channel permissions have not been enabled!")); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/MOTDQueryHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/MOTDQueryHandler.java deleted file mode 100644 index c0f52150..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/MOTDQueryHandler.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.EaglerQuerySimpleHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.MOTDConnection; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.MOTDCacheConfiguration; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.ProxiedPlayer; - -public class MOTDQueryHandler extends EaglerQuerySimpleHandler implements MOTDConnection { - - private long creationTime = 0l; - - private String line1; - private String line2; - private List players; - private int[] bitmap; - private int onlinePlayers; - private int maxPlayers; - private boolean hasIcon; - private boolean iconDirty; - private String subType; - private String returnType; - - @Override - protected void begin(String queryType) { - creationTime = EaglerXBungeeAPIHelper.steadyTimeMillis(); - subType = queryType; - returnType = "MOTD"; - EaglerListenerConfig listener = getListener(); - String[] lns = listener.getMotd().split("\n"); - if(lns.length >= 1) { - line1 = lns[0]; - } - if(lns.length >= 2) { - line2 = lns[1]; - } - maxPlayers = listener.getMaxPlayers(); - onlinePlayers = ProxyServer.getInstance().getOnlineCount(); - players = new ArrayList<>(); - for(ProxiedPlayer pp : ProxyServer.getInstance().getPlayers()) { - players.add(pp.getDisplayName()); - if(players.size() >= 9) { - players.add("" + ChatColor.GRAY + ChatColor.ITALIC + "(" + (onlinePlayers - players.size()) + " more)"); - break; - } - } - bitmap = new int[4096]; - int i = queryType.indexOf('.'); - if(i > 0) { - subType = queryType.substring(i + 1); - if(subType.length() == 0) { - subType = "motd"; - } - }else { - subType = "motd"; - } - if(!subType.startsWith("noicon") && !subType.startsWith("cache.noicon")) { - int[] maybeIcon = listener.getServerIconPixels(); - iconDirty = hasIcon = maybeIcon != null; - if(hasIcon) { - System.arraycopy(maybeIcon, 0, bitmap, 0, 4096); - } - } - } - - @Override - public long getConnectionTimestamp() { - return creationTime; - } - - @Override - public void sendToUser() { - if(!isClosed()) { - JsonObject obj = new JsonObject(); - if(subType.startsWith("cache.anim")) { - obj.addProperty("unsupported", true); - sendJsonResponseAndClose(returnType, obj); - return; - }else if(subType.startsWith("cache")) { - JsonArray cacheControl = new JsonArray(); - MOTDCacheConfiguration cc = getListener().getMOTDCacheConfig(); - if(cc.cacheServerListAnimation) { - cacheControl.add("animation"); - } - if(cc.cacheServerListResults) { - cacheControl.add("results"); - } - if(cc.cacheServerListTrending) { - cacheControl.add("trending"); - } - if(cc.cacheServerListPortfolios) { - cacheControl.add("portfolio"); - } - obj.add("cache", cacheControl); - obj.addProperty("ttl", cc.cacheTTL); - }else { - MOTDCacheConfiguration cc = getListener().getMOTDCacheConfig();; - obj.addProperty("cache", cc.cacheServerListAnimation || cc.cacheServerListResults || - cc.cacheServerListTrending || cc.cacheServerListPortfolios); - } - boolean noIcon = subType.startsWith("noicon") || subType.startsWith("cache.noicon"); - JsonArray motd = new JsonArray(); - if(line1 != null && line1.length() > 0) motd.add(line1); - if(line2 != null && line2.length() > 0) motd.add(line2); - obj.add("motd", motd); - obj.addProperty("icon", hasIcon && !noIcon); - obj.addProperty("online", onlinePlayers); - obj.addProperty("max", maxPlayers); - JsonArray playerz = new JsonArray(); - for(String s : players) { - playerz.add(s); - } - obj.add("players", playerz); - sendJsonResponse(returnType, obj); - if(hasIcon && !noIcon && iconDirty && bitmap != null) { - byte[] iconPixels = new byte[16384]; - for(int i = 0, j; i < 4096; ++i) { - j = i << 2; - iconPixels[j] = (byte)(bitmap[i] >>> 16); - iconPixels[j + 1] = (byte)(bitmap[i] >>> 8); - iconPixels[j + 2] = (byte)(bitmap[i] & 0xFF); - iconPixels[j + 3] = (byte)(bitmap[i] >>> 24); - } - sendBinaryResponse(iconPixels); - iconDirty = false; - } - if(subType.startsWith("cache")) { - close(); - } - } - } - - @Override - public String getLine1() { - return line1; - } - - @Override - public String getLine2() { - return line2; - } - - @Override - public List getPlayerList() { - return players; - } - - @Override - public int[] getBitmap() { - return bitmap; - } - - @Override - public int getOnlinePlayers() { - return onlinePlayers; - } - - @Override - public int getMaxPlayers() { - return maxPlayers; - } - - @Override - public String getSubType() { - return subType; - } - - @Override - public void setLine1(String p) { - line1 = p; - } - - @Override - public void setLine2(String p) { - line2 = p; - } - - @Override - public void setPlayerList(List p) { - players = p; - } - - @Override - public void setPlayerList(String... p) { - players = Arrays.asList(p); - } - - @Override - public void setBitmap(int[] p) { - iconDirty = hasIcon = true; - bitmap = p; - } - - @Override - public void setOnlinePlayers(int i) { - onlinePlayers = i; - } - - @Override - public void setMaxPlayers(int i) { - maxPlayers = i; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/QueryManager.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/QueryManager.java deleted file mode 100644 index da5fc621..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/QueryManager.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; - -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.HttpServerQueryHandler; -import net.md_5.bungee.api.plugin.PluginDescription; - -public class QueryManager { - - private static final Map> queryTypes = new HashMap<>(); - - static { - queryTypes.put("motd", MOTDQueryHandler.class); - queryTypes.put("motd.cache", MOTDQueryHandler.class); - queryTypes.put("version", VersionQueryHandler.class); - queryTypes.put("revoke_session_token", RevokeSessionQueryHandler.class); - } - - public static HttpServerQueryHandler createQueryHandler(String type) { - Class clazz; - synchronized(queryTypes) { - clazz = queryTypes.get(type); - } - if(clazz != null) { - HttpServerQueryHandler obj = null; - try { - obj = clazz.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception creating query handler for '" + type + "'!", e); - } - if(obj != null) { - return obj; - } - } - return null; - } - - public static void registerQueryType(String name, Class clazz) { - synchronized(queryTypes) { - if(queryTypes.put(name, clazz) != null) { - EaglerXBungee.logger().warning("Query type '" + name + "' was registered twice, probably by two different plugins!"); - Thread.dumpStack(); - } - } - } - - public static void unregisterQueryType(String name) { - synchronized(queryTypes) { - queryTypes.remove(name); - } - } - - private static JsonObject createBaseResponse() { - EaglerXBungee plugin = EaglerXBungee.getEagler(); - EaglerBungeeConfig conf = plugin.getConfig(); - JsonObject json = new JsonObject(); - json.addProperty("name", conf.getServerName()); - json.addProperty("brand", "lax1dude"); - PluginDescription desc = plugin.getDescription(); - json.addProperty("vers", "EaglerXBungee/" + desc.getVersion()); - json.addProperty("cracked", conf.isCracked()); - json.addProperty("time", System.currentTimeMillis()); - json.addProperty("uuid", conf.getServerUUID().toString()); - return json; - } - - public static JsonObject createStringResponse(String type, String str) { - JsonObject ret = createBaseResponse(); - ret.addProperty("type", type); - ret.addProperty("data", str); - return ret; - } - - public static JsonObject createJsonObjectResponse(String type, JsonObject json) { - JsonObject ret = createBaseResponse(); - ret.addProperty("type", type); - ret.add("data", json); - return ret; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/RevokeSessionQueryHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/RevokeSessionQueryHandler.java deleted file mode 100644 index 36cfca23..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/RevokeSessionQueryHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query; - -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftRevokeSessionQueryEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftRevokeSessionQueryEvent.EnumSessionRevokeStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.EaglerQueryHandler; -import net.md_5.bungee.BungeeCord; - -public class RevokeSessionQueryHandler extends EaglerQueryHandler { - - @Override - protected void begin(String queryType) { - this.setKeepAlive(true); - this.acceptBinary(); - this.setMaxAge(5000l); - this.sendStringResponse("revoke_session_token", "ready"); - } - - @Override - protected void processString(String str) { - this.close(); - } - - @Override - protected void processJson(JsonObject obj) { - this.close(); - } - - @Override - protected void processBytes(byte[] bytes) { - if(bytes.length > 255) { - JsonObject response = new JsonObject(); - response.addProperty("status", "error"); - response.addProperty("code", 3); - response.addProperty("delete", false); - sendJsonResponseAndClose("revoke_session_token", response); - return; - } - this.setMaxAge(30000l); - EaglercraftRevokeSessionQueryEvent evt = new EaglercraftRevokeSessionQueryEvent(this.getAddress(), this.getOrigin(), bytes, this); - BungeeCord.getInstance().getPluginManager().callEvent(evt); - JsonObject response = new JsonObject(); - EnumSessionRevokeStatus stat = evt.getResultStatus(); - response.addProperty("status", stat.status); - if(stat.code != -1) { - response.addProperty("code", stat.code); - } - if(stat != EnumSessionRevokeStatus.SUCCESS) { - response.addProperty("delete", evt.getShouldDeleteCookie()); - } - sendJsonResponseAndClose("revoke_session_token", response); - } - - @Override - protected void closed() { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/VersionQueryHandler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/VersionQueryHandler.java deleted file mode 100644 index f0d13aba..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/query/VersionQueryHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.query; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.query.EaglerQuerySimpleHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerListenerConfig; -import net.md_5.bungee.api.ProxyServer; - -public class VersionQueryHandler extends EaglerQuerySimpleHandler { - - @Override - protected void begin(String queryType) { - JsonObject responseObj = new JsonObject(); - JsonArray handshakeVersions = new JsonArray(); - EaglerListenerConfig cfg = this.getListener(); - if(cfg.isAllowV3()) { - handshakeVersions.add(2); - handshakeVersions.add(3); - } - if(cfg.isAllowV4()) { - handshakeVersions.add(4); - } - responseObj.add("handshakeVersions", handshakeVersions); - JsonObject protocolVersions = new JsonObject(); - protocolVersions.addProperty("min", cfg.getMinMCProtocol()); - protocolVersions.addProperty("max", cfg.getMaxMCProtocol()); - responseObj.add("protocolVersions", protocolVersions); - JsonObject proxyInfo = new JsonObject(); - proxyInfo.addProperty("brand", ProxyServer.getInstance().getName()); - proxyInfo.addProperty("vers", ProxyServer.getInstance().getVersion()); - responseObj.add("proxyVersions", proxyInfo); - sendJsonResponseAndClose("version", responseObj); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpContentType.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpContentType.java deleted file mode 100644 index 4f69522f..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpContentType.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web; - -import java.util.HashSet; -import java.util.Set; - -public class HttpContentType { - - public final Set extensions; - public final String mimeType; - public final String charset; - public final String httpHeader; - public final String cacheControlHeader; - public final long fileBrowserCacheTTL; - - public static final HttpContentType defaultType = new HttpContentType(new HashSet<>(), "application/octet-stream", null, 14400000l); - - public HttpContentType(Set extensions, String mimeType, String charset, long fileBrowserCacheTTL) { - this.extensions = extensions; - this.mimeType = mimeType; - this.charset = charset; - this.fileBrowserCacheTTL = fileBrowserCacheTTL; - if(charset == null) { - this.httpHeader = mimeType; - }else { - this.httpHeader = mimeType + "; charset=" + charset; - } - if(fileBrowserCacheTTL > 0l) { - this.cacheControlHeader = "max-age=" + (fileBrowserCacheTTL / 1000l); - }else { - this.cacheControlHeader = "no-cache"; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpMemoryCache.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpMemoryCache.java deleted file mode 100644 index 3848f55a..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpMemoryCache.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.SimpleTimeZone; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; - -public class HttpMemoryCache { - - public File fileObject; - public String filePath; - public ByteBuf fileData; - public HttpContentType contentType; - public long lastCacheHit; - public long lastDiskReload; - public long lastDiskModified; - private final String server; - - private static final SimpleDateFormat gmt; - - static { - gmt = new SimpleDateFormat(); - gmt.setTimeZone(new SimpleTimeZone(0, "GMT")); - gmt.applyPattern("dd MMM yyyy HH:mm:ss z"); - } - - public HttpMemoryCache(File fileObject, String filePath, ByteBuf fileData, HttpContentType contentType, - long lastCacheHit, long lastDiskReload, long lastDiskModified) { - this.fileObject = fileObject; - this.filePath = filePath; - this.fileData = fileData; - this.contentType = contentType; - this.lastCacheHit = lastCacheHit; - this.lastDiskReload = lastDiskReload; - this.lastDiskModified = lastDiskModified; - this.server = "EaglerXBungee/" + EaglerXBungee.getEagler().getDescription().getVersion(); - } - - public DefaultFullHttpResponse createHTTPResponse() { - return createHTTPResponse(HttpResponseStatus.OK); - } - - public DefaultFullHttpResponse createHTTPResponse(HttpResponseStatus code) { - DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, code, Unpooled.wrappedBuffer(fileData.retain())); - HttpHeaders responseHeaders = response.headers(); - Date d = new Date(); - responseHeaders.add(HttpHeaderNames.CONTENT_TYPE, contentType.httpHeader); - responseHeaders.add(HttpHeaderNames.CONTENT_LENGTH, fileData.readableBytes()); - responseHeaders.add(HttpHeaderNames.CACHE_CONTROL, contentType.cacheControlHeader); - responseHeaders.add(HttpHeaderNames.DATE, gmt.format(d)); - long l = contentType.fileBrowserCacheTTL; - if(l > 0l && l != Long.MAX_VALUE) { - d.setTime(d.getTime() + l); - responseHeaders.add(HttpHeaderNames.EXPIRES, gmt.format(d)); - } - d.setTime(lastDiskModified); - responseHeaders.add(HttpHeaderNames.LAST_MODIFIED, gmt.format(d)); - responseHeaders.add(HttpHeaderNames.SERVER, server); - return response; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java deleted file mode 100644 index f2fe9d24..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.web; - -import java.io.File; -import java.io.FileInputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import com.google.common.collect.Sets; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; - -public class HttpWebServer { - - public final File directory; - public final Map contentTypes; - private final Map filesCache; - private final List index; - private final String page404; - private static HttpMemoryCache default404Page; - private static HttpMemoryCache default404UpgradePage; - - public HttpWebServer(File directory, Map contentTypes, List index, String page404) { - this.directory = directory; - this.contentTypes = contentTypes; - this.filesCache = new HashMap<>(); - this.index = index; - this.page404 = page404; - } - - public void flushCache() { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - synchronized(filesCache) { - Iterator itr = filesCache.values().iterator(); - while(itr.hasNext()) { - HttpMemoryCache i = itr.next(); - if(i.contentType.fileBrowserCacheTTL != Long.MAX_VALUE && millis - i.lastCacheHit > 900000l) { - i.fileData.release(); - itr.remove(); - } - } - } - } - - public HttpMemoryCache retrieveFile(String path) { - try { - String[] pathSplit = path.split("(\\\\|\\/)+"); - - List pathList = pathSplit.length == 0 ? null : new ArrayList<>(pathSplit.length); - for(int i = 0; i < pathSplit.length; ++i) { - pathSplit[i] = pathSplit[i].trim(); - if(pathSplit[i].length() > 0) { - if(!pathSplit[i].equals(".") && !pathSplit[i].startsWith("..")) { - pathList.add(pathSplit[i]); - } - } - } - - HttpMemoryCache cached; - - if(pathList == null || pathList.size() == 0) { - for(int i = 0, l = index.size(); i < l; ++i) { - cached = retrieveFile(index.get(i)); - if(cached != null) { - return cached; - } - } - return null; - } - - String joinedPath = String.join("/", pathList); - - //TODO: Rewrite this to cause less lock contention - synchronized(filesCache) { - cached = filesCache.get(joinedPath); - - if(cached != null) { - cached = validateCache(cached); - if(cached != null) { - return cached; - }else { - filesCache.remove(joinedPath); - } - } - - File f = new File(directory, joinedPath); - - if(!f.exists()) { - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - - if(f.isDirectory()) { - for(int i = 0, l = index.size(); i < l; ++i) { - String p = joinedPath + "/" + index.get(i); - cached = filesCache.get(p); - if(cached != null) { - cached = validateCache(cached); - if(cached != null) { - filesCache.put(joinedPath, cached); - }else { - filesCache.remove(p); - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - return cached; - } - } - for(int i = 0, l = index.size(); i < l; ++i) { - String p = joinedPath + "/" + index.get(i); - File ff = new File(directory, p); - if(ff.isFile()) { - HttpMemoryCache memCache = retrieveFile(ff, p); - if(memCache != null) { - filesCache.put(joinedPath, memCache); - return memCache; - } - } - } - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - }else { - HttpMemoryCache memCache = retrieveFile(f, joinedPath); - if(memCache != null) { - filesCache.put(joinedPath, memCache); - return memCache; - }else { - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - } - } - }catch(Throwable t) { - return default404Page; - } - } - - private HttpMemoryCache retrieveFile(File path, String requestCachePath) { - int fileSize = (int)path.length(); - try(FileInputStream is = new FileInputStream(path)) { - ByteBuf file = Unpooled.buffer(fileSize, fileSize); - file.writeBytes(is, fileSize); - String ext = path.getName(); - HttpContentType ct = null; - int i = ext.lastIndexOf('.'); - if(i != -1) { - ct = contentTypes.get(ext.substring(i + 1)); - } - if(ct == null) { - ct = HttpContentType.defaultType; - } - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(path, requestCachePath, file, ct, millis, millis, path.lastModified()); - }catch(Throwable t) { - return null; - } - } - - private HttpMemoryCache validateCache(HttpMemoryCache file) { - if(file.fileObject == null) { - return file; - } - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - file.lastCacheHit = millis; - if(millis - file.lastDiskReload > 4000l) { - File f = file.fileObject; - if(!f.isFile()) { - return null; - }else { - long lastMod = f.lastModified(); - if(lastMod != file.lastDiskModified) { - int fileSize = (int)f.length(); - try(FileInputStream is = new FileInputStream(f)) { - file.fileData.release(); - file.fileData = Unpooled.buffer(fileSize, fileSize); - file.fileData.writeBytes(is, fileSize); - file.lastDiskReload = millis; - file.lastDiskModified = lastMod; - return file; - }catch(Throwable t) { - return null; - } - }else { - return file; - } - } - }else { - return file; - } - } - - public static void regenerate404Pages() { - if(default404Page != null) { - default404Page.fileData.release(); - } - default404Page = regenerateDefault404(); - if(default404UpgradePage != null) { - default404UpgradePage.fileData.release(); - } - default404UpgradePage = regenerateDefaultUpgrade404(); - } - - public static HttpMemoryCache getHTTP404() { - return default404Page; - } - - public static HttpMemoryCache getWebSocket404() { - return default404UpgradePage; - } - - private static HttpMemoryCache regenerateDefault404() { - EaglerXBungee plugin = EaglerXBungee.getEagler(); - byte[] src = ("" + htmlEntities(plugin.getConfig().getServerName()) + "" - + "

404 Not Found


" - + "The requested resource " - + " could not be found on this server!

" + htmlEntities(plugin.getDescription().getName()) + "/" - + htmlEntities(plugin.getDescription().getVersion()) + "

").getBytes(StandardCharsets.UTF_8); - HttpContentType htmlContentType = new HttpContentType(Sets.newHashSet("html"), "text/html", "utf-8", 120000l); - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(null, "~404", Unpooled.wrappedBuffer(src), htmlContentType, millis, millis, millis); - } - - private static HttpMemoryCache regenerateDefaultUpgrade404() { - EaglerXBungee plugin = EaglerXBungee.getEagler(); - String name = htmlEntities(plugin.getConfig().getServerName()); - byte[] src = ("" + name + - "

" - + "404 'Websocket Upgrade Failure' (rip)

The URL you have requested is the physical WebSocket address of '" + name + "'

To correctly join this server, load the latest EaglercraftX 1.8 client, click the 'Direct Connect' button
on the 'Multiplayer' screen, " - + "and enter this URL as the server address

").getBytes(StandardCharsets.UTF_8); - HttpContentType htmlContentType = new HttpContentType(Sets.newHashSet("html"), "text/html", "utf-8", 14400000l); - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(null, "~404", Unpooled.wrappedBuffer(src), htmlContentType, millis, millis, millis); - } - - public static String htmlEntities(String input) { - return input.replace("<", "<").replace(">", ">"); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java deleted file mode 100644 index 20be39fc..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.shit; - -import java.util.logging.Logger; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.md_5.bungee.api.ProxyServer; - -public class CompatWarning { - - public static void displayCompatWarning() { - String stfu = System.getProperty("eaglerxbungee.stfu"); - if("true".equalsIgnoreCase(stfu)) { - return; - } - String[] compatWarnings = new String[] { - ":>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>", - ":> ", - ":> EAGLERCRAFTXBUNGEE WARNING:", - ":> ", - ":> This plugin wasn\'t tested to be \'working\'", - ":> with ANY version of BungeeCord (and forks)", - ":> apart from the versions listed below:", - ":> ", - ":> - BungeeCord: " + EaglerXBungee.NATIVE_BUNGEECORD_BUILD, - ":> - " + EaglerXBungee.NATIVE_BUNGEECORD_BUILD_DL, - ":> ", - ":> - Waterfall: " + EaglerXBungee.NATIVE_WATERFALL_BUILD, - ":> - " + EaglerXBungee.NATIVE_WATERFALL_BUILD_DL, - ":> ", - ":> This is not a Bukkit/Spigot plugin!", - ":> ", - ":> Use \"-Deaglerxbungee.stfu=true\" to hide", - ":> ", - ":>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>" - }; - - try { - Logger fuck = ProxyServer.getInstance().getLogger(); - for(int i = 0; i < compatWarnings.length; ++i) { - fuck.warning(compatWarnings[i]); - } - }catch(Throwable t) { - for(int i = 0; i < compatWarnings.length; ++i) { - System.err.println(compatWarnings[i]); - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/MainClass.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/MainClass.java deleted file mode 100644 index bc20fa51..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/MainClass.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.shit; - -import java.awt.GraphicsEnvironment; - -import javax.swing.JOptionPane; - -public class MainClass { - - public static void main(String[] args) { - System.err.println(); - System.err.println("ERROR: The EaglerXBungee 1.8 jar file is a PLUGIN intended to be used with BungeeCord!"); - System.err.println("Place this file in the \"plugins\" directory of your BungeeCord installation"); - System.err.println(); - try { - tryShowPopup(); - }catch(Throwable t) { - } - System.exit(0); - } - - private static void tryShowPopup() throws Throwable { - if(!GraphicsEnvironment.isHeadless()) { - JOptionPane.showMessageDialog(null, "ERROR: The EaglerXBungee 1.8 jar file is a PLUGIN intended to be used with BungeeCord!\nPlace this file in the \"plugins\" directory of your BungeeCord installation", "EaglerXBungee", JOptionPane.ERROR_MESSAGE); - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/AsyncSkinProvider.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/AsyncSkinProvider.java deleted file mode 100644 index 4026c6c9..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/AsyncSkinProvider.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; -import java.util.logging.Level; - -import javax.imageio.ImageIO; - -import org.apache.commons.codec.binary.Base64; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.BinaryHttpClient.Response; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.ICacheProvider.CacheLoadedProfile; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.ICacheProvider.CacheLoadedSkin; - -public class AsyncSkinProvider { - - private static class SkinConsumerImpl implements Consumer { - - protected final Consumer responseConsumer; - - protected SkinConsumerImpl(Consumer consumer) { - this.responseConsumer = consumer; - } - - protected void doAccept(byte[] v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown caching new skin!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - BufferedImage image; - try { - image = ImageIO.read(new ByteArrayInputStream(response.data)); - }catch(IOException ex) { - doAccept(null); - return; - } - try { - int srcWidth = image.getWidth(); - int srcHeight = image.getHeight(); - if(srcWidth < 64 || srcWidth > 512 || srcHeight < 32 || srcHeight > 512) { - doAccept(null); - return; - } - if(srcWidth != 64 || srcHeight != 64) { - if(srcWidth % 64 == 0) { - if(srcWidth == srcHeight * 2) { - BufferedImage scaled = new BufferedImage(64, 32, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = scaled.createGraphics(); - graphics.drawImage(image, 0, 0, 64, 32, 0, 0, srcWidth, srcHeight, null); - graphics.dispose(); - image = scaled; - srcWidth = 64; - srcHeight = 32; - }else if(srcWidth == srcHeight) { - BufferedImage scaled = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = scaled.createGraphics(); - graphics.drawImage(image, 0, 0, 64, 64, 0, 0, srcWidth, srcHeight, null); - graphics.dispose(); - image = scaled; - srcWidth = 64; - srcHeight = 64; - }else { - doAccept(null); - return; - } - }else { - doAccept(null); - return; - } - } - if(srcWidth == 64 && srcHeight == 64) { - int[] tmp = new int[4096]; - byte[] loadedPixels = new byte[16384]; - image.getRGB(0, 0, 64, 64, tmp, 0, 64); - SkinRescaler.convertToBytes(tmp, loadedPixels); - SkinPackets.setAlphaForChestV3(loadedPixels); - doAccept(loadedPixels); - return; - }else if(srcWidth == 64 && srcHeight == 32) { - int[] tmp1 = new int[2048]; - byte[] loadedPixels = new byte[16384]; - image.getRGB(0, 0, 64, 32, tmp1, 0, 64); - SkinRescaler.convert64x32To64x64(tmp1, loadedPixels); - SkinPackets.setAlphaForChestV3(loadedPixels); - doAccept(loadedPixels); - return; - }else { - doAccept(null); - return; - } - }catch(Throwable t) { - - } - } - } - - } - - private static class SkinCachingConsumer implements Consumer { - - protected final UUID skinUUID; - protected final String skinTexture; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected SkinCachingConsumer(UUID skinUUID, String skinTexture, ICacheProvider cacheProvider, - Consumer responseConsumer) { - this.skinUUID = skinUUID; - this.skinTexture = skinTexture; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - @Override - public void accept(byte[] skin) { - if(skin != null) { - try { - cacheProvider.cacheSkinByUUID(skinUUID, skinTexture, skin); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown writing new skin to database!", t); - } - responseConsumer.accept(skin); - }else { - responseConsumer.accept(null); - } - } - - } - - public static class CacheFetchedProfile { - - public final UUID uuid; - public final String username; - public final String texture; - public final UUID textureUUID; - public final String model; - - protected CacheFetchedProfile(UUID uuid, String username, String texture, String model) { - this.uuid = uuid; - this.username = username; - this.texture = texture; - this.textureUUID = SkinPackets.createEaglerURLSkinUUID(texture); - this.model = model; - } - - protected CacheFetchedProfile(CacheLoadedProfile profile) { - this.uuid = profile.uuid; - this.username = profile.username; - this.texture = profile.texture; - this.textureUUID = SkinPackets.createEaglerURLSkinUUID(profile.texture); - this.model = profile.model; - } - - } - - private static class ProfileConsumerImpl implements Consumer { - - protected final UUID uuid; - protected final Consumer responseConsumer; - - protected ProfileConsumerImpl(UUID uuid, Consumer responseConsumer) { - this.uuid = uuid; - this.responseConsumer = responseConsumer; - } - - protected void doAccept(CacheFetchedProfile v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown caching new profile!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String username = json.get("name").getAsString().toLowerCase(); - String texture = null; - String model = null; - JsonElement propsElement = json.get("properties"); - if(propsElement != null) { - try { - JsonArray properties = propsElement.getAsJsonArray(); - if(properties.size() > 0) { - for(int i = 0, l = properties.size(); i < l; ++i) { - JsonElement prop = properties.get(i); - if(prop.isJsonObject()) { - JsonObject propObj = prop.getAsJsonObject(); - if(propObj.get("name").getAsString().equals("textures")) { - String value = new String(Base64.decodeBase64(propObj.get("value").getAsString()), StandardCharsets.UTF_8); - JsonObject texturesJson = JsonParser.parseString(value).getAsJsonObject(); - if(texturesJson != null && texturesJson.has("textures")) { - texturesJson = texturesJson.getAsJsonObject("textures"); - JsonElement skin = texturesJson.get("SKIN"); - if(skin != null) { - model = "default"; - JsonObject skinObj = skin.getAsJsonObject(); - JsonElement urlElement = skinObj.get("url"); - if(urlElement != null && !urlElement.isJsonNull()) { - texture = urlElement.getAsString(); - } - JsonElement metaElement = skinObj.get("metadata"); - if(metaElement != null) { - JsonObject metaObj = metaElement.getAsJsonObject(); - JsonElement modelElement = metaObj.get("model"); - if(modelElement != null) { - model = modelElement.getAsString(); - } - } - } - } - break; - } - } - } - } - }catch(Throwable t2) { - } - } - if(texture == null && model == null) { - model = SkinService.isAlex(uuid) ? "slim" : "default"; - } - doAccept(new CacheFetchedProfile(uuid, username, texture, model)); - }catch(Throwable ex) { - doAccept(null); - } - } - } - - } - - private static class ProfileCachingConsumer implements Consumer { - - protected final UUID uuid; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected ProfileCachingConsumer(UUID uuid, ICacheProvider cacheProvider, Consumer responseConsumer) { - this.uuid = uuid; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - @Override - public void accept(CacheFetchedProfile profile) { - if(profile != null) { - try { - cacheProvider.cacheProfileByUUID(uuid, profile.username, profile.texture, profile.model); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown writing new profile to database!", t); - } - responseConsumer.accept(profile); - }else { - responseConsumer.accept(null); - } - } - - } - - private static class UsernameToUUIDConsumerImpl implements Consumer { - - protected final String username; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected UsernameToUUIDConsumerImpl(String username, ICacheProvider cacheProvider, Consumer responseConsumer) { - this.username = username; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - protected void doAccept(CacheFetchedProfile v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown caching new profile!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - try { - JsonObject json = (new JsonParser()).parse(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String loadUsername = json.get("name").getAsString().toLowerCase(); - if(!username.equals(loadUsername)) { - doAccept(null); - } - UUID mojangUUID = SkinService.parseMojangUUID(json.get("id").getAsString()); - lookupProfileByUUID(mojangUUID, cacheProvider, responseConsumer, false); - }catch(Throwable t) { - doAccept(null); - } - } - } - - } - - private static final SimpleRateLimiter rateLimitDownload = new SimpleRateLimiter(); - private static final SimpleRateLimiter rateLimitLookup = new SimpleRateLimiter(); - - public static void downloadSkin(String skinTexture, ICacheProvider cacheProvider, Consumer responseConsumer) { - downloadSkin(SkinPackets.createEaglerURLSkinUUID(skinTexture), skinTexture, cacheProvider, responseConsumer); - } - - public static void downloadSkin(UUID skinUUID, String skinTexture, ICacheProvider cacheProvider, Consumer responseConsumer) { - CacheLoadedSkin loadedSkin = cacheProvider.loadSkinByUUID(skinUUID); - if(loadedSkin == null) { - URI uri; - try { - uri = URI.create(skinTexture); - }catch(IllegalArgumentException ex) { - try { - responseConsumer.accept(null); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown handling invalid skin!", t); - } - throw new CancelException(); - } - int globalRatelimit = EaglerXBungee.getEagler().getConfig().getSkinRateLimitGlobal(); - boolean isRateLimit; - synchronized(rateLimitDownload) { - isRateLimit = !rateLimitDownload.rateLimit(globalRatelimit); - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", uri, new SkinConsumerImpl( - new SkinCachingConsumer(skinUUID, skinTexture, cacheProvider, responseConsumer))); - }else { - EaglerXBungee.logger().warning("skin system reached the global texture download ratelimit of " + globalRatelimit + " while downloading up \"" + skinTexture + "\""); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(loadedSkin.texture); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown processing cached skin!", t); - } - throw new CancelException(); - } - } - - public static void lookupProfileByUUID(UUID playerUUID, ICacheProvider cacheProvider, Consumer responseConsumer) { - lookupProfileByUUID(playerUUID, cacheProvider, responseConsumer, true); - } - - private static void lookupProfileByUUID(UUID playerUUID, ICacheProvider cacheProvider, Consumer responseConsumer, boolean rateLimit) { - CacheLoadedProfile profile = cacheProvider.loadProfileByUUID(playerUUID); - if(profile == null) { - URI requestURI = URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + SkinService.getMojangUUID(playerUUID)); - int globalRatelimit = EaglerXBungee.getEagler().getConfig().getUuidRateLimitGlobal(); - boolean isRateLimit; - if(rateLimit) { - synchronized(rateLimitLookup) { - isRateLimit = !rateLimitLookup.rateLimit(globalRatelimit); - } - }else { - isRateLimit = false; - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", requestURI, new ProfileConsumerImpl(playerUUID, - new ProfileCachingConsumer(playerUUID, cacheProvider, responseConsumer))); - }else { - EaglerXBungee.logger().warning("skin system reached the global UUID lookup ratelimit of " + globalRatelimit + " while looking up \"" + playerUUID + "\""); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(new CacheFetchedProfile(profile)); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown processing cached profile!", t); - } - throw new CancelException(); - } - } - - public static void lookupProfileByUsername(String playerUsername, ICacheProvider cacheProvider, Consumer responseConsumer) { - String playerUsernameLower = playerUsername.toLowerCase(); - CacheLoadedProfile profile = cacheProvider.loadProfileByUsername(playerUsernameLower); - if(profile == null) { - if(!playerUsernameLower.equals(playerUsernameLower.replaceAll("[^a-z0-9_]", "_").trim())) { - try { - responseConsumer.accept(null); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown processing invalid profile!", t); - } - throw new CancelException(); - } - URI requestURI = URI.create("https://api.mojang.com/users/profiles/minecraft/" + playerUsername); - int globalRatelimit = EaglerXBungee.getEagler().getConfig().getUuidRateLimitGlobal(); - boolean isRateLimit; - synchronized(rateLimitLookup) { - isRateLimit = !rateLimitLookup.rateLimit(globalRatelimit); - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", requestURI, new UsernameToUUIDConsumerImpl(playerUsername, cacheProvider, responseConsumer)); - }else { - EaglerXBungee.logger().warning("skin system reached the global UUID lookup ratelimit of " + globalRatelimit + " while looking up \"" + playerUsername + "\""); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(new CacheFetchedProfile(profile)); - }catch(Throwable t) { - EaglerXBungee.logger().log(Level.SEVERE, "Exception thrown processing cached profile!", t); - } - throw new CancelException(); - } - } - - public static class CancelException extends RuntimeException { - - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/BinaryHttpClient.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/BinaryHttpClient.java deleted file mode 100644 index 1b756918..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/BinaryHttpClient.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.URI; -import java.net.UnknownHostException; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import javax.net.ssl.SSLEngine; - -import org.apache.commons.lang3.ArrayUtils; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.ThreadFactoryBuilder; - -import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultHttpRequest; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpContent; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpObject; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.LastHttpContent; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.timeout.ReadTimeoutHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.md_5.bungee.netty.PipelineUtils; - -public class BinaryHttpClient { - - public static class Response { - - public final int code; - public final byte[] data; - public final Throwable exception; - - public Response(int code, byte[] data) { - this.code = code; - this.data = data; - this.exception = null; - } - - public Response(Throwable exception) { - this.code = -1; - this.data = null; - this.exception = exception; - } - - } - - private static class NettyHttpChannelFutureListener implements ChannelFutureListener { - - protected final String method; - protected final URI requestURI; - protected final Consumer responseCallback; - - protected NettyHttpChannelFutureListener(String method, URI requestURI, Consumer responseCallback) { - this.method = method; - this.requestURI = requestURI; - this.responseCallback = responseCallback; - } - - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isSuccess()) { - String path = requestURI.getRawPath() - + ((requestURI.getRawQuery() == null) ? "" : ("?" + requestURI.getRawQuery())); - HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, - HttpMethod.valueOf(method), path); - request.headers().set(HttpHeaderNames.HOST, (Object) requestURI.getHost()); - request.headers().set(HttpHeaderNames.USER_AGENT, "Mozilla/5.0 EaglerXBungee/" + EaglerXBungee.getEagler().getDescription().getVersion()); - future.channel().writeAndFlush(request); - } else { - addressCache.invalidate(requestURI.getHost()); - responseCallback.accept(new Response(new IOException("Connection failed"))); - } - } - - } - - private static class NettyHttpChannelInitializer extends ChannelInitializer { - - protected final Consumer responseCallback; - protected final boolean ssl; - protected final String host; - protected final int port; - - protected NettyHttpChannelInitializer(Consumer responseCallback, boolean ssl, String host, int port) { - this.responseCallback = responseCallback; - this.ssl = ssl; - this.host = host; - this.port = port; - } - - @Override - protected void initChannel(Channel ch) throws Exception { - ch.pipeline().addLast("timeout", new ReadTimeoutHandler(5L, TimeUnit.SECONDS)); - if (this.ssl) { - SSLEngine engine = SslContextBuilder.forClient().build().newEngine(ch.alloc(), host, port); - ch.pipeline().addLast("ssl", new SslHandler(engine)); - } - - ch.pipeline().addLast("http", new HttpClientCodec()); - ch.pipeline().addLast("handler", new NettyHttpResponseHandler(responseCallback)); - } - - } - - private static class NettyHttpResponseHandler extends SimpleChannelInboundHandler { - - protected final Consumer responseCallback; - protected int responseCode = -1; - protected ByteBuf buffer = null; - - protected NettyHttpResponseHandler(Consumer responseCallback) { - this.responseCallback = responseCallback; - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { - if (msg instanceof HttpResponse) { - HttpResponse response = (HttpResponse) msg; - responseCode = response.status().code(); - if (responseCode == HttpResponseStatus.NO_CONTENT.code()) { - this.done(ctx); - return; - } - } - if (msg instanceof HttpContent) { - HttpContent content = (HttpContent) msg; - if(buffer == null) { - buffer = ctx.alloc().buffer(); - } - this.buffer.writeBytes(content.content()); - if (msg instanceof LastHttpContent) { - this.done(ctx); - } - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - responseCallback.accept(new Response(cause)); - } - - private void done(ChannelHandlerContext ctx) { - try { - byte[] array; - if(buffer != null) { - array = new byte[buffer.readableBytes()]; - buffer.readBytes(array); - buffer.release(); - }else { - array = ArrayUtils.EMPTY_BYTE_ARRAY; - } - responseCallback.accept(new Response(responseCode, array)); - }finally { - ctx.channel().pipeline().remove(this); - ctx.channel().close(); - } - } - - } - - private static final Cache addressCache = CacheBuilder.newBuilder().expireAfterWrite(15L, TimeUnit.MINUTES).build(); - private static EventLoopGroup eventLoop = null; - - public static void asyncRequest(String method, URI uri, Consumer responseCallback) { - EventLoopGroup eventLoop = getEventLoopGroup(); - - int port = uri.getPort(); - boolean ssl = false; - String scheme = uri.getScheme(); - switch(scheme) { - case "http": - if(port == -1) { - port = 80; - } - break; - case "https": - if(port == -1) { - port = 443; - } - ssl = true; - break; - default: - responseCallback.accept(new Response(new UnsupportedOperationException("Unsupported scheme: " + scheme))); - return; - } - - String host = uri.getHost(); - InetAddress inetHost = addressCache.getIfPresent(host); - if (inetHost == null) { - try { - inetHost = InetAddress.getByName(host); - } catch (UnknownHostException ex) { - responseCallback.accept(new Response(ex)); - return; - } - addressCache.put(host, inetHost); - } - - (new Bootstrap()).channel(PipelineUtils.getChannel(null)).group(eventLoop) - .handler(new NettyHttpChannelInitializer(responseCallback, ssl, host, port)) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000).option(ChannelOption.TCP_NODELAY, true) - .remoteAddress(inetHost, port).connect() - .addListener(new NettyHttpChannelFutureListener(method, uri, responseCallback)); - } - - private static EventLoopGroup getEventLoopGroup() { - if(eventLoop == null) { - eventLoop = PipelineUtils.newEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Skin Download Thread #%1$d").build()); - } - return eventLoop; - } - - public static void killEventLoop() { - if(eventLoop != null) { - EaglerXBungee.logger().info("Stopping skin cache HTTP client..."); - eventLoop.shutdownGracefully(); - try { - eventLoop.awaitTermination(30l, TimeUnit.SECONDS); - } catch (InterruptedException var13) { - ; - } - eventLoop = null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapePackets.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapePackets.java deleted file mode 100644 index 7c0ef208..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapePackets.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; - -public class CapePackets { - - public static final int PACKET_MY_CAPE_PRESET = 0x01; - public static final int PACKET_MY_CAPE_CUSTOM = 0x02; - - public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, CapeServiceOffline capeService) throws IOException { - if(bs.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - GameMessagePacket generatedPacket; - int packetType = (int)bs[0] & 0xFF; - switch(packetType) { - case PACKET_MY_CAPE_PRESET: - if(bs.length != 5) { - throw new IOException("Invalid length " + bs.length + " for preset cape packet"); - } - generatedPacket = new SPacketOtherCapePresetEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); - break; - case PACKET_MY_CAPE_CUSTOM: - if(bs.length != 1174) { - throw new IOException("Invalid length " + bs.length + " for custom cape packet"); - } - byte[] capePixels = new byte[bs.length - 1]; - System.arraycopy(bs, 1, capePixels, 0, capePixels.length); - generatedPacket = new SPacketOtherCapeCustomEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), capePixels); - break; - default: - throw new IOException("Unknown skin packet type: " + packetType); - } - capeService.registerEaglercraftPlayer(clientUUID, generatedPacket); - } - - public static void registerEaglerPlayerFallback(UUID clientUUID, CapeServiceOffline capeService) { - capeService.registerEaglercraftPlayer(clientUUID, new SPacketOtherCapePresetEAG( - clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), 0)); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java deleted file mode 100644 index 817f1066..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2024-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientCapeCustomV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientCapePresetV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; -import net.md_5.bungee.UserConnection; - -public class CapeServiceOffline { - - public static final int masterRateLimitPerPlayer = 250; - - private final ConcurrentMap capesCache = new ConcurrentHashMap<>(); - - public void registerEaglercraftPlayer(UUID playerUUID, GameMessagePacket capePacket) { - capesCache.put(playerUUID, capePacket); - } - - public void processGetOtherCape(UUID searchUUID, UserConnection sender) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(initialHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - GameMessagePacket maybeCape = capesCache.get(searchUUID); - if(maybeCape != null) { - initialHandler.sendEaglerMessage(maybeCape); - }else { - initialHandler.sendEaglerMessage(new SPacketOtherCapePresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - } - } - } - - public void processForceCape(UUID clientUUID, EaglerInitialHandler initialHandler) { - GameMessagePacket maybeCape = capesCache.get(clientUUID); - if(maybeCape != null) { - if (maybeCape instanceof SPacketOtherCapePresetEAG) { - initialHandler.sendEaglerMessage( - new SPacketForceClientCapePresetV4EAG(((SPacketOtherCapePresetEAG) maybeCape).presetCape)); - } else if (maybeCape instanceof SPacketOtherCapeCustomEAG) { - initialHandler.sendEaglerMessage( - new SPacketForceClientCapeCustomV4EAG(((SPacketOtherCapeCustomEAG) maybeCape).customCape)); - } - } - } - - public void unregisterPlayer(UUID playerUUID) { - capesCache.remove(playerUUID); - } - - public GameMessagePacket getCape(UUID clientUUID) { - return capesCache.get(clientUUID); - } - - public byte[] getCapeHandshakeData(UUID clientUUID) { - GameMessagePacket capePacket = getCape(clientUUID); - if(capePacket != null) { - if(capePacket instanceof SPacketOtherCapeCustomEAG) { - SPacketOtherCapeCustomEAG pkt = (SPacketOtherCapeCustomEAG)capePacket; - byte[] ret = new byte[1174]; - ret[0] = (byte)2; - System.arraycopy(pkt.customCape, 0, ret, 1, 1173); - return ret; - }else { - SPacketOtherCapePresetEAG pkt = (SPacketOtherCapePresetEAG)capePacket; - int p = pkt.presetCape; - byte[] ret = new byte[5]; - ret[0] = (byte)1; - ret[1] = (byte)(p >>> 24); - ret[2] = (byte)(p >>> 16); - ret[3] = (byte)(p >>> 8); - ret[4] = (byte)(p & 0xFF); - return ret; - } - }else { - return null; - } - } - - public void shutdown() { - capesCache.clear(); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ICacheProvider.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ICacheProvider.java deleted file mode 100644 index 5158d2c6..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ICacheProvider.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.util.UUID; - -public interface ICacheProvider { - - public static class CacheException extends RuntimeException { - - public CacheException() { - super(); - } - - public CacheException(String message, Throwable cause) { - super(message, cause); - } - - public CacheException(String message) { - super(message); - } - - public CacheException(Throwable cause) { - super(cause); - } - - } - - public static class CacheLoadedSkin { - - public final UUID uuid; - public final String url; - public final byte[] texture; - - public CacheLoadedSkin(UUID uuid, String url, byte[] texture) { - this.uuid = uuid; - this.url = url; - this.texture = texture; - } - - } - - public static class CacheLoadedProfile { - - public final UUID uuid; - public final String username; - public final String texture; - public final String model; - - public CacheLoadedProfile(UUID uuid, String username, String texture, String model) { - this.uuid = uuid; - this.username = username; - this.texture = texture; - this.model = model; - } - - public UUID getSkinUUID() { - return SkinPackets.createEaglerURLSkinUUID(texture); - } - - } - - CacheLoadedSkin loadSkinByUUID(UUID uuid) throws CacheException; - - void cacheSkinByUUID(UUID uuid, String url, byte[] textureBlob) throws CacheException; - - CacheLoadedProfile loadProfileByUUID(UUID uuid) throws CacheException; - - CacheLoadedProfile loadProfileByUsername(String username) throws CacheException; - - void cacheProfileByUUID(UUID uuid, String username, String texture, String model) throws CacheException; - - void flush() throws CacheException; - - void destroy(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ISkinService.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ISkinService.java deleted file mode 100644 index 4cf2d64e..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/ISkinService.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.UserConnection; - -public interface ISkinService { - - void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles); - - void processGetOtherSkin(final UUID searchUUID, final UserConnection sender); - - void processGetOtherSkin(UUID searchUUID, String skinURL, UserConnection sender); - - void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId); - - void unregisterPlayer(UUID clientUUID); - - default void registerTextureToPlayerAssociation(String textureURL, UUID playerUUID) { - registerTextureToPlayerAssociation(SkinPackets.createEaglerURLSkinUUID(textureURL), playerUUID); - } - - void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID); - - void flush(); - - void shutdown(); - - void processForceSkin(UUID playerUUID, EaglerInitialHandler initialHandler); - - SkinPacketVersionCache getSkin(UUID playerUUID); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/JDBCCacheProvider.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/JDBCCacheProvider.java deleted file mode 100644 index cfba992d..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/JDBCCacheProvider.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; -import java.util.UUID; -import java.util.logging.Level; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import org.apache.commons.lang3.ArrayUtils; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.sqlite.EaglerDrivers; - -public class JDBCCacheProvider implements ICacheProvider { - - public static JDBCCacheProvider initialize(String uri, String driverClass, String driverPath, int keepObjectsDays, - int keepProfilesDays, int maxObjects, int maxProfiles) throws CacheException { - Connection conn; - try { - conn = EaglerDrivers.connectToDatabase(uri, driverClass, driverPath, new Properties()); - if(conn == null) { - throw new IllegalStateException("Connection is null"); - } - }catch(Throwable t) { - throw new CacheException("Could not initialize '" + uri + "'!", t); - } - EaglerXBungee.logger().info("Connected to database: " + uri); - try { - try(Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE IF NOT EXISTS " - + "\"eaglercraft_skins_objects\" (" - + "\"TextureUUID\" TEXT(32) NOT NULL," - + "\"TextureURL\" VARCHAR(256) NOT NULL," - + "\"TextureTime\" DATETIME NOT NULL," - + "\"TextureData\" BLOB," - + "\"TextureLength\" INT(24) NOT NULL," - + "PRIMARY KEY(\"TextureUUID\"))"); - stmt.execute("CREATE TABLE IF NOT EXISTS " - + "\"eaglercraft_skins_profiles\" (" - + "\"ProfileUUID\" TEXT(32) NOT NULL," - + "\"ProfileName\" TEXT(16) NOT NULL," - + "\"ProfileTime\" DATETIME NOT NULL," - + "\"ProfileTexture\" VARCHAR(256)," - + "\"ProfileModel\" VARCHAR(16) NOT NULL," - + "PRIMARY KEY(\"ProfileUUID\"))"); - stmt.execute("CREATE INDEX IF NOT EXISTS \"profile_name_index\" " - + "ON \"eaglercraft_skins_profiles\" (\"ProfileName\")"); - } - JDBCCacheProvider cacheProvider = new JDBCCacheProvider(conn, uri, keepObjectsDays, keepProfilesDays, maxObjects, maxProfiles); - cacheProvider.flush(); - return cacheProvider; - }catch(CacheException ex) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw ex; - }catch(Throwable t) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw new CacheException("Could not initialize '" + uri + "'!", t); - } - } - - protected final Connection connection; - protected final String uri; - - protected final PreparedStatement discardExpiredObjects; - protected final PreparedStatement discardExpiredProfiles; - protected final PreparedStatement getTotalObjects; - protected final PreparedStatement getTotalProfiles; - protected final PreparedStatement deleteSomeOldestObjects; - protected final PreparedStatement deleteSomeOldestProfiles; - protected final PreparedStatement querySkinByUUID; - protected final PreparedStatement queryProfileByUUID; - protected final PreparedStatement queryProfileByUsername; - protected final PreparedStatement cacheNewSkin; - protected final PreparedStatement cacheNewProfile; - protected final PreparedStatement cacheHasSkin; - protected final PreparedStatement cacheHasProfile; - protected final PreparedStatement cacheUpdateSkin; - protected final PreparedStatement cacheUpdateProfile; - - protected long lastFlush; - - protected int keepObjectsDays; - protected int keepProfilesDays; - protected int maxObjects; - protected int maxProfiles; - - protected JDBCCacheProvider(Connection conn, String uri, int keepObjectsDays, int keepProfilesDays, int maxObjects, - int maxProfiles) throws SQLException { - this.connection = conn; - this.uri = uri; - this.lastFlush = 0l; - this.keepObjectsDays = keepObjectsDays; - this.keepProfilesDays = keepProfilesDays; - this.maxObjects = maxObjects; - this.maxProfiles = maxProfiles; - - this.discardExpiredObjects = connection.prepareStatement("DELETE FROM eaglercraft_skins_objects WHERE textureTime < ?"); - this.discardExpiredProfiles = connection.prepareStatement("DELETE FROM eaglercraft_skins_profiles WHERE profileTime < ?"); - this.getTotalObjects = connection.prepareStatement("SELECT COUNT(*) AS total_objects FROM eaglercraft_skins_objects"); - this.getTotalProfiles = connection.prepareStatement("SELECT COUNT(*) AS total_profiles FROM eaglercraft_skins_profiles"); - this.deleteSomeOldestObjects = connection.prepareStatement("DELETE FROM eaglercraft_skins_objects WHERE TextureUUID IN (SELECT TextureUUID FROM eaglercraft_skins_objects ORDER BY TextureTime ASC LIMIT ?)"); - this.deleteSomeOldestProfiles = connection.prepareStatement("DELETE FROM eaglercraft_skins_profiles WHERE ProfileUUID IN (SELECT ProfileUUID FROM eaglercraft_skins_profiles ORDER BY ProfileTime ASC LIMIT ?)"); - this.querySkinByUUID = connection.prepareStatement("SELECT TextureURL,TextureData,TextureLength FROM eaglercraft_skins_objects WHERE TextureUUID = ? LIMIT 1"); - this.queryProfileByUUID = connection.prepareStatement("SELECT ProfileName,ProfileTexture,ProfileModel FROM eaglercraft_skins_profiles WHERE ProfileUUID = ? LIMIT 1"); - this.queryProfileByUsername = connection.prepareStatement("SELECT ProfileUUID,ProfileTexture,ProfileModel FROM eaglercraft_skins_profiles WHERE ProfileName = ? LIMIT 1"); - this.cacheNewSkin = connection.prepareStatement("INSERT INTO eaglercraft_skins_objects (TextureUUID, TextureURL, TextureTime, TextureData, TextureLength) VALUES(?, ?, ?, ?, ?)"); - this.cacheNewProfile = connection.prepareStatement("INSERT INTO eaglercraft_skins_profiles (ProfileUUID, ProfileName, ProfileTime, ProfileTexture, ProfileModel) VALUES(?, ?, ?, ?, ?)"); - this.cacheHasSkin = connection.prepareStatement("SELECT COUNT(TextureUUID) AS has_object FROM eaglercraft_skins_objects WHERE TextureUUID = ? LIMIT 1"); - this.cacheHasProfile = connection.prepareStatement("SELECT COUNT(ProfileUUID) AS has_profile FROM eaglercraft_skins_profiles WHERE ProfileUUID = ? LIMIT 1"); - this.cacheUpdateSkin = connection.prepareStatement("UPDATE eaglercraft_skins_objects SET TextureURL = ?, TextureTime = ?, TextureData = ?, TextureLength = ? WHERE TextureUUID = ?"); - this.cacheUpdateProfile = connection.prepareStatement("UPDATE eaglercraft_skins_profiles SET ProfileName = ?, ProfileTime = ?, ProfileTexture = ?, ProfileModel = ? WHERE ProfileUUID = ?"); - } - - public CacheLoadedSkin loadSkinByUUID(UUID uuid) throws CacheException { - String uuidString = SkinService.getMojangUUID(uuid); - String queriedUrls; - byte[] queriedTexture; - int queriedLength; - try { - synchronized(querySkinByUUID) { - querySkinByUUID.setString(1, uuidString); - try(ResultSet resultSet = querySkinByUUID.executeQuery()) { - if(resultSet.next()) { - queriedUrls = resultSet.getString(1); - queriedTexture = resultSet.getBytes(2); - queriedLength = resultSet.getInt(3); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading cached skin", ex); - } - if(queriedLength == 0) { - return new CacheLoadedSkin(uuid, queriedUrls, ArrayUtils.EMPTY_BYTE_ARRAY); - }else { - byte[] decompressed = new byte[queriedLength]; - try { - GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream(queriedTexture)); - int i = 0, j = 0; - while(j < queriedLength && (i = is.read(decompressed, j, queriedLength - j)) != -1) { - j += i; - } - }catch(IOException ex) { - throw new CacheException("SQL query failure while loading cached skin"); - } - return new CacheLoadedSkin(uuid, queriedUrls, decompressed); - } - } - - public void cacheSkinByUUID(UUID uuid, String url, byte[] textureBlob) throws CacheException { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - GZIPOutputStream deflateOut = new GZIPOutputStream(bao); - deflateOut.write(textureBlob); - deflateOut.close(); - }catch(IOException ex) { - throw new CacheException("Skin compression error", ex); - } - int len; - byte[] textureBlobCompressed; - if(textureBlob == null || textureBlob.length == 0) { - len = 0; - textureBlobCompressed = null; - }else { - len = textureBlob.length; - textureBlobCompressed = bao.toByteArray(); - } - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(cacheNewSkin) { - boolean has; - cacheHasSkin.setString(1, uuidString); - try(ResultSet resultSet = cacheHasSkin.executeQuery()) { - if(resultSet.next()) { - has = resultSet.getInt(1) > 0; - }else { - has = false; // ?? - } - } - if(has) { - cacheUpdateSkin.setString(1, url); - cacheUpdateSkin.setDate(2, new Date(System.currentTimeMillis())); - cacheUpdateSkin.setBytes(3, textureBlobCompressed); - cacheUpdateSkin.setInt(4, len); - cacheUpdateSkin.setString(5, uuidString); - cacheUpdateSkin.executeUpdate(); - }else { - cacheNewSkin.setString(1, uuidString); - cacheNewSkin.setString(2, url); - cacheNewSkin.setDate(3, new Date(System.currentTimeMillis())); - cacheNewSkin.setBytes(4, textureBlobCompressed); - cacheNewSkin.setInt(5, len); - cacheNewSkin.executeUpdate(); - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while caching new skin", ex); - } - } - - public CacheLoadedProfile loadProfileByUUID(UUID uuid) throws CacheException { - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(queryProfileByUUID) { - queryProfileByUUID.setString(1, uuidString); - try(ResultSet resultSet = queryProfileByUUID.executeQuery()) { - if(resultSet.next()) { - String profileName = resultSet.getString(1); - String profileTexture = resultSet.getString(2); - String profileModel = resultSet.getString(3); - return new CacheLoadedProfile(uuid, profileName, profileTexture, profileModel); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading profile by uuid", ex); - } - } - - public CacheLoadedProfile loadProfileByUsername(String username) throws CacheException { - try { - synchronized(queryProfileByUsername) { - queryProfileByUsername.setString(1, username); - try(ResultSet resultSet = queryProfileByUsername.executeQuery()) { - if(resultSet.next()) { - UUID profileUUID = SkinService.parseMojangUUID(resultSet.getString(1)); - String profileTexture = resultSet.getString(2); - String profileModel = resultSet.getString(3); - return new CacheLoadedProfile(profileUUID, username, profileTexture, profileModel); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading profile by username", ex); - } - } - - public void cacheProfileByUUID(UUID uuid, String username, String texture, String model) throws CacheException { - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(cacheNewProfile) { - boolean has; - cacheHasProfile.setString(1, uuidString); - try(ResultSet resultSet = cacheHasProfile.executeQuery()) { - if(resultSet.next()) { - has = resultSet.getInt(1) > 0; - }else { - has = false; // ?? - } - } - if(has) { - cacheUpdateProfile.setString(1, username); - cacheUpdateProfile.setDate(2, new Date(System.currentTimeMillis())); - cacheUpdateProfile.setString(3, texture); - cacheUpdateProfile.setString(4, model); - cacheUpdateProfile.setString(5, uuidString); - cacheUpdateProfile.executeUpdate(); - }else { - cacheNewProfile.setString(1, uuidString); - cacheNewProfile.setString(2, username); - cacheNewProfile.setDate(3, new Date(System.currentTimeMillis())); - cacheNewProfile.setString(4, texture); - cacheNewProfile.setString(5, model); - cacheNewProfile.executeUpdate(); - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while caching new profile", ex); - } - } - - @Override - public void flush() { - long millis = System.currentTimeMillis(); - long steadyMillis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - if(steadyMillis - lastFlush > 1200000l) { // 30 minutes - lastFlush = steadyMillis; - try { - Date expiryObjects = new Date(millis - keepObjectsDays * 86400000l); - Date expiryProfiles = new Date(millis - keepProfilesDays * 86400000l); - - synchronized(discardExpiredObjects) { - discardExpiredObjects.setDate(1, expiryObjects); - discardExpiredObjects.execute(); - } - synchronized(discardExpiredProfiles) { - discardExpiredProfiles.setDate(1, expiryProfiles); - discardExpiredProfiles.execute(); - } - - int totalObjects, totalProfiles; - - synchronized(getTotalObjects) { - try(ResultSet resultSet = getTotalObjects.executeQuery()) { - if(resultSet.next()) { - totalObjects = resultSet.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved when checking \"eaglercraft_skins_objects\" row count"); - } - } - } - - synchronized(getTotalProfiles) { - try(ResultSet resultSet = getTotalProfiles.executeQuery()) { - if(resultSet.next()) { - totalProfiles = resultSet.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved when checking \"eaglercraft_skins_profiles\" row count"); - } - } - } - - if(totalObjects > maxObjects) { - int deleteCount = totalObjects - maxObjects + (maxObjects >> 3); - EaglerXBungee.logger().warning("Skin object cache has passed " + maxObjects + " skins in size (" - + totalObjects + "), deleting " + deleteCount + " skins from the cache to free space"); - synchronized(deleteSomeOldestObjects) { - deleteSomeOldestObjects.setInt(1, deleteCount); - deleteSomeOldestObjects.executeUpdate(); - } - } - - if(totalProfiles > maxProfiles) { - int deleteCount = totalProfiles - maxProfiles + (maxProfiles >> 3); - EaglerXBungee.logger().warning("Skin profile cache has passed " + maxProfiles + " profiles in size (" - + totalProfiles + "), deleting " + deleteCount + " profiles from the cache to free space"); - synchronized(deleteSomeOldestProfiles) { - deleteSomeOldestProfiles.setInt(1, deleteCount); - deleteSomeOldestProfiles.executeUpdate(); - } - } - - }catch(SQLException ex) { - throw new CacheException("SQL query failure while flushing cache!", ex); - } - } - } - - private void destroyStatement(Statement stmt) { - try { - stmt.close(); - } catch (SQLException e) { - } - } - - @Override - public void destroy() { - destroyStatement(discardExpiredObjects); - destroyStatement(discardExpiredProfiles); - destroyStatement(getTotalObjects); - destroyStatement(getTotalProfiles); - destroyStatement(deleteSomeOldestObjects); - destroyStatement(deleteSomeOldestProfiles); - destroyStatement(querySkinByUUID); - destroyStatement(queryProfileByUUID); - destroyStatement(queryProfileByUsername); - destroyStatement(cacheNewSkin); - destroyStatement(cacheNewProfile); - destroyStatement(cacheHasSkin); - destroyStatement(cacheHasProfile); - destroyStatement(cacheUpdateSkin); - destroyStatement(cacheUpdateProfile); - try { - connection.close(); - EaglerXBungee.logger().info("Successfully disconnected from database '" + uri + "'"); - } catch (SQLException e) { - EaglerXBungee.logger().log(Level.WARNING, "Exception disconnecting from database '" + uri + "'!", e); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SimpleRateLimiter.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SimpleRateLimiter.java deleted file mode 100644 index b12ab6c4..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SimpleRateLimiter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; - -public class SimpleRateLimiter { - - private long timer; - private int count; - - public SimpleRateLimiter() { - timer = EaglerXBungeeAPIHelper.steadyTimeMillis(); - count = 0; - } - - public boolean rateLimit(int maxPerMinute) { - int t = 60000 / maxPerMinute; - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - int decr = (int)(millis - timer) / t; - if(decr > 0) { - timer += decr * t; - count -= decr; - if(count < 0) { - count = 0; - } - } - if(count >= maxPerMinute) { - return false; - }else { - ++count; - return true; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinPackets.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinPackets.java deleted file mode 100644 index 1fb94421..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinPackets.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV3EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class SkinPackets { - - public static final int PACKET_MY_SKIN_PRESET = 0x01; - public static final int PACKET_MY_SKIN_CUSTOM = 0x02; - - public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, ISkinService skinService, int protocolVers) throws IOException { - if(bs.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - GameMessagePacket generatedPacketV3 = null; - GameMessagePacket generatedPacketV4 = null; - int skinModel = -1; - int packetType = (int)bs[0] & 0xFF; - switch(packetType) { - case PACKET_MY_SKIN_PRESET: - if(bs.length != 5) { - throw new IOException("Invalid length " + bs.length + " for preset skin packet"); - } - generatedPacketV3 = generatedPacketV4 = new SPacketOtherSkinPresetEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); - break; - case PACKET_MY_SKIN_CUSTOM: - if(protocolVers <= 3) { - byte[] pixels = new byte[16384]; - if(bs.length != 2 + pixels.length) { - throw new IOException("Invalid length " + bs.length + " for custom skin packet"); - } - setAlphaForChestV3(pixels); - System.arraycopy(bs, 2, pixels, 0, pixels.length); - generatedPacketV3 = new SPacketOtherSkinCustomV3EAG(clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), (skinModel = (int)bs[1] & 0xFF), pixels); - }else { - byte[] pixels = new byte[12288]; - if(bs.length != 2 + pixels.length) { - throw new IOException("Invalid length " + bs.length + " for custom skin packet"); - } - setAlphaForChestV4(pixels); - System.arraycopy(bs, 2, pixels, 0, pixels.length); - generatedPacketV4 = new SPacketOtherSkinCustomV4EAG(clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), (skinModel = (int)bs[1] & 0xFF), pixels); - } - break; - default: - throw new IOException("Unknown skin packet type: " + packetType); - } - skinService.registerEaglercraftPlayer(clientUUID, new SkinPacketVersionCache(generatedPacketV3, generatedPacketV4), skinModel); - } - - public static void registerEaglerPlayerFallback(UUID clientUUID, ISkinService skinService) throws IOException { - int skinModel = (clientUUID.hashCode() & 1) != 0 ? 1 : 0; - skinService.registerEaglercraftPlayer(clientUUID, SkinPacketVersionCache.createPreset( - clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), skinModel), skinModel); - } - - public static void setAlphaForChestV3(byte[] skin64x64) { - if(skin64x64.length != 16384) { - throw new IllegalArgumentException("Skin is not 64x64!"); - } - for(int y = 20; y < 32; ++y) { - for(int x = 16; x < 40; ++x) { - skin64x64[(y << 8) | (x << 2)] = (byte)0xFF; - } - } - } - - public static void setAlphaForChestV4(byte[] skin64x64) { - if(skin64x64.length != 12288) { - throw new IllegalArgumentException("Skin is not 64x64!"); - } - for(int y = 20; y < 32; ++y) { - for(int x = 16; x < 40; ++x) { - skin64x64[((y << 6) | x) * 3] |= 0x80; - } - } - } - - public static String bytesToAscii(byte[] bytes, int off, int len) { - char[] ret = new char[len]; - for(int i = 0; i < len; ++i) { - ret[i] = (char)((int)bytes[off + i] & 0xFF); - } - return new String(ret); - } - - public static String bytesToAscii(byte[] bytes) { - return bytesToAscii(bytes, 0, bytes.length); - } - - public static byte[] asciiString(String string) { - byte[] str = new byte[string.length()]; - for(int i = 0; i < str.length; ++i) { - str[i] = (byte)string.charAt(i); - } - return str; - } - - public static UUID createEaglerURLSkinUUID(String skinUrl) { - return UUID.nameUUIDFromBytes(asciiString("EaglercraftSkinURL:" + skinUrl)); - } - - public static int getModelId(String modelName) { - return "slim".equalsIgnoreCase(modelName) ? 1 : 0; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinRescaler.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinRescaler.java deleted file mode 100644 index 9ae26cce..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinRescaler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -public class SkinRescaler { - - public static void convertToBytes(int[] imageIn, byte[] imageOut) { - for(int i = 0, j, k; i < imageIn.length; ++i) { - j = i << 2; - k = imageIn[i]; - imageOut[j] = (byte)(k >>> 24); - imageOut[j + 1] = (byte)(k & 0xFF); - imageOut[j + 2] = (byte)(k >>> 8); - imageOut[j + 3] = (byte)(k >>> 16); - } - } - - public static void convert64x32To64x64(int[] imageIn, byte[] imageOut) { - copyRawPixels(imageIn, imageOut, 0, 0, 0, 0, 64, 32, 64, 64, false); - copyRawPixels(imageIn, imageOut, 24, 48, 20, 52, 4, 16, 8, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 28, 48, 24, 52, 8, 16, 12, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 20, 52, 16, 64, 8, 20, 12, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 24, 52, 20, 64, 4, 20, 8, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 28, 52, 24, 64, 0, 20, 4, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 32, 52, 28, 64, 12, 20, 16, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 40, 48, 36, 52, 44, 16, 48, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 44, 48, 40, 52, 48, 16, 52, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 36, 52, 32, 64, 48, 20, 52, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 40, 52, 36, 64, 44, 20, 48, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 44, 52, 40, 64, 40, 20, 44, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 48, 52, 44, 64, 52, 20, 56, 32, 64, 64); - } - - private static void copyRawPixels(int[] imageIn, byte[] imageOut, int dx1, int dy1, int dx2, int dy2, int sx1, - int sy1, int sx2, int sy2, int imgSrcWidth, int imgDstWidth) { - if(dx1 > dx2) { - copyRawPixels(imageIn, imageOut, sx1, sy1, dx2, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, true); - } else { - copyRawPixels(imageIn, imageOut, sx1, sy1, dx1, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, false); - } - } - - private static void copyRawPixels(int[] imageIn, byte[] imageOut, int srcX, int srcY, int dstX, int dstY, int width, - int height, int imgSrcWidth, int imgDstWidth, boolean flip) { - int i, j; - for(int y = 0; y < height; ++y) { - for(int x = 0; x < width; ++x) { - i = imageIn[(srcY + y) * imgSrcWidth + srcX + x]; - if(flip) { - j = (dstY + y) * imgDstWidth + dstX + width - x - 1; - }else { - j = (dstY + y) * imgDstWidth + dstX + x; - } - j = j << 2; - imageOut[j] = (byte)(i >>> 24); - imageOut[j + 1] = (byte)(i & 0xFF); - imageOut[j + 2] = (byte)(i >>> 8); - imageOut[j + 3] = (byte)(i >>> 16); - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java deleted file mode 100644 index 06e60cc4..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java +++ /dev/null @@ -1,1450 +0,0 @@ -/* - * Copyright (c) 2022-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Consumer; -import org.apache.commons.codec.binary.Base64; - -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import gnu.trove.map.TObjectIntMap; -import gnu.trove.map.hash.TObjectIntHashMap; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.AsyncSkinProvider.CacheFetchedProfile; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins.AsyncSkinProvider.CancelException; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientSkinPresetV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.connection.LoginResult; -import net.md_5.bungee.protocol.Property; - -public class SkinService implements ISkinService { - - public static final int masterRateLimitPerPlayer = 250; - - private final ConcurrentMap onlinePlayersCache = new ConcurrentHashMap<>(); - private final ConcurrentMap onlinePlayersToTexturesMap = new ConcurrentHashMap<>(); - private final ConcurrentMap foreignSkinCache = new ConcurrentHashMap<>(); - - private final ReadWriteLock onlinePlayersFromTexturesMapLock = new ReentrantReadWriteLock(); - private final Multimap onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build(); - - private final Map pendingTextures = new HashMap<>(); - private final Map pendingUUIDs = new HashMap<>(); - private final Map pendingNameLookups = new HashMap<>(); - - private final ReadWriteLock antagonistsLock = new ReentrantReadWriteLock(); - private final TObjectIntMap antagonists = new TObjectIntHashMap<>(); - - private long antagonistCooldown = EaglerXBungeeAPIHelper.steadyTimeMillis(); - - private final Consumer> antagonistLogger = new Consumer>() { - - @Override - public void accept(Set t) { - if(t.size() == 1) { - int limit = EaglerXBungee.getEagler().getConfig().getAntagonistsRateLimit() << 1; - UUID offender = t.iterator().next(); - antagonistsLock.writeLock().lock(); - try { - int v = antagonists.get(offender); - if(v == antagonists.getNoEntryValue()) { - antagonists.put(offender, 1); - }else { - if(v <= limit) { - antagonists.put(offender, v + 1); - } - } - }finally { - antagonistsLock.writeLock().unlock(); - } - } - } - - }; - - private ICacheProvider cacheProvider = null; - - protected static class CachedForeignSkin { - - protected final UUID uuid; - protected final SkinPacketVersionCache data; - protected final int modelKnown; - protected volatile long lastHit; - - protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) { - this.uuid = uuid; - this.data = data; - this.modelKnown = modelKnown; - this.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - } - - } - - protected static class CachedPlayerSkin { - - protected final SkinPacketVersionCache data; - protected final UUID textureUUID; - protected final int modelId; - - protected CachedPlayerSkin(SkinPacketVersionCache data, UUID textureUUID, int modelId) { - this.data = data; - this.textureUUID = textureUUID; - this.modelId = modelId; - } - - } - - protected class PendingTextureDownload implements Consumer { - - protected final UUID textureUUID; - protected final String textureURL; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingTextureDownload(UUID textureUUID, String textureURL, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.textureUUID = textureUUID; - this.textureURL = textureURL; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXBungeeAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(byte[] t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingTextures) { - finalized = true; - pendingTextures.remove(textureUUID); - } - } - } - - } - - protected class PendingProfileUUIDLookup implements Consumer { - - protected final UUID profileUUID; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.profileUUID = profileUUID; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXBungeeAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(CacheFetchedProfile t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingUUIDs) { - finalized = true; - pendingUUIDs.remove(profileUUID); - } - } - } - - } - - protected class PendingProfileNameLookup implements Consumer { - - protected final String profileName; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingProfileNameLookup(String profileName, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.profileName = profileName; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXBungeeAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(CacheFetchedProfile t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingNameLookups) { - finalized = true; - pendingNameLookups.remove(profileName); - } - } - } - - } - - public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles) { - antagonistCooldown = EaglerXBungeeAPIHelper.steadyTimeMillis(); - if(cacheProvider == null) { - cacheProvider = JDBCCacheProvider.initialize(uri, driverClass, driverPath, keepObjectsDays, - keepProfilesDays, maxObjects, maxProfiles); - } - resetMaps(); - } - - public void processGetOtherSkin(final UUID searchUUID, final UserConnection sender) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(!eaglerHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - return; - } - - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(searchUUID); - - if(maybeCachedPacket != null) { - eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.get(eaglerHandler.getEaglerProtocol())); - }else { - ProxiedPlayer player = BungeeCord.getInstance().getPlayer(searchUUID); - UUID playerTexture = onlinePlayersToTexturesMap.get(searchUUID); - if(playerTexture != null) { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( - maybeCachedPacket.data, searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits()); - if(player != null) { - onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten, - maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); - } - eaglerHandler.sendEaglerMessage(rewritten.get(eaglerHandler.getEaglerProtocol())); - return; - } - } - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture); - if(foreignSkin != null && foreignSkin.modelKnown != -1) { - if(player != null) { - onlinePlayersCache.put(searchUUID, - new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, - searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()), - playerTexture, foreignSkin.modelKnown)); - foreignSkinCache.remove(playerTexture); - }else { - foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - } - eaglerHandler.sendEaglerMessage(foreignSkin.data.get(eaglerHandler.getEaglerProtocol())); - return; - } - } - if(player != null && (player instanceof UserConnection)) { - LoginResult loginProfile = ((UserConnection)player).getPendingConnection().getLoginProfile(); - if(loginProfile != null) { - Property[] props = loginProfile.getProperties(); - if(props.length > 0) { - for(int i = 0; i < props.length; ++i) { - Property pp = props[i]; - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = sanitizeTextureURL(url.getAsString()); - if(urlStr == null) { - break; - } - int model = 0; - JsonElement el = skinObj.get("metadata"); - if(el != null && el.isJsonObject()) { - el = el.getAsJsonObject().get("model"); - if(el != null) { - model = SkinPackets.getModelId(el.getAsString()); - } - } - UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr); - - CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID); - if(foreignSkin != null) { - registerTextureToPlayerAssociation(skinUUID, searchUUID); - SkinPacketVersionCache rewrite = SkinPacketVersionCache - .rewriteUUIDModel(foreignSkin.data, - searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), model); - onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model)); - eaglerHandler.sendEaglerMessage(rewrite.get(eaglerHandler.getEaglerProtocol())); - return; - } - - // download player skin, put in onlinePlayersCache, no limit - - if(!isLimitedAsAntagonist(player.getUniqueId())) { - final int modelf = model; - doAsync(() -> { - processResolveURLTextureForOnline(sender, searchUUID, skinUUID, urlStr, modelf); - }); - } - - return; - } - } - }catch(Throwable t) { - } - } - } - } - } - if(!isLimitedAsAntagonist(player.getUniqueId())) { - doAsync(() -> { - if(player.getPendingConnection().isOnlineMode()) { - processResolveProfileTextureByUUIDForOnline(sender, searchUUID); - }else { - processResolveProfileTextureByNameForOnline(sender, player.getPendingConnection().getName(), searchUUID); - } - }); - } - }else { - CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - eaglerHandler.sendEaglerMessage(foreignSkin.data.get(eaglerHandler.getEaglerProtocol())); - }else { - if (eaglerHandler.skinUUIDLookupRateLimiter - .rateLimit(EaglerXBungee.getEagler().getConfig().getUuidRateLimitPlayer()) - && !isLimitedAsAntagonist(sender.getUniqueId())) { - if(eaglerHandler.isOnlineMode()) { - doAsync(() -> { - processResolveProfileTextureByUUIDForeign(sender, searchUUID); - }); - }else { - eaglerHandler.sendEaglerMessage( - new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), isAlex(searchUUID) ? 1 : 0)); - } - } - } - } - } - } - - public void processGetOtherSkin(UUID searchUUID, String skinURL, UserConnection sender) { - EaglerBungeeConfig config = EaglerXBungee.getEagler().getConfig(); - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(!eaglerHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - return; - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - eaglerHandler.sendEaglerMessage(foreignSkin.data.get(eaglerHandler.getEaglerProtocol())); - }else { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(searchUUID)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.get(eaglerHandler.getEaglerProtocol(), - searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits())); - return; - } - } - } - if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds - eaglerHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - return; - } - skinURL = sanitizeTextureURL(skinURL); - if(skinURL != null) { - final String skinURL_ = skinURL; - if(eaglerHandler.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) { - doAsync(() -> { - processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL_, -1); - }); - } - }else { - eaglerHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - } - } - } - - private void processResolveURLTextureForOnline(final UserConnection initiator, final UUID onlineCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID); - if(skin != null) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin; - if (t != null) { - registerTextureToPlayerAssociation(skinUUID, onlineCacheUUID); - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createCustomV3( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits(), modelId, t), - skinUUID, modelId); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits()), null, -1); - } - onlinePlayersCache.put(onlineCacheUUID, skin); - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveURLTextureForForeign(final UserConnection initiator, final UUID foreignCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID); - if(skin != null) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin; - if (t != null) { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createCustomV3( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits(), modelId, t), - modelId); - } else { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createPreset( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits()), - -1); - } - foreignSkinCache.put(foreignCacheUUID, skin); - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForOnline(final UserConnection initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - if(skin != null) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - }else { - processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - null, -1); - } - onlinePlayersCache.put(playerUUID, skin); - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - }else { - processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - private void processResolveProfileTextureByNameForOnline(final UserConnection initiator, final String playerName, final UUID mapUUID) { - synchronized(pendingNameLookups) { - PendingProfileNameLookup alreadyPending = pendingNameLookups.get(playerName); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid); - if(skin != null) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - }else { - processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileNameLookup newTask = new PendingProfileNameLookup( - playerName, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(mapUUID.getMostSignificantBits(), - mapUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1); - } - onlinePlayersCache.put(mapUUID, skin); - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - }else { - processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUsername(playerName, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingNameLookups.put(playerName, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForeign(final UserConnection initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin = foreignSkinCache.get(playerUUID); - if(skin != null) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - } - }else { - processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin; - if (t == null) { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - -1); - } else { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - -1); - } - foreignSkinCache.put(playerUUID, skin); - EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection(); - initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol())); - }else { - processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { - foreignSkinCache.remove(clientUUID); - onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId)); - } - - public void unregisterPlayer(UUID clientUUID) { - CachedPlayerSkin data = onlinePlayersCache.remove(clientUUID); - if(data != null) { - foreignSkinCache.put(clientUUID, new CachedForeignSkin(clientUUID, data.data, data.modelId)); - if(data.textureUUID != null) { - foreignSkinCache.put(data.textureUUID, new CachedForeignSkin(data.textureUUID, data.data, data.modelId)); - } - deletePlayerTextureAssociation(clientUUID, data.textureUUID); - }else { - deletePlayerTextureAssociation(clientUUID, null); - } - } - - private void deletePlayerTextureAssociation(UUID clientUUID, UUID textureUUID) { - if(textureUUID != null) { - onlinePlayersToTexturesMap.remove(clientUUID); - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.remove(textureUUID, clientUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - }else { - UUID removedUUID = onlinePlayersToTexturesMap.remove(clientUUID); - if(removedUUID != null) { - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.remove(removedUUID, clientUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - } - } - } - - public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) { - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.put(textureUUID, playerUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - onlinePlayersToTexturesMap.put(playerUUID, textureUUID); - CachedForeignSkin foreign = foreignSkinCache.remove(textureUUID); - if(foreign != null) { - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(foreign.data, textureUUID, foreign.modelKnown)); - } - } - - public void processForceSkin(UUID playerUUID, EaglerInitialHandler eaglerHandler) { - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(playerUUID); - - if(maybeCachedPacket != null) { - eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4()); - }else { - UUID playerTexture = onlinePlayersToTexturesMap.get(playerUUID); - if(playerTexture != null) { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( - maybeCachedPacket.data, playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()); - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten, - maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); - eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4()); - return; - } - } - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture); - if(foreignSkin != null && foreignSkin.modelKnown != -1) { - onlinePlayersCache.put(playerUUID, - new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, - playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()), - playerTexture, foreignSkin.modelKnown)); - foreignSkinCache.remove(playerTexture); - eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4()); - return; - } - } - LoginResult loginProfile = eaglerHandler.getLoginProfile(); - if(loginProfile != null) { - Property[] props = loginProfile.getProperties(); - if(props.length > 0) { - for(int i = 0; i < props.length; ++i) { - Property pp = props[i]; - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = sanitizeTextureURL(url.getAsString()); - if(urlStr == null) { - break; - } - int model = 0; - JsonElement el = skinObj.get("metadata"); - if(el != null && el.isJsonObject()) { - el = el.getAsJsonObject().get("model"); - if(el != null) { - model = SkinPackets.getModelId(el.getAsString()); - } - } - UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr); - - CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID); - if(foreignSkin != null) { - registerTextureToPlayerAssociation(skinUUID, playerUUID); - SkinPacketVersionCache rewrite = SkinPacketVersionCache - .rewriteUUIDModel(foreignSkin.data, - playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), model); - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewrite, skinUUID, model)); - eaglerHandler.sendEaglerMessage(rewrite.getForceClientV4()); - return; - } - - // download player skin, put in onlinePlayersCache, no limit - - final int modelf = model; - doAsync(() -> { - processResolveURLTextureForOnlineToForce(eaglerHandler, playerUUID, skinUUID, urlStr, modelf); - }); - - return; - } - } - }catch(Throwable t) { - } - } - } - } - doAsync(() -> { - if(eaglerHandler.isOnlineMode()) { - processResolveProfileTextureByUUIDForOnlineToForce(eaglerHandler, playerUUID); - }else { - processResolveProfileTextureByNameForOnlineToForce(eaglerHandler, eaglerHandler.getName(), playerUUID); - } - }); - }else { - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis(); - eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4()); - }else { - if(eaglerHandler.isOnlineMode()) { - doAsync(() -> { - processResolveProfileTextureByUUIDForeignToForce(eaglerHandler, playerUUID); - }); - }else { - eaglerHandler.sendEaglerMessage(new SPacketForceClientSkinPresetV4EAG(isAlex(playerUUID) ? 1 : 0)); - } - } - } - } - } - - private void processResolveURLTextureForOnlineToForce(final EaglerInitialHandler initiator, final UUID onlineCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin; - if (t != null) { - registerTextureToPlayerAssociation(skinUUID, onlineCacheUUID); - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createCustomV3( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits(), modelId, t), - skinUUID, modelId); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits()), null, -1); - } - onlinePlayersCache.put(onlineCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveURLTextureForForeignToForce(final EaglerInitialHandler initiator, final UUID foreignCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin; - if (t != null) { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createCustomV3( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits(), modelId, t), - modelId); - } else { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createPreset( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits()), - -1); - } - foreignSkinCache.put(foreignCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForOnlineToForce(final EaglerInitialHandler initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - null, -1); - } - onlinePlayersCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - private void processResolveProfileTextureByNameForOnlineToForce(final EaglerInitialHandler initiator, final String playerName, final UUID mapUUID) { - synchronized(pendingNameLookups) { - PendingProfileNameLookup alreadyPending = pendingNameLookups.get(playerName); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileNameLookup newTask = new PendingProfileNameLookup( - playerName, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(mapUUID.getMostSignificantBits(), - mapUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1); - } - onlinePlayersCache.put(mapUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUsername(playerName, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingNameLookups.put(playerName, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForeignToForce(final EaglerInitialHandler initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin = foreignSkinCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin; - if (t == null) { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - -1); - } else { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - -1); - } - foreignSkinCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - public void flush() { - long millis = EaglerXBungeeAPIHelper.steadyTimeMillis(); - - final List foreignSkinCleanup = new ArrayList<>(4); - foreignSkinCache.entrySet().forEach((etr) -> { - if(millis - etr.getValue().lastHit > 900000l) { // 15 minutes - foreignSkinCleanup.add(etr.getKey()); - } - }); - - if(!foreignSkinCleanup.isEmpty()) { - for(UUID uuid : foreignSkinCleanup) { - foreignSkinCache.remove(uuid); - } - } - - synchronized(pendingTextures) { - Iterator itr = pendingTextures.values().iterator(); - while(itr.hasNext()) { - PendingTextureDownload etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - synchronized(pendingUUIDs) { - Iterator itr = pendingUUIDs.values().iterator(); - while(itr.hasNext()) { - PendingProfileUUIDLookup etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - synchronized(pendingNameLookups) { - Iterator itr = pendingNameLookups.values().iterator(); - while(itr.hasNext()) { - PendingProfileNameLookup etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - int cooldownPeriod = 60000 / EaglerXBungee.getEagler().getConfig().getAntagonistsRateLimit(); - int elapsedCooldown = (int)(millis - antagonistCooldown); - elapsedCooldown /= cooldownPeriod; - if(elapsedCooldown > 0) { - antagonistCooldown += elapsedCooldown * cooldownPeriod; - antagonistsLock.writeLock().lock(); - try { - Iterator itr = antagonists.keySet().iterator(); - while(itr.hasNext()) { - UUID key = itr.next(); - int i = antagonists.get(key) - elapsedCooldown; - if(i <= 0) { - itr.remove(); - }else { - antagonists.put(key, i); - } - } - }finally { - antagonistsLock.writeLock().unlock(); - } - } - - cacheProvider.flush(); - } - - public SkinPacketVersionCache getSkin(UUID playerUUID) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - return skin != null ? skin.data : null; - } - - public void shutdown() { - resetMaps(); - if(cacheProvider != null) { - cacheProvider.destroy(); - } - cacheProvider = null; - } - - private boolean isLimitedAsAntagonist(UUID uuid) { - int limit = EaglerXBungee.getEagler().getConfig().getAntagonistsRateLimit(); - limit += limit >> 1; - int i; - antagonistsLock.readLock().lock(); - try { - i = antagonists.get(uuid); - }finally { - antagonistsLock.readLock().unlock(); - } - return i != antagonists.getNoEntryValue() && i > limit; - } - - private void resetMaps() { - onlinePlayersCache.clear(); - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.clear(); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - onlinePlayersToTexturesMap.clear(); - foreignSkinCache.clear(); - synchronized(pendingTextures) { - pendingTextures.clear(); - } - synchronized(pendingUUIDs) { - pendingUUIDs.clear(); - } - synchronized(pendingNameLookups) { - pendingNameLookups.clear(); - } - antagonistsLock.writeLock().lock(); - try { - antagonists.clear(); - }finally { - antagonistsLock.writeLock().unlock(); - } - } - - private void doAsync(Runnable handler) { - ProxyServer.getInstance().getScheduler().runAsync(EaglerXBungee.getEagler(), handler); - } - - public static String sanitizeTextureURL(String url) { - try { - URI uri = URI.create(url); - StringBuilder builder = new StringBuilder(); - String scheme = uri.getScheme(); - if(scheme == null) { - return null; - } - String host = uri.getHost(); - if(host == null || !EaglerXBungee.getEagler().getConfig().isValidSkinHost(host)) { - return null; - } - scheme = scheme.toLowerCase(); - builder.append(scheme).append("://"); - builder.append(host); - int port = uri.getPort(); - if(port != -1) { - switch(scheme) { - case "http": - if(port == 80) { - port = -1; - } - break; - case "https": - if(port == 443) { - port = -1; - } - break; - default: - return null; - } - if(port != -1) { - builder.append(":").append(port); - } - } - String path = uri.getRawPath(); - if(path != null) { - if(path.contains("//")) { - path = String.join("/", path.split("[\\/]+")); - } - int len = path.length(); - if(len > 1 && path.charAt(len - 1) == '/') { - path = path.substring(0, len - 1); - } - builder.append(path); - } - return builder.toString(); - }catch(Throwable t) { - return null; - } - } - - private static final String hexString = "0123456789abcdef"; - - private static final char[] HEX = new char[] { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - public static String getMojangUUID(UUID uuid) { - char[] ret = new char[32]; - long msb = uuid.getMostSignificantBits(); - long lsb = uuid.getLeastSignificantBits(); - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - ret[i] = HEX[(int)((msb >> j) & 15l)]; - ret[i + 16] = HEX[(int)((lsb >> j) & 15l)]; - } - return new String(ret); - } - - public static UUID parseMojangUUID(String uuid) { - long msb = 0l; - long lsb = 0l; - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - msb |= ((long)hexString.indexOf(uuid.charAt(i)) << j); - lsb |= ((long)hexString.indexOf(uuid.charAt(i + 16)) << j); - } - return new UUID(msb, lsb); - } - - public static boolean isAlex(UUID skinUUID) { - return (skinUUID.hashCode() & 1) != 0; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java deleted file mode 100644 index b1503e79..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2022-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; -import net.md_5.bungee.UserConnection; - -public class SkinServiceOffline implements ISkinService { - - public static final int masterRateLimitPerPlayer = 250; - - private static class CachedSkin { - - protected final UUID uuid; - protected final SkinPacketVersionCache packet; - - protected CachedSkin(UUID uuid, SkinPacketVersionCache packet) { - this.uuid = uuid; - this.packet = packet; - } - - } - - private final ConcurrentMap skinCache = new ConcurrentHashMap<>(); - - public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles) { - skinCache.clear(); - } - - public void processGetOtherSkin(UUID searchUUID, UserConnection sender) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(initialHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - CachedSkin cached = skinCache.get(searchUUID); - if(cached != null) { - initialHandler.sendEaglerMessage(cached.packet.get(initialHandler.getEaglerProtocol())); - }else { - initialHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), (searchUUID.hashCode() & 1) != 0 ? 1 : 0)); - } - } - } - - public void processGetOtherSkin(UUID searchUUID, String skinURL, UserConnection sender) { - EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds - initialHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - return; - } - initialHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), (searchUUID.hashCode() & 1) != 0 ? 1 : 0)); - } - - public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { - skinCache.put(clientUUID, new CachedSkin(clientUUID, generatedPacket)); - } - - public void unregisterPlayer(UUID clientUUID) { - skinCache.remove(clientUUID); - } - - public void registerTextureToPlayerAssociation(String textureURL, UUID playerUUID) { - } - - public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) { - } - - public void processForceSkin(UUID playerUUID, EaglerInitialHandler initialHandler) { - CachedSkin cached = skinCache.get(playerUUID); - if(cached != null) { - initialHandler.sendEaglerMessage(cached.packet.getForceClientV4()); - } - } - - public void flush() { - // no - } - - public void shutdown() { - skinCache.clear(); - } - - public SkinPacketVersionCache getSkin(UUID playerUUID) { - CachedSkin cached = skinCache.get(playerUUID); - return cached != null ? cached.packet : null; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/sqlite/EaglerDrivers.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/sqlite/EaglerDrivers.java deleted file mode 100644 index a2598e76..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/sqlite/EaglerDrivers.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.sqlite; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.sql.Connection; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.codehaus.plexus.util.FileUtils; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee; - -public class EaglerDrivers { - - private static Driver initializeDriver(String address, String driverClass) { - URLClassLoader classLoader = driversJARs.get(address); - if(classLoader == null) { - File driver; - if(address.equalsIgnoreCase("internal")) { - driver = new File(EaglerXBungee.getEagler().getDataFolder(), "drivers/sqlite-jdbc.jar"); - driver.getParentFile().mkdirs(); - if(!driver.exists()) { - try { - URL u = new URL("https://repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.45.0.0/sqlite-jdbc-3.45.0.0.jar"); - EaglerXBungee.logger().info("Downloading from maven: " + u.toString()); - FileUtils.copyURLToFile(u, driver); - } catch (Throwable ex) { - EaglerXBungee.logger().severe("Could not download sqlite-jdbc.jar from repo1.maven.org!"); - EaglerXBungee.logger().severe("Please download \"org.xerial:sqlite-jdbc:3.45.0.0\" jar to file: " + driver.getAbsolutePath()); - throw new ExceptionInInitializerError(ex); - } - } - }else { - driver = new File(address); - } - URL driverURL; - try { - driverURL = driver.toURI().toURL(); - }catch(MalformedURLException ex) { - EaglerXBungee.logger().severe("Invalid JDBC driver path: " + address); - throw new ExceptionInInitializerError(ex); - } - classLoader = URLClassLoader.newInstance(new URL[] { driverURL }, ClassLoader.getSystemClassLoader()); - driversJARs.put(address, classLoader); - } - - Class loadedDriver; - try { - loadedDriver = classLoader.loadClass(driverClass); - }catch(ClassNotFoundException ex) { - try { - classLoader.close(); - } catch (IOException e) { - } - EaglerXBungee.logger().severe("Could not find JDBC driver class: " + driverClass); - throw new ExceptionInInitializerError(ex); - } - Driver sqlDriver = null; - try { - sqlDriver = (Driver) loadedDriver.newInstance(); - }catch(Throwable ex) { - try { - classLoader.close(); - } catch (IOException e) { - } - EaglerXBungee.logger().severe("Could not initialize JDBC driver class: " + driverClass); - throw new ExceptionInInitializerError(ex); - } - - return sqlDriver; - } - - private static final Map driversJARs = new HashMap<>(); - private static final Map driversDrivers = new HashMap<>(); - - public static Connection connectToDatabase(String address, String driverClass, String driverPath, Properties props) - throws SQLException { - if(driverClass.equalsIgnoreCase("internal")) { - driverClass = "org.sqlite.JDBC"; - } - if(driverPath == null) { - try { - Class.forName(driverClass); - } catch (ClassNotFoundException e) { - throw new SQLException("Driver class not found in JRE: " + driverClass, e); - } - return DriverManager.getConnection(address, props); - }else { - String driverMapPath = "" + driverPath + "?" + driverClass; - Driver dv = driversDrivers.get(driverMapPath); - if(dv == null) { - dv = initializeDriver(driverPath, driverClass); - driversDrivers.put(driverMapPath, dv); - } - return dv.connect(address, props); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/ExpiringSet.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/ExpiringSet.java deleted file mode 100644 index 2d4902c5..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/ExpiringSet.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper; - -public class ExpiringSet extends HashSet { - private final long expiration; - private final ExpiringEvent event; - - private final Map timestamps = new HashMap<>(); - - public ExpiringSet(long expiration) { - this.expiration = expiration; - this.event = null; - } - - public ExpiringSet(long expiration, ExpiringEvent event) { - this.expiration = expiration; - this.event = event; - } - - public interface ExpiringEvent { - void onExpiration(T item); - } - - public void checkForExpirations() { - Iterator iterator = this.timestamps.keySet().iterator(); - long now = EaglerXBungeeAPIHelper.steadyTimeMillis(); - while (iterator.hasNext()) { - T element = iterator.next(); - if (super.contains(element)) { - if (this.timestamps.get(element) + this.expiration < now) { - if (this.event != null) this.event.onExpiration(element); - iterator.remove(); - super.remove(element); - } - } else { - iterator.remove(); - super.remove(element); - } - } - } - - public boolean add(T o) { - checkForExpirations(); - boolean success = super.add(o); - if (success) timestamps.put(o, EaglerXBungeeAPIHelper.steadyTimeMillis()); - return success; - } - - public boolean remove(Object o) { - checkForExpirations(); - boolean success = super.remove(o); - if (success) timestamps.remove(o); - return success; - } - - public void clear() { - this.timestamps.clear(); - super.clear(); - } - - public boolean contains(Object o) { - checkForExpirations(); - return super.contains(o); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceServerImpl.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceServerImpl.java deleted file mode 100644 index 17bd65d9..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceServerImpl.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.*; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.config.ServerInfo; - -public class VoiceServerImpl { - - private final ServerInfo server; - private final GameMessagePacket iceServersPacket; - - private final Map voicePlayers = new HashMap<>(); - private final Map> voiceRequests = new HashMap<>(); - private final Set voicePairs = new HashSet<>(); - - private static final int VOICE_CONNECT_RATELIMIT = 15; - - private static class VoicePair { - - private final UUID uuid1; - private final UUID uuid2; - - @Override - public int hashCode() { - return uuid1.hashCode() ^ uuid2.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - VoicePair other = (VoicePair) obj; - return (uuid1.equals(other.uuid1) && uuid2.equals(other.uuid2)) - || (uuid1.equals(other.uuid2) && uuid2.equals(other.uuid1)); - } - - private VoicePair(UUID uuid1, UUID uuid2) { - this.uuid1 = uuid1; - this.uuid2 = uuid2; - } - - private boolean anyEquals(UUID uuid) { - return uuid1.equals(uuid) || uuid2.equals(uuid); - } - } - - VoiceServerImpl(ServerInfo server, GameMessagePacket iceServersPacket) { - this.server = server; - this.iceServersPacket = iceServersPacket; - } - - public void handlePlayerLoggedIn(UserConnection player) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)player.getPendingConnection(); - eaglerHandler.sendEaglerMessage(iceServersPacket); - eaglerHandler.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.DISABLED); - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - eaglerHandler.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - } - } - - public void handlePlayerLoggedOut(UserConnection player) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)player.getPendingConnection(); - removeUser(eaglerHandler.getUniqueId()); - } - - void handleVoiceSignalPacketTypeRequest(UUID player, UserConnection sender) { - UUID senderUUID; - EaglerInitialHandler targetInitialHandler; - EaglerInitialHandler senderInitialHandler; - synchronized (voicePlayers) { - senderUUID = sender.getUniqueId(); - if (senderUUID.equals(player)) - return; // prevent duplicates - if (!voicePlayers.containsKey(senderUUID)) - return; - UserConnection targetPlayerCon = voicePlayers.get(player); - if (targetPlayerCon == null) - return; - VoicePair newPair = new VoicePair(player, senderUUID); - if (voicePairs.contains(newPair)) - return; // already paired - ExpiringSet senderRequestSet = voiceRequests.get(senderUUID); - if (senderRequestSet == null) { - voiceRequests.put(senderUUID, senderRequestSet = new ExpiringSet<>(2000)); - } - if (!senderRequestSet.add(player)) { - return; - } - - // check if other has requested earlier - ExpiringSet theSet; - if ((theSet = voiceRequests.get(player)) != null && theSet.contains(senderUUID)) { - theSet.remove(senderUUID); - if (theSet.isEmpty()) - voiceRequests.remove(player); - senderRequestSet.remove(player); - if (senderRequestSet.isEmpty()) - voiceRequests.remove(senderUUID); - // send each other add data - voicePairs.add(newPair); - targetInitialHandler = (EaglerInitialHandler) targetPlayerCon.getPendingConnection(); - senderInitialHandler = (EaglerInitialHandler) sender.getPendingConnection(); - }else { - return; - } - } - if (targetInitialHandler.getEaglerProtocol().ver <= 3) { - targetInitialHandler.sendEaglerMessage(new SPacketVoiceSignalConnectV3EAG( - senderUUID.getMostSignificantBits(), senderUUID.getLeastSignificantBits(), false, false)); - } else { - targetInitialHandler.sendEaglerMessage(new SPacketVoiceSignalConnectV4EAG( - senderUUID.getMostSignificantBits(), senderUUID.getLeastSignificantBits(), false)); - } - if (senderInitialHandler.getEaglerProtocol().ver <= 3) { - senderInitialHandler.sendEaglerMessage(new SPacketVoiceSignalConnectV3EAG( - player.getMostSignificantBits(), player.getLeastSignificantBits(), false, true)); - } else { - senderInitialHandler.sendEaglerMessage(new SPacketVoiceSignalConnectV4EAG( - player.getMostSignificantBits(), player.getLeastSignificantBits(), true)); - } - } - - void handleVoiceSignalPacketTypeConnect(UserConnection sender) { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)sender.getPendingConnection(); - if(!eaglerHandler.voiceConnectRateLimiter.rateLimit(VOICE_CONNECT_RATELIMIT)) { - return; - } - eaglerHandler.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.ENABLED); - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - eaglerHandler.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_ENABLED); - } - UUID senderUuid = eaglerHandler.getUniqueId(); - List lst; - synchronized (voicePlayers) { - if (voicePlayers.containsKey(senderUuid)) { - return; - } - boolean hasNoOtherPlayers = voicePlayers.isEmpty(); - voicePlayers.put(senderUuid, sender); - if (hasNoOtherPlayers) { - return; - } - lst = new ArrayList<>(voicePlayers.values()); - } - GameMessagePacket v3p = null; - GameMessagePacket v4p = null; - for (UserConnection conn : lst) { - EaglerInitialHandler handler = (EaglerInitialHandler) conn.getPendingConnection(); - if (handler.getEaglerProtocol().ver <= 3) { - handler.sendEaglerMessage( - v3p == null - ? (v3p = new SPacketVoiceSignalConnectV3EAG(senderUuid.getMostSignificantBits(), - senderUuid.getLeastSignificantBits(), true, false)) - : v3p); - } else { - handler.sendEaglerMessage( - v4p == null - ? (v4p = new SPacketVoiceSignalConnectAnnounceV4EAG(senderUuid.getMostSignificantBits(), - senderUuid.getLeastSignificantBits())) - : v4p); - } - } - Collection userDatas = new ArrayList<>(lst.size()); - for(UserConnection userCon : lst) { - UUID uuid = userCon.getUniqueId(); - userDatas.add(new SPacketVoiceSignalGlobalEAG.UserData(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), userCon.getDisplayName())); - } - GameMessagePacket packetToBroadcast = new SPacketVoiceSignalGlobalEAG(userDatas); - for (UserConnection userCon : lst) { - ((EaglerInitialHandler)userCon.getPendingConnection()).sendEaglerMessage(packetToBroadcast); - } - } - - void handleVoiceSignalPacketTypeICE(UUID player, byte[] str, UserConnection sender) { - UserConnection pass; - VoicePair pair = new VoicePair(player, sender.getUniqueId()); - synchronized (voicePlayers) { - pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; - } - if (pass != null) { - UUID uuid = sender.getUniqueId(); - ((EaglerInitialHandler) pass.getPendingConnection()).sendEaglerMessage( - new SPacketVoiceSignalICEEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); - } - } - - void handleVoiceSignalPacketTypeDesc(UUID player, byte[] str, UserConnection sender) { - UserConnection pass; - VoicePair pair = new VoicePair(player, sender.getUniqueId()); - synchronized (voicePlayers) { - pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; - } - if (pass != null) { - UUID uuid = sender.getUniqueId(); - ((EaglerInitialHandler) pass.getPendingConnection()).sendEaglerMessage( - new SPacketVoiceSignalDescEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); - } - } - - void handleVoiceSignalPacketTypeDisconnect(UserConnection sender) { - removeUser(sender.getUniqueId()); - } - - void handleVoiceSignalPacketTypeDisconnectPeer(UUID player, UserConnection sender) { - List peersToDisconnect = new ArrayList<>(); - synchronized (voicePlayers) { - if (!voicePlayers.containsKey(player)) { - return; - } - Iterator pairsItr = voicePairs.iterator(); - while (pairsItr.hasNext()) { - VoicePair voicePair = pairsItr.next(); - UUID target = null; - if (voicePair.uuid1.equals(player)) { - target = voicePair.uuid2; - } else if (voicePair.uuid2.equals(player)) { - target = voicePair.uuid1; - } - if (target != null) { - pairsItr.remove(); - final UserConnection conn = voicePlayers.get(target); - final UUID target2 = target; - peersToDisconnect.add(() -> { - if (conn != null) { - ((EaglerInitialHandler) conn.getPendingConnection()).sendEaglerMessage( - new SPacketVoiceSignalDisconnectPeerEAG(player.getMostSignificantBits(), - player.getLeastSignificantBits())); - } - ((EaglerInitialHandler) sender.getPendingConnection()) - .sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG(target2.getMostSignificantBits(), - target2.getLeastSignificantBits())); - }); - } - } - } - for(Runnable r : peersToDisconnect) { - r.run(); - } - } - - void removeUser(final UUID user) { - List peersToDisconnect; - synchronized (voicePlayers) { - final UserConnection connRemove; - if ((connRemove = voicePlayers.remove(user)) == null) { - return; - } - peersToDisconnect = new ArrayList<>(); - if(connRemove != null) { - peersToDisconnect.add(() -> { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)connRemove.getPendingConnection(); - eaglerHandler.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.DISABLED); - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - eaglerHandler.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - } - }); - } - voiceRequests.remove(user); - if (voicePlayers.size() > 0) { - Collection userDatas = new ArrayList<>(voicePlayers.size()); - for(UserConnection userCon : voicePlayers.values()) { - UUID uuid = userCon.getUniqueId(); - userDatas.add(new SPacketVoiceSignalGlobalEAG.UserData(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), userCon.getDisplayName())); - } - final GameMessagePacket voicePlayersPkt = new SPacketVoiceSignalGlobalEAG(userDatas); - for (final UserConnection userCon : voicePlayers.values()) { - if (!user.equals(userCon.getUniqueId())) { - peersToDisconnect.add(() -> { - ((EaglerInitialHandler)userCon.getPendingConnection()).sendEaglerMessage(voicePlayersPkt); - }); - } - } - } - Iterator pairsItr = voicePairs.iterator(); - while (pairsItr.hasNext()) { - VoicePair voicePair = pairsItr.next(); - UUID target = null; - if (voicePair.uuid1.equals(user)) { - target = voicePair.uuid2; - } else if (voicePair.uuid2.equals(user)) { - target = voicePair.uuid1; - } - if (target != null) { - pairsItr.remove(); - if (voicePlayers.size() > 0) { - final UserConnection conn = voicePlayers.get(target); - if (conn != null) { - peersToDisconnect.add(() -> { - ((EaglerInitialHandler) conn.getPendingConnection()).sendEaglerMessage( - new SPacketVoiceSignalDisconnectPeerEAG(user.getMostSignificantBits(), - user.getLeastSignificantBits())); - }); - } - } - } - } - } - for(Runnable r : peersToDisconnect) { - r.run(); - } - } - - EnumVoiceState getPlayerVoiceState(UUID uniqueId) { - synchronized (voicePlayers) { - if(voicePlayers.containsKey(uniqueId)) { - return EnumVoiceState.ENABLED; - } - } - return EnumVoiceState.DISABLED; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceService.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceService.java deleted file mode 100644 index 327f20cd..00000000 --- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/voice/VoiceService.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.voice; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import gnu.trove.map.TMap; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.config.EaglerBungeeConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalAllowedEAG; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.UserConnection; -import net.md_5.bungee.api.config.ServerInfo; - -public class VoiceService { - - private final Map serverMap = new HashMap<>(); - private final GameMessagePacket disableVoicePacket; - - public VoiceService(EaglerBungeeConfig conf) { - this.disableVoicePacket = new SPacketVoiceSignalAllowedEAG(false, null); - String[] iceServers = conf.getICEServers().toArray(new String[conf.getICEServers().size()]); - SPacketVoiceSignalAllowedEAG iceServersPacket = new SPacketVoiceSignalAllowedEAG(true, iceServers); - TMap servers = BungeeCord.getInstance().config.getServers(); - Set keySet = new HashSet<>(servers.keySet()); - keySet.removeAll(conf.getDisableVoiceOnServersSet()); - for(String s : keySet) { - serverMap.put(s, new VoiceServerImpl(servers.get(s), iceServersPacket)); - } - } - - public void handlePlayerLoggedIn(UserConnection player) { - - } - - public void handlePlayerLoggedOut(UserConnection player) { - - } - - public void handleServerConnected(UserConnection player, ServerInfo server) { - VoiceServerImpl svr = serverMap.get(server.getName()); - if(svr != null) { - svr.handlePlayerLoggedIn(player); - }else { - EaglerInitialHandler eaglerHandler = (EaglerInitialHandler)player.getPendingConnection(); - eaglerHandler.sendEaglerMessage(disableVoicePacket); - eaglerHandler.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.SERVER_DISABLE); - if(eaglerHandler.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - eaglerHandler.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - } - } - } - - public void handleServerDisconnected(UserConnection player, ServerInfo server) { - VoiceServerImpl svr = serverMap.get(server.getName()); - if(svr != null) { - svr.handlePlayerLoggedOut(player); - } - } - - public void handleVoiceSignalPacketTypeRequest(UUID player, UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeRequest(player, sender); - } - } - } - - public void handleVoiceSignalPacketTypeConnect(UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeConnect(sender); - } - } - } - - public void handleVoiceSignalPacketTypeICE(UUID player, byte[] str, UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeICE(player, str, sender); - } - } - } - - public void handleVoiceSignalPacketTypeDesc(UUID player, byte[] str, UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDesc(player, str, sender); - } - } - } - - public void handleVoiceSignalPacketTypeDisconnect(UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDisconnect(sender); - } - } - } - - public void handleVoiceSignalPacketTypeDisconnectPeer(UUID player, UserConnection sender) { - if(sender.getServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getServer().getInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDisconnectPeer(player, sender); - } - } - } - - public EnumVoiceState getPlayerVoiceState(UUID player, ServerInfo info) { - VoiceServerImpl svr = serverMap.get(info.getName()); - if(svr != null) { - return svr.getPlayerVoiceState(player); - }else { - return EnumVoiceState.SERVER_DISABLE; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_authservice.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_authservice.yml deleted file mode 100644 index cdaa330f..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_authservice.yml +++ /dev/null @@ -1,17 +0,0 @@ -enable_authentication_system: true -use_onboard_eaglerx_system: true -auth_db_uri: 'jdbc:sqlite:eaglercraft_auths.db' -sql_driver_class: 'internal' -sql_driver_path: 'internal' -password_prompt_screen_text: 'Enter your password to join:' -wrong_password_screen_text: 'Password Incorrect!' -not_registered_screen_text: 'You are not registered on this server!' -eagler_command_name: 'eagler' -use_register_command_text: '&aUse /eagler to set an Eaglercraft password on this account' -use_change_command_text: '&bUse /eagler to change your Eaglercraft password' -command_success_text: '&bYour eagler password was changed successfully.' -last_eagler_login_message: 'Your last Eaglercraft login was on $date from $ip' -too_many_registrations_message: '&cThe maximum number of registrations has been reached for your IP address' -need_vanilla_to_register_message: '&cYou need to log in with a vanilla account to use this command' -override_eagler_to_vanilla_skins: false -max_registration_per_ip: -1 \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_http_mime_types.json b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_http_mime_types.json deleted file mode 100644 index 38458bdd..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_http_mime_types.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "text/html": { - "files": [ "html", "htm", "shtml" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/javascript": { - "files": [ "js" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/octet-stream": { - "files": [ "epk" ], - "expires": 14400 - }, - "text/css": { - "files": [ "css" ], - "expires": 14400, - "charset": "utf-8" - }, - "text/xml": { - "files": [ "xml" ], - "expires": 3600, - "charset": "utf-8" - }, - "text/plain": { - "files": [ "txt" ], - "expires": 3600, - "charset": "utf-8" - }, - "image/png": { - "files": [ "png" ], - "expires": 14400 - }, - "image/jpeg": { - "files": [ "jpeg", "jpg", "jfif" ], - "expires": 14400 - }, - "image/gif": { - "files": [ "gif" ], - "expires": 14400 - }, - "image/webp": { - "files": [ "webp" ], - "expires": 14400 - }, - "image/svg+xml": { - "files": [ "svg", "svgz" ], - "expires": 14400, - "charset": "utf-8" - }, - "image/tiff": { - "files": [ "tiff", "tif" ], - "expires": 14400 - }, - "image/avif": { - "files": [ "avif" ], - "expires": 14400 - }, - "image/x-ms-bmp": { - "files": [ "bmp" ], - "expires": 14400 - }, - "image/x-icon": { - "files": [ "ico" ], - "expires": 14400 - }, - "image/woff": { - "files": [ "woff" ], - "expires": 43200 - }, - "image/woff2": { - "files": [ "woff2" ], - "expires": 43200 - }, - "application/json": { - "files": [ "json" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/pdf": { - "files": [ "pdf" ], - "expires": 14400 - }, - "application/rtf": { - "files": [ "rtf" ], - "expires": 14400 - }, - "application/java-archive": { - "files": [ "jar", "war", "ear" ], - "expires": 14400 - }, - "application/wasm": { - "files": [ "wasm" ], - "expires": 3600 - }, - "application/xhtml+xml": { - "files": [ "xhtml" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/zip": { - "files": [ "zip" ], - "expires": 14400 - }, - "audio/midi": { - "files": [ "mid", "midi", "kar" ], - "expires": 43200 - }, - "audio/mpeg": { - "files": [ "mp3" ], - "expires": 43200 - }, - "audio/ogg": { - "files": [ "ogg" ], - "expires": 43200 - }, - "audio/x-m4a": { - "files": [ "m4a" ], - "expires": 43200 - }, - "application/atom+xml": { - "files": [ "atom" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/rss+xml": { - "files": [ "rss" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/x-shockwave-flash": { - "files": [ "swf" ], - "expires": 43200 - }, - "video/3gpp": { - "files": [ "3gpp", "3gp" ], - "expires": 43200 - }, - "video/mp4": { - "files": [ "mp4" ], - "expires": 43200 - }, - "video/mpeg": { - "files": [ "mpeg", "mpg" ], - "expires": 43200 - }, - "video/quicktime": { - "files": [ "mov" ], - "expires": 43200 - }, - "video/webm": { - "files": [ "webm" ], - "expires": 43200 - }, - "video/x-motion-jpeg": { - "files": [ "mjpg" ], - "expires": 14400 - }, - "video/x-flv": { - "files": [ "flv" ], - "expires": 43200 - }, - "video/x-m4v": { - "files": [ "m4v" ], - "expires": 43200 - }, - "video/x-mng": { - "files": [ "3mng" ], - "expires": 43200 - }, - "video/x-ms-wmv": { - "files": [ "wmv" ], - "expires": 43200 - }, - "video/x-msvideo": { - "files": [ "avi" ], - "expires": 43200 - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_ice_servers.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_ice_servers.yml deleted file mode 100644 index c771aa10..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_ice_servers.yml +++ /dev/null @@ -1,20 +0,0 @@ -voice_servers_no_passwd: -- 'stun:stun.l.google.com:19302' -- 'stun:stun1.l.google.com:19302' -- 'stun:stun2.l.google.com:19302' -- 'stun:stun3.l.google.com:19302' -- 'stun:stun4.l.google.com:19302' -- 'stun:openrelay.metered.ca:80' -voice_servers_passwd: - openrelay1: - url: 'turn:openrelay.metered.ca:80' - username: 'openrelayproject' - password: 'openrelayproject' - openrelay2: - url: 'turn:openrelay.metered.ca:443' - username: 'openrelayproject' - password: 'openrelayproject' - openrelay3: - url: 'turn:openrelay.metered.ca:443?transport=tcp' - username: 'openrelayproject' - password: 'openrelayproject' \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_listeners.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_listeners.yml deleted file mode 100644 index 6013e082..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_listeners.yml +++ /dev/null @@ -1,73 +0,0 @@ -listener_01: - address: 0.0.0.0:8081 - address_v6: 'null' - max_players: 60 - tab_list: GLOBAL_PING - default_server: lobby - force_default_server: false - forward_ip: false - forward_ip_header: X-Real-IP - redirect_legacy_clients_to: 'null' - server_icon: server-icon.png - server_motd: - - '&6An EaglercraftX server' - allow_motd: true - allow_query: true - min_minecraft_protocol: 47 - max_minecraft_protocol: 340 - allow_protocol_v3: true - allow_protocol_v4: true - protocol_v4_defrag_send_delay: 10 - use_haproxy_protocol: false - allow_cookie_revoke_query: true - request_motd_cache: - cache_ttl: 7200 - online_server_list_animation: false - online_server_list_results: true - online_server_list_trending: true - online_server_list_portfolios: false - http_server: - enabled: false - root: 'web' - page_404_not_found: 'default' - page_index_name: - - 'index.html' - - 'index.htm' - allow_voice: false - ratelimit: - ip: - enable: true - period: 90 - limit: 60 - limit_lockout: 80 - lockout_duration: 1200 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - login: - enable: true - period: 50 - limit: 5 - limit_lockout: 10 - lockout_duration: 300 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - motd: - enable: true - period: 30 - limit: 5 - limit_lockout: 15 - lockout_duration: 300 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - query: - enable: true - period: 30 - limit: 15 - limit_lockout: 25 - lockout_duration: 900 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_example.html b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_example.html deleted file mode 100644 index 4d35e893..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_example.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - -Eaglercraft Server - - - - - -

Message API Test

-

Server Version: {% global `plugin_name` %} {% global `plugin_version` %}

-

Make sure you enable javascript in "pause_menu.yml"

-

Message:

-

Recieved from server:

-
    - - \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_v1.js b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_v1.js deleted file mode 100644 index 95e20d72..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_message_api_v1.js +++ /dev/null @@ -1,63 +0,0 @@ -"use strict"; -window.serverMessageAPI = (function() { - var channelOpen = null; - var messageHandlers = []; - window.addEventListener("message", function(evt) { - var dat = evt.data; - if((typeof dat === "object") && dat.ver === 1 && (typeof dat.type === "string") && (typeof dat.channel === "string") && dat.channel.length > 0) { - for(var i = 0; i < messageHandlers.length; ++i) { - messageHandlers[i](dat); - } - } - }); - var ServerMessageAPIError = function(message) { - this.name = "ServerMessageAPIError"; - this.message = message; - }; - ServerMessageAPIError.prototype = Error.prototype; - var openCh = function(chName) { - if(channelOpen !== null) throw new ServerMessageAPIError("Cannot open multiple channels, this feature is not supported!"); - channelOpen = chName; - window.parent.postMessage({ver:1,channel:chName,open:true}, "*"); - }; - var closeCh = function(chName) { - if(channelOpen !== chName) throw new ServerMessageAPIError("Cannot close channel \"" + chName + "\", that channel is not open!"); - channelOpen = null; - window.parent.postMessage({ver:1,channel:chName,open:false}, "*"); - }; - var addListener = function(name, handler) { - if(name === "message") messageHandlers.push(handler); - }; - var remListener = function(name, handler) { - if(name === "message") messageHandlers = messageHandlers.filter(function(o) { return o !== handler; }); - }; - var fixTypedArray = function(arr) { - if(arr.length === arr.buffer.byteLength) { - return arr.buffer; - }else { - var toSend = (data instanceof Uint8Array) ? new Uint8Array(arr.length) : new Int8Array(arr.length); - toSend.set(arr); - return toSend.buffer; - } - }; - var send = function(chName, data) { - if(channelOpen !== chName) throw new ServerMessageAPIError("Cannot send message on channel \"" + chName + "\", that channel is not open!"); - if(typeof data === "string") { - window.parent.postMessage({ver:1,channel:chName,data:data}, "*"); - }else if(data instanceof ArrayBuffer) { - window.parent.postMessage({ver:1,channel:chName,data:data}, "*"); - }else if((data instanceof Uint8Array) || (data instanceof Int8Array)) { - window.parent.postMessage({ver:1,channel:chName,data:fixTypedArray(data)}, "*"); - }else { - throw new ServerMessageAPIError("Only strings, ArrayBuffers, Uint8Arrays, and Int8Arrays can be sent with this function!"); - } - }; - return { - ServerMessageAPIError: ServerMessageAPIError, - openChannel: openCh, - closeChannel: closeCh, - addEventListener: addListener, - removeEventListener: remListener, - send: send - }; -})(); diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu.yml deleted file mode 100644 index 9042249d..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu.yml +++ /dev/null @@ -1,43 +0,0 @@ -enable_custom_pause_menu: false -server_info_button: - enable_button: true - button_text: 'Server Info' - button_mode_open_new_tab: false - server_info_embed_url: '' - button_mode_embed_file: true - server_info_embed_file: 'server_info.html' - server_info_embed_screen_title: 'Server Info' - server_info_embed_send_chunk_rate: 1 - server_info_embed_send_chunk_size: 24576 - enable_template_macros: true - server_info_embed_template_globals: - example_global: 'eagler' - allow_embed_template_eval_macro: false - enable_webview_javascript: false - enable_webview_message_api: false - enable_webview_strict_csp: true -discord_button: - enable_button: true - button_text: 'Discord' - button_url: 'https://invite url here' -custom_images: - icon_title_L: '' - icon_title_R: '' - icon_backToGame_L: '' - icon_backToGame_R: '' - icon_achievements_L: '' - icon_achievements_R: '' - icon_statistics_L: '' - icon_statistics_R: '' - icon_serverInfo_L: '' - icon_serverInfo_R: '' - icon_options_L: '' - icon_options_R: '' - icon_discord_L: '' - icon_discord_R: '' - icon_disconnect_L: '' - icon_disconnect_R: '' - icon_background_pause: 'test_image.png' - icon_background_all: 'test_image.png' - icon_watermark_pause: '' - icon_watermark_all: '' \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_server_info.html b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_server_info.html deleted file mode 100644 index ee7077aa..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_server_info.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - -Eaglercraft Server - - - - -

    Hello World

    - -{% htmlescape on %} -

    Server Name: {% global `server_name` %}

    -

    Using: {% global `plugin_name` %} {% global `plugin_version` %}

    -

    JVM: {% property `java.vm.name` `(unknown)` %} ({% property `java.vm.info` `null` %}) {% property `java.vm.vendor` `(unknown)` %}

    -{% htmlescape off %} - -

    - - - - - - \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_test_image.png b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_test_image.png deleted file mode 100644 index 9c9fc898..00000000 Binary files a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_pause_menu_test_image.png and /dev/null differ diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_settings.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_settings.yml deleted file mode 100644 index 6739d712..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_settings.yml +++ /dev/null @@ -1,28 +0,0 @@ -server_name: 'EaglercraftXBungee Server' -server_uuid: ${random_uuid} -websocket_connection_timeout: 15000 -websocket_handshake_timeout: 5000 -builtin_http_server_timeout: 10000 -http_websocket_compression_level: 6 -download_vanilla_skins_to_clients: true -valid_skin_download_urls: - - 'textures.minecraft.net' -uuid_lookup_ratelimit_player: 50 -uuid_lookup_ratelimit_global: 175 -skin_download_ratelimit_player: 1000 -skin_download_ratelimit_global: 30000 -skin_cache_db_uri: 'jdbc:sqlite:eaglercraft_skins_cache.db' -skin_cache_keep_objects_days: 45 -skin_cache_keep_profiles_days: 7 -skin_cache_max_objects: 32768 -skin_cache_max_profiles: 32768 -skin_cache_antagonists_ratelimit: 15 -sql_driver_class: 'internal' -sql_driver_path: 'internal' -eagler_players_vanilla_skin: '' -enable_is_eagler_player_property: true -disable_voice_chat_on_servers: [] -disable_fnaw_skins_everywhere: false -disable_fnaw_skins_on_servers: [] -enable_backend_rpc_api: false -use_modernized_channel_names: false \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_updates.yml b/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_updates.yml deleted file mode 100644 index d341cec4..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/config/default_updates.yml +++ /dev/null @@ -1,9 +0,0 @@ -block_all_client_updates: false -discard_login_packet_certs: false -cert_packet_data_rate_limit: 524288 -enable_eagcert_folder: true -download_latest_certs: true -download_certs_from: -- 'https://eaglercraft.com/backup.cert' -- 'https://deev.is/eagler/backup.cert' -check_for_update_every: 28800 \ No newline at end of file diff --git a/gateway/EaglercraftXBungee/src/main/resources/plugin.yml b/gateway/EaglercraftXBungee/src/main/resources/plugin.yml deleted file mode 100644 index 8f7a37b7..00000000 --- a/gateway/EaglercraftXBungee/src/main/resources/plugin.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: EaglercraftXBungee -main: net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee -version: 1.3.6 -description: Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks -author: lax1dude \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/.gitignore b/gateway/EaglercraftXVelocity/.gitignore deleted file mode 100644 index 1d62218f..00000000 --- a/gateway/EaglercraftXVelocity/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -lib/* -.idea/* -*.iml -out/* -deps/Velocity.jar -/.gradle/ -/.settings/ -.classpath -.project -/build/ -/bin/ diff --git a/gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar b/gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar deleted file mode 100644 index b77cba0a..00000000 Binary files a/gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar and /dev/null differ diff --git a/gateway/EaglercraftXVelocity/build.gradle b/gateway/EaglercraftXVelocity/build.gradle deleted file mode 100644 index a1dfe767..00000000 --- a/gateway/EaglercraftXVelocity/build.gradle +++ /dev/null @@ -1,43 +0,0 @@ -plugins { - id 'java' - id 'eclipse' -} - -group = 'net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity' -version = '' - -repositories { - mavenCentral() -} - -sourceSets { - main { - java { - srcDirs( - 'src/main/java', - '../../sources/protocol-game/java', - '../backend-rpc-protocol/src/backend-rpc-protocol/java' - ) - } - } -} - -dependencies { - implementation files('deps/Velocity.jar') -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -jar { - compileJava.options.encoding = 'UTF-8' - javadoc.options.encoding = 'UTF-8' - - manifest { - attributes( - 'Main-Class': 'net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.shit.MainClass' - ) - } -} diff --git a/gateway/EaglercraftXVelocity/deps/readme.txt b/gateway/EaglercraftXVelocity/deps/readme.txt deleted file mode 100644 index 64434b64..00000000 --- a/gateway/EaglercraftXVelocity/deps/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Place the Velocity JAR file in this folder, name it "Velocity.jar" - -You can download it from here: https://papermc.io/downloads/velocity \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.jar b/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e5832..00000000 Binary files a/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.properties b/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index eb7f6f99..00000000 --- a/gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Jun 20 10:14:47 CDT 2024 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gateway/EaglercraftXVelocity/gradlew b/gateway/EaglercraftXVelocity/gradlew deleted file mode 100644 index 1b6c7873..00000000 --- a/gateway/EaglercraftXVelocity/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gateway/EaglercraftXVelocity/gradlew.bat b/gateway/EaglercraftXVelocity/gradlew.bat deleted file mode 100644 index 107acd32..00000000 --- a/gateway/EaglercraftXVelocity/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/gateway/EaglercraftXVelocity/readme.txt b/gateway/EaglercraftXVelocity/readme.txt deleted file mode 100644 index 186c85fb..00000000 --- a/gateway/EaglercraftXVelocity/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -Plugin for eaglercraft on velocity - -Still in development, not recommended for public servers! - -Not using gradle to give more direct access to velocity's internals, as gradle only provides a dummy jar containing the api. - -EaglercraftXVelocity requires netty's websocket client/server, which is already in the production velocity jar so it's ideal to compile directly against the real jar - -Simply link "src/main/java" and "src/main/resources" as source folders, and then add the latest version of velocity jar for minecraft 1.8 to the build path. - -To build, export the source folders as a JAR and export the JAR to contain all the classes found in the JARs in "deps" within it, but not including the classes from the actual velocity jar \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/settings.gradle b/gateway/EaglercraftXVelocity/settings.gradle deleted file mode 100644 index cd54735f..00000000 --- a/gateway/EaglercraftXVelocity/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'EaglercraftXVelocity' - diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocity.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocity.java deleted file mode 100644 index 7e08bdc2..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocity.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.nio.file.Path; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -import org.slf4j.Logger; - -import com.google.inject.Inject; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; -import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; -import com.velocitypowered.api.plugin.Plugin; -import com.velocitypowered.api.plugin.annotation.DataDirectory; -import com.velocitypowered.api.proxy.ProxyServer; -import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; -import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; -import com.velocitypowered.proxy.VelocityServer; -import com.velocitypowered.proxy.network.ConnectionManager; -import com.velocitypowered.proxy.network.TransportType; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFactory; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.socket.DatagramChannel; -import io.netty.channel.socket.ServerSocketChannel; -import io.netty.channel.socket.SocketChannel; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandClientBrand; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandConfirmCode; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandDomain; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandEaglerPurge; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandEaglerRegister; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandRatelimit; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.EaglerCommand; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.handlers.EaglerPacketEventListener; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerUpdateSvc; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpWebServer; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.shit.CompatWarning; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.BinaryHttpClient; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.CapeServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.ISkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; - -@Plugin( - id = EaglerXVelocityVersion.PLUGIN_ID, - name = EaglerXVelocityVersion.NAME, - description = EaglerXVelocityVersion.DESCRIPTION, - version = EaglerXVelocityVersion.VERSION, - authors = { - "lax1dude", - "ayunami2000" - } -) -public class EaglerXVelocity { - - static { - CompatWarning.displayCompatWarning(); - } - - private static EaglerXVelocity instance = null; - private final VelocityServer proxy; - private final Logger logger; - private final Path dataDirAsPath; - private final File dataDir; - private ConnectionManager cm; - private EaglerVelocityConfig conf = null; - private EventLoopGroup bossGroup; - private EventLoopGroup workerGroup; - private TransportType transportType; - private ChannelFactory serverSocketChannelFactory; - private ChannelFactory socketChannelFactory; - private ChannelFactory datagramChannelFactory; - private Collection openChannels; - private Timer closeInactiveConnections; - private Timer skinServiceTasks = null; - private Timer authServiceTasks = null; - private Timer updateServiceTasks = null; - private final ChannelFutureListener newChannelListener; - private ISkinService skinService; - private CapeServiceOffline capeService; - private VoiceService voiceService; - private DefaultAuthSystem defaultAuthSystem; - - @Inject - public EaglerXVelocity(ProxyServer proxyIn, Logger loggerIn, @DataDirectory Path dataDirIn) { - instance = this; - proxy = (VelocityServer)proxyIn; - logger = loggerIn; - dataDirAsPath = dataDirIn; - dataDir = dataDirIn.toFile(); - - openChannels = new LinkedList<>(); - newChannelListener = new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture ch) throws Exception { - synchronized(openChannels) { // synchronize whole block to preserve logging order - if(ch.isSuccess()) { - EaglerXVelocity.logger().info("Eaglercraft is listening on: {}", ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get()); - openChannels.add(ch.channel()); - }else { - EaglerXVelocity.logger().error("Eaglercraft could not bind port: {}", ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get()); - EaglerXVelocity.logger().error("Reason: {}", ch.cause().toString()); - } - } - } - }; - } - - @Subscribe - public void onProxyInit(ProxyInitializeEvent e) { - logger.warn("This plugin is still in development, certain features may not be functional!"); - logger.warn("Not recommended for public servers yet, please check for updates"); - try { - Field f = VelocityServer.class.getDeclaredField("cm"); - f.setAccessible(true); - cm = (ConnectionManager)f.get(proxy); - f = ConnectionManager.class.getDeclaredField("bossGroup"); - f.setAccessible(true); - bossGroup = (EventLoopGroup)f.get(cm); - f = ConnectionManager.class.getDeclaredField("workerGroup"); - f.setAccessible(true); - workerGroup = (EventLoopGroup)f.get(cm); - f = ConnectionManager.class.getDeclaredField("transportType"); - f.setAccessible(true); - transportType = (TransportType)f.get(cm); - f = TransportType.class.getDeclaredField("serverSocketChannelFactory"); - f.setAccessible(true); - serverSocketChannelFactory = (ChannelFactory)f.get(transportType); - f = TransportType.class.getDeclaredField("socketChannelFactory"); - f.setAccessible(true); - socketChannelFactory = (ChannelFactory)f.get(transportType); - f = TransportType.class.getDeclaredField("datagramChannelFactory"); - f.setAccessible(true); - datagramChannelFactory = (ChannelFactory)f.get(transportType); - } catch(Throwable t) { - throw new RuntimeException("Accessing private fields failed!", t); - } - Map templateGlobals = EaglerXVelocityAPIHelper.getTemplateGlobals(); - templateGlobals.put("plugin_name", EaglerXVelocityVersion.NAME); - templateGlobals.put("plugin_version", EaglerXVelocityVersion.VERSION); - templateGlobals.put("plugin_authors", String.join(", ", EaglerXVelocityVersion.AUTHORS)); - templateGlobals.put("plugin_description", EaglerXVelocityVersion.DESCRIPTION); - reloadConfig(); - proxy.getEventManager().register(this, new EaglerPacketEventListener(this)); - EaglerCommand.register(this, new CommandRatelimit()); - EaglerCommand.register(this, new CommandConfirmCode()); - EaglerCommand.register(this, new CommandDomain()); - EaglerCommand.register(this, new CommandClientBrand()); - EaglerAuthConfig authConf = conf.getAuthConfig(); - conf.setCracked(!proxy.getConfiguration().isOnlineMode() || !authConf.isEnableAuthentication()); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - if(!proxy.getConfiguration().isOnlineMode()) { - logger.error("Online mode is set to false! Authentication system has been disabled"); - authConf.triggerOnlineModeDisabled(); - }else { - EaglerCommand.register(this, new CommandEaglerRegister(authConf.getEaglerCommandName())); - EaglerCommand.register(this, new CommandEaglerPurge(authConf.getEaglerCommandName())); - } - } - for(String str : GamePluginMessageProtocol.getAllChannels()) { - proxy.getChannelRegistrar().register(new LegacyChannelIdentifier(str)); - } - proxy.getChannelRegistrar().register(new LegacyChannelIdentifier(EaglerBackendRPCProtocol.CHANNEL_NAME)); - proxy.getChannelRegistrar().register(new LegacyChannelIdentifier(EaglerBackendRPCProtocol.CHANNEL_NAME_READY)); - proxy.getChannelRegistrar().register(MinecraftChannelIdentifier.from(EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN)); - proxy.getChannelRegistrar().register(MinecraftChannelIdentifier.from(EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN)); - proxy.getChannelRegistrar().register(EaglerPacketEventListener.GET_DOMAIN_CHANNEL); - - if(closeInactiveConnections != null) { - closeInactiveConnections.cancel(); - closeInactiveConnections = null; - } - closeInactiveConnections = new Timer(EaglerXVelocityVersion.ID + ": Network Tick Tasks"); - closeInactiveConnections.scheduleAtFixedRate(EaglerPipeline.closeInactive, 0l, 250l); - - startListeners(); - - if(skinServiceTasks != null) { - skinServiceTasks.cancel(); - skinServiceTasks = null; - } - boolean downloadSkins = conf.getDownloadVanillaSkins(); - if(downloadSkins) { - if(skinService == null) { - skinService = new SkinService(); - }else if(skinService instanceof SkinServiceOffline) { - skinService.shutdown(); - skinService = new SkinService(); - } - } else { - if(skinService == null) { - skinService = new SkinServiceOffline(); - }else if(skinService instanceof SkinService) { - skinService.shutdown(); - skinService = new SkinServiceOffline(); - } - } - skinService.init(conf.getSkinCacheURI(), conf.getSQLiteDriverClass(), conf.getSQLiteDriverPath(), - conf.getKeepObjectsDays(), conf.getKeepProfilesDays(), conf.getMaxObjects(), conf.getMaxProfiles()); - if(skinService instanceof SkinService) { - skinServiceTasks = new Timer(EaglerXVelocityVersion.ID + ": Skin Service Tasks"); - skinServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - skinService.flush(); - }catch(Throwable t) { - logger.error("Error flushing skin cache!", t); - } - } - }, 1000l, 1000l); - } - capeService = new CapeServiceOffline(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - try { - defaultAuthSystem = DefaultAuthSystem.initializeAuthSystem(authConf); - }catch(DefaultAuthSystem.AuthSystemException ex) { - logger.error("Could not load authentication system!", ex); - } - if(defaultAuthSystem != null) { - authServiceTasks = new Timer(EaglerXVelocityVersion.ID + ": Auth Service Tasks"); - authServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - defaultAuthSystem.flush(); - }catch(Throwable t) { - logger.error("Error flushing auth cache!", t); - } - } - }, 60000l, 60000l); - } - } - if(conf.getEnableVoiceChat()) { - voiceService = new VoiceService(conf); - logger.warn("Voice chat enabled, not recommended for public servers!"); - }else { - logger.info("Voice chat disabled, add \"allow_voice: true\" to your listeners to enable"); - } - if(updateServiceTasks != null) { - updateServiceTasks.cancel(); - updateServiceTasks = null; - } - if(!conf.getUpdateConfig().isBlockAllClientUpdates()) { - updateServiceTasks = new Timer(EaglerXVelocityVersion.ID + ": Update Service Tasks"); - updateServiceTasks.schedule(new TimerTask() { - @Override - public void run() { - try { - EaglerUpdateSvc.updateTick(); - }catch(Throwable t) { - logger.error("Error ticking update service!", t); - } - } - }, 0l, 5000l); - } - } - - @Subscribe - public void onProxyShutdown(ProxyShutdownEvent e) { - stopListeners(); - if(updateServiceTasks != null) { - updateServiceTasks.cancel(); - updateServiceTasks = null; - } - if(closeInactiveConnections != null) { - closeInactiveConnections.cancel(); - closeInactiveConnections = null; - } - if(skinServiceTasks != null) { - skinServiceTasks.cancel(); - skinServiceTasks = null; - } - if(updateServiceTasks != null) { - updateServiceTasks.cancel(); - updateServiceTasks = null; - } - if(skinService != null) { - skinService.shutdown(); - skinService = null; - } - if(capeService != null) { - capeService.shutdown(); - capeService = null; - } - if(defaultAuthSystem != null) { - defaultAuthSystem.destroy(); - defaultAuthSystem = null; - if(authServiceTasks != null) { - authServiceTasks.cancel(); - authServiceTasks = null; - } - } - voiceService = null; - BinaryHttpClient.killEventLoop(); - } - - public void reload() { - stopListeners(); - reloadConfig(); - startListeners(); - } - - private void reloadConfig() { - try { - conf = EaglerVelocityConfig.loadConfig(dataDir); - if(conf == null) { - throw new IOException("Config failed to parse!"); - } - conf.setCracked(!proxy.getConfiguration().isOnlineMode() || !conf.getAuthConfig().isEnableAuthentication()); - HttpWebServer.regenerate404Pages(); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - public void startListeners() { - for(EaglerListenerConfig conf : conf.getServerListeners()) { - if(conf.getAddress() != null) { - makeListener(conf, conf.getAddress()); - } - if(conf.getAddressV6() != null) { - makeListener(conf, conf.getAddressV6()); - } - } - } - - private void makeListener(EaglerListenerConfig confData, InetSocketAddress addr) { - ServerBootstrap bootstrap = new ServerBootstrap(); - bootstrap.option(ChannelOption.SO_REUSEADDR, true) - .childOption(ChannelOption.TCP_NODELAY, true) - .channelFactory(serverSocketChannelFactory) - .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, EaglerPipeline.SERVER_WRITE_MARK) - .group(bossGroup, workerGroup) - .childAttr(EaglerPipeline.LISTENER, confData) - .attr(EaglerPipeline.LOCAL_ADDRESS, addr) - .childOption(ChannelOption.IP_TOS, 24) - .localAddress(addr) - .childHandler(EaglerPipeline.SERVER_CHILD); - if (this.proxy.getConfiguration().useTcpFastOpen()) { - bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); - } - bootstrap.bind().addListener(newChannelListener); - } - - public void stopListeners() { - synchronized(openChannels) { - for(Channel c : openChannels) { - c.close().syncUninterruptibly(); - EaglerXVelocity.logger().info("Eaglercraft listener closed: " + c.attr(EaglerPipeline.LOCAL_ADDRESS).get()); - } - openChannels.clear(); - } - synchronized(EaglerPipeline.openChannels) { - EaglerPipeline.openChannels.clear(); - } - } - - public EaglerVelocityConfig getConfig() { - return conf; - } - - public EventLoopGroup getBossEventLoopGroup() { - return bossGroup; - } - - public EventLoopGroup getWorkerEventLoopGroup() { - return workerGroup; - } - - public TransportType getTransportType() { - return transportType; - } - - public ChannelFactory getChannelFactory() { - return socketChannelFactory; - } - - public ISkinService getSkinService() { - return skinService; - } - - public CapeServiceOffline getCapeService() { - return capeService; - } - - public DefaultAuthSystem getAuthService() { - return defaultAuthSystem; - } - - public VoiceService getVoiceService() { - return voiceService; - } - - public static EaglerXVelocity getEagler() { - return instance; - } - - public VelocityServer getProxy() { - return proxy; - } - - public Logger getLogger() { - return logger; - } - - public File getDataFolder() { - return dataDir; - } - - public static VelocityServer proxy() { - return instance.getProxy(); - } - - public static Logger logger() { - return instance.getLogger(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocityVersion.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocityVersion.java deleted file mode 100644 index d25731d3..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/EaglerXVelocityVersion.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity; - -public class EaglerXVelocityVersion { - - public static final String NATIVE_VELOCITY_BUILD = "3.4.0-SNAPSHOT:6995f415:b464"; - public static final String NATIVE_VELOCITY_BUILD_DL = "https://api.papermc.io/v2/projects/velocity/versions/3.4.0-SNAPSHOT/builds/464/downloads/velocity-3.4.0-SNAPSHOT-464.jar"; - - public static final String ID = "EaglerXVelocity"; - public static final String PLUGIN_ID = "eaglerxvelocity"; - public static final String NAME = "EaglercraftXVelocity"; - public static final String DESCRIPTION = "Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks"; - public static final String VERSION = "1.1.7"; - public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" }; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EaglerXVelocityAPIHelper.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EaglerXVelocityAPIHelper.java deleted file mode 100644 index ec9cefd5..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EaglerXVelocityAPIHelper.java +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.zip.GZIPOutputStream; - -import javax.imageio.ImageIO; - -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.SHA1Digest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.ServerInfoTemplateParser; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.CapeServiceOffline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.ISkinService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinRescaler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketEnableFNAWSkinsEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketInvalidatePlayerCacheV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV3EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketServerInfoDataChunkV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUnforceClientV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class EaglerXVelocityAPIHelper { - - public static EaglerXVelocity getEaglerXVelocity() { - return EaglerXVelocity.getEagler(); - } - - public static EaglerPlayerData getEaglerHandle(Player player) { - return player != null ? EaglerPipeline.getEaglerHandle(player) : null; - } - - public static boolean isEaglerPlayer(Player player) { - return player != null && (EaglerPipeline.getEaglerHandle(player) != null); - } - - public static ConnectedPlayer getPlayer(EaglerPlayerData conn) { - return conn != null ? conn.getPlayerObj() : null; - } - - public static final UUID BRAND_NULL_UUID = new UUID(0l, 0l); - public static final UUID BRAND_PENDING_UUID = new UUID(0x6969696969696969l, 0x6969696969696969l); - public static final UUID BRAND_VANILLA_UUID = new UUID(0x1DCE015CD384374El, 0x85030A4DE95E5736l); - - public static final UUID BRAND_EAGLERCRAFTX_V4_UUID = makeClientBrandUUID("EaglercraftX"); - public static final UUID BRAND_EAGLERCRAFTX_LEGACY_UUID = makeClientBrandUUIDLegacy("EaglercraftX"); - - public static UUID makeClientBrandUUID(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClient:" + name).getBytes(StandardCharsets.UTF_8)); - } - - public static UUID makeClientBrandUUIDLegacy(String name) { - return UUID.nameUUIDFromBytes(("EaglercraftXClientOld:" + name).getBytes(StandardCharsets.UTF_8)); - } - - public static UUID getClientBrandUUID(Player player) { - if(player == null) { - return BRAND_NULL_UUID; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - if(conn != null) { - UUID ret = conn.getClientBrandUUID(); - if(ret != null) { - return ret; - }else { - return BRAND_NULL_UUID; - } - }else { - return BRAND_VANILLA_UUID; - } - } - - public static UUID getClientBrandUUID(EaglerPlayerData conn) { - if(conn == null) { - return BRAND_NULL_UUID; - } - UUID ret = conn.getClientBrandUUID(); - if(ret != null) { - return ret; - }else { - return BRAND_NULL_UUID; - } - } - - public static String getClientVersionString(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getEaglerVersionString() : null; - } - - public static String getClientVersionString(EaglerPlayerData conn) { - return conn != null ? conn.getEaglerVersionString() : null; - } - - public static String getClientBrandString(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getEaglerBrandString() : null; - } - - public static String getClientBrandString(EaglerPlayerData conn) { - return conn != null ? conn.getEaglerBrandString() : null; - } - - public static String getClientOrigin(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getOrigin() : null; - } - - public static String getClientOrigin(EaglerPlayerData conn) { - return conn != null ? conn.getOrigin() : null; - } - - public static String getClientUserAgent(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getUserAgent() : null; - } - - public static String getClientUserAgent(EaglerPlayerData conn) { - return conn != null ? conn.getUserAgent() : null; - } - - public static boolean getCookieAllowed(Player player) { - if(player == null) { - return false; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getCookieAllowed() : null; - } - - public static boolean getCookieAllowed(EaglerPlayerData conn) { - return conn != null ? conn.getCookieAllowed() : null; - } - - public static byte[] getCookieData(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - return conn != null ? conn.getCookieData() : null; - } - - public static byte[] getCookieData(EaglerPlayerData conn) { - return conn != null ? conn.getCookieData() : null; - } - - public static String getCookieDataString(Player player) { - byte[] ret = getCookieData(player); - if(ret == null) { - return null; - } - return new String(ret, StandardCharsets.UTF_8); - } - - public static String getCookieDataString(EaglerPlayerData conn) { - byte[] ret = getCookieData(conn); - if(ret == null) { - return null; - } - return new String(ret, StandardCharsets.UTF_8); - } - - public static void setCookieDataString(Player player, String data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieDataString(Player player, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieDataString(Player player, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieDataString(Player player, String data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - setCookieData(eaglerHandle, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - }else { - throw new UnsupportedOperationException("Can't set cookies on vanilla players!"); - } - } - - public static void setCookieDataString(EaglerPlayerData conn, String data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieDataString(EaglerPlayerData conn, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieDataString(EaglerPlayerData conn, String data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieDataString(EaglerPlayerData conn, String data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data != null ? data.getBytes(StandardCharsets.UTF_8) : null, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(Player player, byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieData(Player player, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieData(Player player, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(player, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(Player player, byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - setCookieData(eaglerHandle, data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - }else { - throw new UnsupportedOperationException("Can't set cookies on vanilla players!"); - } - } - - public static void setCookieData(EaglerPlayerData conn, byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public static void setCookieData(EaglerPlayerData conn, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public static void setCookieData(EaglerPlayerData conn, byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(conn, data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void setCookieData(EaglerPlayerData conn, byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - conn.setCookieData(data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk); - } - - public static void clearCookieData(Player player) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - setCookieData(eaglerHandle, (byte[])null, 0, false, false); - }else { - throw new UnsupportedOperationException("Can't set cookies on vanilla players!"); - } - } - - public static void clearCookieData(EaglerPlayerData conn) { - setCookieData(conn, (byte[])null, 0, false, false); - } - - public static boolean getRedirectSupported(Player player) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null && eaglerHandle.redirectToWebSocketSupported(); - } - - public static boolean getRedirectSupported(EaglerPlayerData conn) { - return conn != null && conn.redirectToWebSocketSupported(); - } - - public static void redirectPlayerToWebSocket(Player player, String serverAddress) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.redirectPlayerToWebSocket(serverAddress); - }else { - throw new UnsupportedOperationException("Can't redirect vanilla players to websocket addresses!"); - } - } - - public static void redirectPlayerToWebSocket(EaglerPlayerData conn, String serverAddress) { - conn.redirectPlayerToWebSocket(serverAddress); - } - - public static byte[] loadCustomSkinFromImage(File phile) throws IOException { - try(FileInputStream is = new FileInputStream(phile)) { - return loadCustomSkinFromImage(is); - } - } - - public static byte[] loadCustomCapeFromImage(File phile) throws IOException { - try(FileInputStream is = new FileInputStream(phile)) { - return loadCustomCapeFromImage(is); - } - } - - public static byte[] loadCustomSkinFromImage(InputStream phile) throws IOException { - return loadCustomSkinFromImage(ImageIO.read(phile)); - } - - public static byte[] loadCustomCapeFromImage(InputStream phile) throws IOException { - return loadCustomCapeFromImage(ImageIO.read(phile)); - } - - public static byte[] loadCustomSkinFromImage(BufferedImage img) throws IOException { - if(img.getWidth() != 64 || (img.getHeight() != 32 && img.getHeight() != 64)) { - throw new IOException("Invalid image dimensions!"); - } - byte[] ret = new byte[16384]; - if(img.getHeight() == 32) { - int[] pixels = new int[2048]; - img.getRGB(0, 0, 64, 32, pixels, 0, 64); - SkinRescaler.convert64x32To64x64(pixels, ret); - }else { - int[] pixels = new int[4096]; - img.getRGB(0, 0, 64, 64, pixels, 0, 64); - SkinRescaler.convertToBytes(pixels, ret); - } - return ret; - } - - public static byte[] loadCustomCapeFromImage(BufferedImage img) throws IOException { - if(img.getHeight() != 32 || (img.getWidth() != 32 && img.getWidth() != 64)) { - throw new IOException("Invalid image dimensions!"); - } - int[] pixels = new int[1024]; - img.getRGB(0, 0, 32, 32, pixels, 0, 32); - byte[] ret = new byte[4096]; - SkinRescaler.convertToBytes(pixels, ret); - return ret; - } - - public static void changePlayerSkinPreset(Player player, int presetId, boolean notifyOtherPlayers) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - UUID uuid = eaglerHandle.getUniqueId(); - ISkinService svc = EaglerXVelocity.getEagler().getSkinService(); - if(eaglerHandle.originalSkin == null) { - eaglerHandle.originalSkin = svc.getSkin(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherSkinPresetEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), presetId); - svc.registerEaglercraftPlayer(uuid, new SkinPacketVersionCache(replacement, replacement), -1); - if(eaglerHandle.getEaglerProtocol().ver >= 4) { - svc.processForceSkin(uuid, eaglerHandle); - } - if(notifyOtherPlayers) { - Optional svr = player.getCurrentServer(); - if(svr.isPresent()) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(true, false, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(Player otherPlayer : svr.get().getServer().getPlayersConnected()) { - if(player != otherPlayer) { - EaglerPlayerData otherConn = EaglerPipeline.getEaglerHandle(otherPlayer); - if(otherConn != null) { - if(otherConn.getEaglerProtocol().ver >= 4) { - otherConn.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerSkinCustom(Player player, int modelId, byte[] texture, boolean notifyOtherPlayers) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - UUID uuid = eaglerHandle.getUniqueId(); - ISkinService svc = EaglerXVelocity.getEagler().getSkinService(); - if(eaglerHandle.originalSkin == null) { - eaglerHandle.originalSkin = svc.getSkin(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherSkinCustomV3EAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), modelId, texture); - svc.registerEaglercraftPlayer(uuid, new SkinPacketVersionCache(replacement, null), modelId); - if(eaglerHandle.getEaglerProtocol().ver >= 4) { - svc.processForceSkin(uuid, eaglerHandle); - } - if(notifyOtherPlayers) { - Optional svr = player.getCurrentServer(); - if(svr.isPresent()) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(true, false, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(Player otherPlayer : svr.get().getServer().getPlayersConnected()) { - if(player != otherPlayer) { - EaglerPlayerData otherConn = EaglerPipeline.getEaglerHandle(otherPlayer); - if(otherConn != null) { - if(otherConn.getEaglerProtocol().ver >= 4) { - otherConn.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerCapePreset(Player player, int presetId, boolean notifyOtherPlayers) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - UUID uuid = eaglerHandle.getUniqueId(); - CapeServiceOffline svc = EaglerXVelocity.getEagler().getCapeService(); - if(eaglerHandle.originalCape == null) { - eaglerHandle.originalCape = svc.getCape(uuid); - } - svc.unregisterPlayer(uuid); - GameMessagePacket replacement = new SPacketOtherCapePresetEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), presetId); - svc.registerEaglercraftPlayer(uuid, replacement); - if(eaglerHandle.getEaglerProtocol().ver >= 4) { - svc.processForceCape(uuid, eaglerHandle); - } - if(notifyOtherPlayers) { - Optional svr = player.getCurrentServer(); - if(svr.isPresent()) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(false, true, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(Player otherPlayer : svr.get().getServer().getPlayersConnected()) { - if(player != otherPlayer) { - EaglerPlayerData otherConn = EaglerPipeline.getEaglerHandle(otherPlayer); - if(otherConn != null) { - if(otherConn.getEaglerProtocol().ver >= 4) { - otherConn.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void changePlayerCapeCustom(Player player, byte[] texture, boolean notifyOtherPlayers) { - changePlayerCapeCustom(player, texture, false, notifyOtherPlayers); - } - - public static void changePlayerCapeCustom(Player player, byte[] texture, boolean compressedFormat, boolean notifyOtherPlayers) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - UUID uuid = eaglerHandle.getUniqueId(); - CapeServiceOffline svc = EaglerXVelocity.getEagler().getCapeService(); - if(eaglerHandle.originalCape == null) { - eaglerHandle.originalCape = svc.getCape(uuid); - } - svc.unregisterPlayer(uuid); - byte[] capeTex; - if(compressedFormat) { - capeTex = texture; - }else { - capeTex = new byte[1173]; - convertCape32x32RGBAto23x17RGB(texture, capeTex); - } - GameMessagePacket replacement = new SPacketOtherCapeCustomEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), capeTex); - svc.registerEaglercraftPlayer(uuid, replacement); - if(eaglerHandle.getEaglerProtocol().ver >= 4) { - svc.processForceCape(uuid, eaglerHandle); - } - if(notifyOtherPlayers) { - Optional svr = player.getCurrentServer(); - if(svr.isPresent()) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(false, true, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(Player otherPlayer : svr.get().getServer().getPlayersConnected()) { - if(player != otherPlayer) { - EaglerPlayerData otherConn = EaglerPipeline.getEaglerHandle(otherPlayer); - if(otherConn != null) { - if(otherConn.getEaglerProtocol().ver >= 4) { - otherConn.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setEnableFNAWSkins(Player player, boolean enable) { - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - if(conn != null) { - setEnableFNAWSkins(conn, enable); - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setEnableFNAWSkins(EaglerPlayerData conn, boolean enable) { - if(enable != conn.currentFNAWSkinEnableStatus.getAndSet(enable)) { - conn.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(enable, conn.currentFNAWSkinForceStatus.get())); - } - } - - public static void setForceFNAWSkins(Player player, boolean force) { - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - if(conn != null) { - setForceFNAWSkins(conn, force); - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setForceFNAWSkins(EaglerPlayerData conn, boolean force) { - if(force != conn.currentFNAWSkinForceStatus.getAndSet(force)) { - conn.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(conn.currentFNAWSkinEnableStatus.get(), force)); - } - } - - public static void setEnableForceFNAWSkins(Player player, boolean enable, boolean force) { - EaglerPlayerData conn = EaglerPipeline.getEaglerHandle(player); - if(conn != null) { - setForceFNAWSkins(conn, force); - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static void setEnableForceFNAWSkins(EaglerPlayerData conn, boolean enable, boolean force) { - if ((enable != conn.currentFNAWSkinEnableStatus.getAndSet(enable)) - | (force != conn.currentFNAWSkinForceStatus.getAndSet(force))) { - conn.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(enable, force)); - } - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, byte[] skinOut) { - convertCape32x32RGBAto23x17RGB(skinIn, 0, skinOut, 0); - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = inOffset + ((y * 32 + x) << 2); - j = outOffset + ((y * 23 + x) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - for(int y = 0; y < 11; ++y) { - i = inOffset + (((y + 11) * 32 + 22) << 2); - j = outOffset + (((y + 6) * 23 + 22) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, byte[] skinOut) { - convertCape23x17RGBto32x32RGBA(skinIn, 0, skinOut, 0); - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = outOffset + ((y * 32 + x) << 2); - j = inOffset + ((y * 23 + x) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - for(int y = 0; y < 11; ++y) { - i = outOffset + (((y + 11) * 32 + 22) << 2); - j = inOffset + (((y + 6) * 23 + 22) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - - public static void resetPlayerSkin(Player player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, true, false, false, notifyOtherPlayers); - } - - public static void resetPlayerCape(Player player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, false, true, false, notifyOtherPlayers); - } - - public static void resetPlayerSkinAndCape(Player player, boolean notifyOtherPlayers) { - resetPlayerMulti(player, true, true, false, notifyOtherPlayers); - } - - public static void resetPlayerMulti(Player player, boolean resetSkin, boolean resetCape, boolean resetForceFNAWSkins, boolean notifyOtherPlayers) { - EaglerPlayerData eaglerHandler = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandler != null) { - UUID uuid = eaglerHandler.getUniqueId(); - boolean notifyResetSkin = false; - boolean notifyResetCape = false; - if(resetSkin) { - if(eaglerHandler.originalSkin != null) { - notifyResetSkin = true; - ISkinService svc = EaglerXVelocity.getEagler().getSkinService(); - svc.unregisterPlayer(uuid); - svc.registerEaglercraftPlayer(uuid, eaglerHandler.originalSkin, eaglerHandler.originalSkin.getModelId()); - } - } - if(resetCape) { - if(eaglerHandler.originalCape != null) { - notifyResetCape = true; - CapeServiceOffline svc = EaglerXVelocity.getEagler().getCapeService(); - svc.unregisterPlayer(uuid); - svc.registerEaglercraftPlayer(uuid, eaglerHandler.originalCape); - } - } - if(resetForceFNAWSkins) { - eaglerHandler.currentFNAWSkinForceStatus.set(false); - } - if(eaglerHandler.getEaglerProtocol().ver >= 4) { - eaglerHandler.sendEaglerMessage(new SPacketUnforceClientV4EAG(resetSkin, resetCape, resetForceFNAWSkins)); - } - if(notifyOtherPlayers && (notifyResetSkin || notifyResetCape)) { - Optional svr = player.getCurrentServer(); - if(svr != null) { - SPacketInvalidatePlayerCacheV4EAG pkt = new SPacketInvalidatePlayerCacheV4EAG(notifyResetSkin, notifyResetCape, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); - for(Player otherPlayer : svr.get().getServer().getPlayersConnected()) { - if(player != otherPlayer) { - EaglerPlayerData otherConn = EaglerPipeline.getEaglerHandle(otherPlayer); - if(otherConn != null) { - if(otherConn.getEaglerProtocol().ver >= 4) { - otherConn.sendEaglerMessage(pkt); - } - } - } - } - } - } - }else { - throw new UnsupportedOperationException("Can't send eagler packets to vanilla players!"); - } - } - - public static EnumVoiceState getClientVoiceState(Player player) { - if(player == null) { - return EnumVoiceState.SERVER_DISABLE; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - VoiceService svc = EaglerXVelocity.getEagler().getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - Optional svr = player.getCurrentServer(); - if(svr.isPresent()) { - return svc.getPlayerVoiceState(eaglerHandle.getUniqueId(), svr.get().getServerInfo()); - }else { - return EnumVoiceState.SERVER_DISABLE; - } - }else { - return EnumVoiceState.SERVER_DISABLE; - } - }else { - return EnumVoiceState.SERVER_DISABLE; - } - } - - public static List convertServerInfoToChunks(String rawData, byte[] hashReturn) throws IOException { - return convertServerInfoToChunks(rawData.getBytes(StandardCharsets.UTF_8), hashReturn, 24576); - } - - public static List convertServerInfoToChunks(byte[] rawData, byte[] hashReturn) throws IOException { - return convertServerInfoToChunks(rawData, hashReturn, 24576); - } - - public static List convertServerInfoToChunks(byte[] rawData, byte[] hashReturn, int chunkSize) throws IOException { - if(hashReturn.length != 20) { - throw new IllegalArgumentException("Hash return array must be 20 bytes long!"); - } - - SHA1Digest digest = new SHA1Digest(); - digest.update(rawData, 0, rawData.length); - digest.doFinal(hashReturn, 0); - - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - bao.write((rawData.length >>> 24) & 0xFF); - bao.write((rawData.length >>> 16) & 0xFF); - bao.write((rawData.length >>> 8) & 0xFF); - bao.write(rawData.length & 0xFF); - - try(OutputStream os = new GZIPOutputStream(bao)) { - os.write(rawData); - } - - byte[] toFragment = bao.toByteArray(); - - int i = 0, j = 0, k = 0; - List ret = new ArrayList<>(); - while(i < toFragment.length) { - j = Math.min(toFragment.length - i, chunkSize); - byte[] chunk = new byte[j]; - System.arraycopy(toFragment, i, chunk, 0, j); - ret.add(new SPacketServerInfoDataChunkV4EAG(i + j == toFragment.length, k++, hashReturn, toFragment.length, chunk)); - i += j; - } - - return ret; - } - - public static String loadFileToStringServerInfo(File serverInfoFile) throws IOException { - return new String(loadFileToByteArrayServerInfo(serverInfoFile), StandardCharsets.UTF_8); - } - - public static byte[] loadFileToByteArrayServerInfo(File serverInfoFile) throws IOException { - long ll = serverInfoFile.length(); - if(ll > 0x2000000l) { - throw new IOException("File is too large: " + serverInfoFile.getAbsolutePath()); - } - int expectLen = (int)ll; - if(expectLen <= 0) { - expectLen = 1024; - } - ByteArrayOutputStream bao = new ByteArrayOutputStream(expectLen); - byte[] copyBuffer = new byte[Math.min(expectLen, 1024)]; - try(InputStream is = new FileInputStream(serverInfoFile)) { - int i; - while((i = is.read(copyBuffer)) != -1) { - bao.write(copyBuffer, 0, i); - } - } - return bao.toByteArray(); - } - - public static String loadServerInfoTemplateEagler(File serverInfoFile, File baseDir, boolean allowEvalMacro) throws IOException { - return loadServerInfoTemplateEagler(serverInfoFile, serverInfoFile.getParentFile(), allowEvalMacro); - } - - public static String loadServerInfoTemplateEagler(File serverInfoFile, boolean allowEvalMacro) throws IOException { - return loadServerInfoTemplateEagler(serverInfoFile, serverInfoFile.getParentFile(), allowEvalMacro); - } - - public static String loadServerInfoTemplateEagler(String serverInfoFile, File baseDir, boolean allowEvalMacro) throws IOException { - return ServerInfoTemplateParser.loadTemplate(serverInfoFile, baseDir, allowEvalMacro, templateGlobals); - } - - private static final Map templateGlobals = new ConcurrentHashMap<>(); - - public static Map getTemplateGlobals() { - return templateGlobals; - } - - public static boolean getWebViewSupport(Player player) { - if(player == null) { - return false; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - return eaglerHandle.getWebViewSupport(); - }else { - return false; - } - } - - public static boolean getWebViewSupport(EaglerPlayerData conn) { - return conn != null && conn.getWebViewSupport(); - } - - public static boolean getWebViewMessageChannelOpen(Player player) { - if(player == null) { - return false; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null && eaglerHandle.getWebViewMessageChannelOpen(); - } - - public static boolean getWebViewMessageChannelOpen(EaglerPlayerData conn) { - return conn != null && conn.getWebViewMessageChannelOpen(); - } - - public static String getWebViewMessageChannelName(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null ? eaglerHandle.getWebViewMessageChannelName() : null; - } - - public static String getWebViewMessageChannelName(EaglerPlayerData conn) { - return conn != null ? conn.getWebViewMessageChannelName() : null; - } - - public static boolean checkCurrentWebViewChannelIsOpen(Player player, String channelName) { - if(player == null) { - return false; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null && eaglerHandle.getWebViewMessageChannelOpen() && channelName.equals(eaglerHandle.getWebViewMessageChannelName()); - } - - public static boolean checkCurrentWebViewChannelIsOpen(EaglerPlayerData conn, String channelName) { - return conn != null && conn.getWebViewMessageChannelOpen() && channelName.equals(conn.getWebViewMessageChannelName()); - } - - public static void sendWebViewMessagePacket(Player player, String str) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.sendWebViewMessage(str); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendWebViewMessagePacket(EaglerPlayerData conn, String str) { - conn.sendWebViewMessage(str); - } - - public static void sendWebViewMessagePacket(Player player, byte[] data) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.sendWebViewMessage(data); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendWebViewMessagePacket(EaglerPlayerData conn, byte[] data) { - conn.sendWebViewMessage(data); - } - - public static EnumWebViewState getWebViewState(Player player) { - if(player == null) { - return EnumWebViewState.NOT_SUPPORTED; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null ? eaglerHandle.getWebViewState() : EnumWebViewState.NOT_SUPPORTED; - } - - public static EnumWebViewState getWebViewState(EaglerPlayerData conn) { - return conn != null ? conn.getWebViewState() : EnumWebViewState.NOT_SUPPORTED; - } - - public static PacketImageData loadPacketImageData(File img) throws IOException { - return loadPacketImageData(ImageIO.read(img), 255, 255); - } - - public static PacketImageData loadPacketImageData(File img, int maxWidth, int maxHeight) throws IOException { - return loadPacketImageData(ImageIO.read(img), maxWidth, maxHeight); - } - - public static PacketImageData loadPacketImageData(BufferedImage img) { - return loadPacketImageData(img, 255, 255); - } - - public static PacketImageData loadPacketImageData(BufferedImage img, int maxWidth, int maxHeight) { - int w = img.getWidth(); - int h = img.getHeight(); - if(w > maxWidth || h > maxHeight) { - float aspectRatio = (float)w / (float)h; - int nw, nh; - if(aspectRatio >= 1.0f) { - nw = (int)(maxWidth / aspectRatio); - nh = maxHeight; - }else { - nw = maxWidth; - nh = (int)(maxHeight * aspectRatio); - } - BufferedImage resized = new BufferedImage(nw, nh, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D) resized.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, nw, nh); - g.drawImage(img, 0, 0, nw, nh, 0, 0, w, h, null); - g.dispose(); - img = resized; - } - int[] pixels = new int[w * h]; - img.getRGB(0, 0, w, h, pixels, 0, w); - return new PacketImageData(w, h, pixels); - } - - public static boolean canSendNotificationsTo(Player player) { - if(player == null) { - return false; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null && eaglerHandle.notificationSupported(); - } - - public static boolean canSendNotificationsTo(EaglerPlayerData conn) { - return conn.notificationSupported(); - } - - public static void registerNotificationIcon(Player player, UUID uuid, PacketImageData imageData) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.registerNotificationIcon(uuid, imageData); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void registerNotificationIcon(EaglerPlayerData conn, UUID uuid, PacketImageData imageData) { - conn.registerNotificationIcon(uuid, imageData); - } - - public static void registerNotificationIcons(Player player, Map imageDatas) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.registerNotificationIcons(imageDatas); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void registerNotificationIcons(EaglerPlayerData conn, Map imageDatas) { - conn.registerNotificationIcons(imageDatas); - } - - public static void showNotificationBadge(Player player, NotificationBadgeBuilder badgeBuilder) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.showNotificationBadge(badgeBuilder); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(EaglerPlayerData conn, NotificationBadgeBuilder badgeBuilder) { - conn.showNotificationBadge(badgeBuilder); - } - - public static void showNotificationBadge(Player player, SPacketNotifBadgeShowV4EAG badgePacket) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.showNotificationBadge(badgePacket); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void showNotificationBadge(EaglerPlayerData conn, SPacketNotifBadgeShowV4EAG badgePacket) { - conn.showNotificationBadge(badgePacket); - } - - public static void hideNotificationBadge(Player player, UUID badgeUUID) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.hideNotificationBadge(badgeUUID); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void hideNotificationBadge(EaglerPlayerData conn, UUID badgeUUID) { - conn.hideNotificationBadge(badgeUUID); - } - - public static void releaseNotificationIcon(Player player, UUID uuid) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.releaseNotificationIcon(uuid); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcon(EaglerPlayerData conn, UUID uuid) { - conn.releaseNotificationIcon(uuid); - } - - public static void releaseNotificationIcons(Player player, Collection uuids) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(eaglerHandle != null) { - eaglerHandle.releaseNotificationIcons(uuids); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void releaseNotificationIcons(EaglerPlayerData conn, Collection uuids) { - conn.releaseNotificationIcons(uuids); - } - - public static int getEaglerProtocolVersion(Player player) { - if(player == null) { - return -1; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null ? eaglerHandle.getEaglerProtocolHandshake() : -1; - } - - public static int getEaglerProtocolVersion(EaglerPlayerData conn) { - return conn != null ? conn.getEaglerProtocolHandshake() : -1; - } - - public static GamePluginMessageProtocol getMessageProtocolVersion(Player player) { - if(player == null) { - return null; - } - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - return eaglerHandle != null ? eaglerHandle.getEaglerProtocol() : null; - } - - public static GamePluginMessageProtocol getMessageProtocolVersion(EaglerPlayerData conn) { - return conn.getEaglerProtocol(); - } - - public static void sendEaglerMessagePacket(Player player, GameMessagePacket packet) { - EaglerPlayerData eaglerHandle = EaglerPipeline.getEaglerHandle(player); - if(player != null) { - eaglerHandle.sendEaglerMessage(packet); - }else { - throw new UnsupportedOperationException("Can't send eagler message packets to vanilla players!"); - } - } - - public static void sendEaglerMessagePacket(EaglerPlayerData conn, GameMessagePacket packet) { - conn.sendEaglerMessage(packet); - } - - public static long steadyTimeMillis() { - return System.nanoTime() / 1000000l; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumVoiceState.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumVoiceState.java deleted file mode 100644 index c87c1479..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumVoiceState.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; - -public enum EnumVoiceState { - SERVER_DISABLE, - DISABLED, - ENABLED; -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumWebViewState.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumWebViewState.java deleted file mode 100644 index 1e296a61..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumWebViewState.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; - -public enum EnumWebViewState { - NOT_SUPPORTED, - SERVER_DISABLE, - CHANNEL_CLOSED, - CHANNEL_OPEN; -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/JSONLegacySerializer.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/JSONLegacySerializer.java deleted file mode 100644 index a9e9e8fa..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/JSONLegacySerializer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; - -import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; -import net.kyori.adventure.text.serializer.json.LegacyHoverEventSerializer; -import net.kyori.adventure.text.serializer.json.legacyimpl.NBTLegacyHoverEventSerializer; - -public class JSONLegacySerializer { - - static { - JSONComponentSerializer.Builder builder = JSONComponentSerializer.builder(); - try { - builder.legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get()); - }catch(Throwable t) { - try { - Class c = Class.forName("com.velocitypowered.proxy.protocol.util.VelocityLegacyHoverEventSerializer"); - builder.legacyHoverEventSerializer((LegacyHoverEventSerializer)c.getDeclaredField("INSTANCE").get(null)); - }catch(Throwable tt) { - throw new RuntimeException("Legacy hover event serializer is unavailable! (downgrade velocity)"); - } - } - instance = builder.build(); - } - - public static final JSONComponentSerializer instance; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/NotificationBadgeBuilder.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/NotificationBadgeBuilder.java deleted file mode 100644 index 489c9899..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/NotificationBadgeBuilder.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; - -import java.util.UUID; - -import net.kyori.adventure.text.Component; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG.EnumBadgePriority; - -public class NotificationBadgeBuilder { - - public static enum BadgePriority { - LOW, NORMAL, HIGHER, HIGHEST; - } - - private UUID badgeUUID = null; - private Component bodyComponent = null; - private Component titleComponent = null; - private Component sourceComponent = null; - private long originalTimestampSec = 0l; - private boolean silent = false; - private BadgePriority priority = BadgePriority.NORMAL; - private UUID mainIconUUID = null; - private UUID titleIconUUID = null; - private int hideAfterSec = 10; - private int expireAfterSec = 3600; - private int backgroundColor = 0xFFFFFF; - private int bodyTxtColor = 0xFFFFFF; - private int titleTxtColor = 0xFFFFFF; - private int sourceTxtColor = 0xFFFFFF; - - private SPacketNotifBadgeShowV4EAG packetCache = null; - private boolean packetDirty = true; - - public NotificationBadgeBuilder() { - originalTimestampSec = System.currentTimeMillis() / 1000l; - } - - public NotificationBadgeBuilder(NotificationBadgeBuilder builder) { - badgeUUID = builder.badgeUUID; - bodyComponent = builder.bodyComponent; - titleComponent = builder.titleComponent; - sourceComponent = builder.sourceComponent; - originalTimestampSec = builder.originalTimestampSec; - silent = builder.silent; - priority = builder.priority; - mainIconUUID = builder.mainIconUUID; - titleIconUUID = builder.titleIconUUID; - hideAfterSec = builder.hideAfterSec; - backgroundColor = builder.backgroundColor; - bodyTxtColor = builder.bodyTxtColor; - titleTxtColor = builder.titleTxtColor; - sourceTxtColor = builder.sourceTxtColor; - packetCache = !builder.packetDirty ? builder.packetCache : null; - packetDirty = builder.packetDirty; - } - - public NotificationBadgeBuilder(SPacketNotifBadgeShowV4EAG packet) { - badgeUUID = new UUID(packet.badgeUUIDMost, packet.badgeUUIDLeast); - try { - bodyComponent = JSONLegacySerializer.instance.deserialize(packet.bodyComponent); - }catch(Throwable t) { - bodyComponent = Component.text(packet.bodyComponent); - } - try { - titleComponent = JSONLegacySerializer.instance.deserialize(packet.titleComponent); - }catch(Throwable t) { - titleComponent = Component.text(packet.titleComponent); - } - try { - sourceComponent = JSONLegacySerializer.instance.deserialize(packet.sourceComponent); - }catch(Throwable t) { - sourceComponent = Component.text(packet.sourceComponent); - } - originalTimestampSec = packet.originalTimestampSec; - silent = packet.silent; - switch(packet.priority) { - case LOW: - default: - priority = BadgePriority.LOW; - break; - case NORMAL: - priority = BadgePriority.NORMAL; - break; - case HIGHER: - priority = BadgePriority.HIGHER; - break; - case HIGHEST: - priority = BadgePriority.HIGHEST; - break; - } - mainIconUUID = new UUID(packet.mainIconUUIDMost, packet.mainIconUUIDLeast); - titleIconUUID = new UUID(packet.titleIconUUIDMost, packet.titleIconUUIDLeast); - hideAfterSec = packet.hideAfterSec; - backgroundColor = packet.backgroundColor; - bodyTxtColor = packet.bodyTxtColor; - titleTxtColor = packet.titleTxtColor; - sourceTxtColor = packet.sourceTxtColor; - packetCache = packet; - packetDirty = false; - } - - public UUID getBadgeUUID() { - return badgeUUID; - } - - public NotificationBadgeBuilder setBadgeUUID(UUID badgeUUID) { - this.badgeUUID = badgeUUID; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBadgeUUIDRandom() { - this.badgeUUID = UUID.randomUUID(); - this.packetDirty = true; - return this; - } - - public Component getBodyComponent() { - return bodyComponent; - } - - public NotificationBadgeBuilder setBodyComponent(Component bodyComponent) { - this.bodyComponent = bodyComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyComponent(String bodyText) { - this.bodyComponent = Component.text(bodyText); - this.packetDirty = true; - return this; - } - - public Component getTitleComponent() { - return titleComponent; - } - - public NotificationBadgeBuilder setTitleComponent(Component titleComponent) { - this.titleComponent = titleComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleComponent(String titleText) { - this.titleComponent = Component.text(titleText); - this.packetDirty = true; - return this; - } - - public Component getSourceComponent() { - return sourceComponent; - } - - public NotificationBadgeBuilder setSourceComponent(Component sourceComponent) { - this.sourceComponent = sourceComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceComponent(String sourceText) { - this.sourceComponent = Component.text(sourceText); - this.packetDirty = true; - return this; - } - - public long getOriginalTimestampSec() { - return originalTimestampSec; - } - - public NotificationBadgeBuilder setOriginalTimestampSec(long originalTimestampSec) { - this.originalTimestampSec = originalTimestampSec; - this.packetDirty = true; - return this; - } - - public boolean isSilent() { - return silent; - } - - public NotificationBadgeBuilder setSilent(boolean silent) { - this.silent = silent; - this.packetDirty = true; - return this; - } - - public BadgePriority getPriority() { - return priority; - } - - public NotificationBadgeBuilder setPriority(BadgePriority priority) { - this.priority = priority; - this.packetDirty = true; - return this; - } - - public UUID getMainIconUUID() { - return mainIconUUID; - } - - public NotificationBadgeBuilder setMainIconUUID(UUID mainIconUUID) { - this.mainIconUUID = mainIconUUID; - this.packetDirty = true; - return this; - } - - public UUID getTitleIconUUID() { - return titleIconUUID; - } - - public NotificationBadgeBuilder setTitleIconUUID(UUID titleIconUUID) { - this.titleIconUUID = titleIconUUID; - this.packetDirty = true; - return this; - } - - public int getHideAfterSec() { - return hideAfterSec; - } - - public NotificationBadgeBuilder setHideAfterSec(int hideAfterSec) { - this.hideAfterSec = hideAfterSec; - this.packetDirty = true; - return this; - } - - public int getExpireAfterSec() { - return expireAfterSec; - } - - public NotificationBadgeBuilder setExpireAfterSec(int expireAfterSec) { - this.expireAfterSec = expireAfterSec; - this.packetDirty = true; - return this; - } - - public int getBackgroundColor() { - return backgroundColor; - } - - public NotificationBadgeBuilder setBackgroundColor(int backgroundColor) { - this.backgroundColor = backgroundColor; - this.packetDirty = true; - return this; - } - - public int getBodyTxtColorRGB() { - return bodyTxtColor; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorRGB) { - this.bodyTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorR, int colorG, int colorB) { - this.bodyTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getTitleTxtColorRGB() { - return titleTxtColor; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorRGB) { - this.titleTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorR, int colorG, int colorB) { - this.titleTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getSourceTxtColorRGB() { - return sourceTxtColor; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorRGB) { - this.sourceTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorR, int colorG, int colorB) { - this.sourceTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public Object clone() { - return new NotificationBadgeBuilder(this); - } - - public SPacketNotifBadgeShowV4EAG buildPacket() { - if(packetDirty || packetCache == null) { - if(badgeUUID == null) { - badgeUUID = UUID.randomUUID(); - }else if(badgeUUID.getMostSignificantBits() == 0l && badgeUUID.getLeastSignificantBits() == 0l) { - throw new IllegalStateException("Badge UUID cannot be 0!"); - } - EnumBadgePriority internalPriority; - switch(priority) { - case LOW: - default: - internalPriority = EnumBadgePriority.LOW; - break; - case NORMAL: - internalPriority = EnumBadgePriority.NORMAL; - break; - case HIGHER: - internalPriority = EnumBadgePriority.HIGHER; - break; - case HIGHEST: - internalPriority = EnumBadgePriority.HIGHEST; - break; - } - String bodyComp = bodyComponent != null ? JSONLegacySerializer.instance.serialize(bodyComponent) : ""; - if(bodyComp.length() > 32767) { - throw new IllegalStateException("Body component is longer than 32767 chars serialized!"); - } - String titleComp = titleComponent != null ? JSONLegacySerializer.instance.serialize(titleComponent) : ""; - if(titleComp.length() > 255) { - throw new IllegalStateException("Title component is longer than 255 chars serialized!"); - } - String sourceComp = sourceComponent != null ? JSONLegacySerializer.instance.serialize(sourceComponent) : ""; - if(sourceComp.length() > 255) { - throw new IllegalStateException("Body component is longer than 255 chars serialized!"); - } - packetCache = new SPacketNotifBadgeShowV4EAG(badgeUUID.getMostSignificantBits(), - badgeUUID.getLeastSignificantBits(), bodyComp, titleComp, sourceComp, originalTimestampSec, silent, - internalPriority, mainIconUUID != null ? mainIconUUID.getMostSignificantBits() : 0l, - mainIconUUID != null ? mainIconUUID.getLeastSignificantBits() : 0l, - titleIconUUID != null ? titleIconUUID.getMostSignificantBits() : 0l, - titleIconUUID != null ? titleIconUUID.getLeastSignificantBits() : 0l, hideAfterSec, expireAfterSec, - backgroundColor, bodyTxtColor, titleTxtColor, sourceTxtColor); - packetDirty = false; - } - return packetCache; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftClientBrandEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftClientBrandEvent.java deleted file mode 100644 index e6bce4cb..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftClientBrandEvent.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; - -import net.kyori.adventure.text.Component; - -public class EaglercraftClientBrandEvent { - - private final String clientBrand; - private final String clientVersion; - private final String origin; - private final int protocolVersion; - private final InetAddress remoteAddress; - private boolean cancelled; - private Component message; - - public EaglercraftClientBrandEvent(String clientBrand, String clientVersion, String origin, int protocolVersion, - InetAddress remoteAddress) { - this.clientBrand = clientBrand; - this.clientVersion = clientVersion; - this.origin = origin; - this.protocolVersion = protocolVersion; - this.remoteAddress = remoteAddress; - } - - public Component getMessage() { - return message; - } - - public void setMessage(Component message) { - this.message = message; - } - - public String getClientBrand() { - return clientBrand; - } - - public String getClientVersion() { - return clientVersion; - } - - public String getOrigin() { - return origin; - } - - public int getProtocolVersion() { - return protocolVersion; - } - - public InetAddress getRemoteAddress() { - return remoteAddress; - } - - public boolean isCancelled() { - return cancelled; - } - - public void setCancelled(boolean cancelled) { - this.cancelled = cancelled; - } - - public void setKickMessage(String message) { - this.cancelled = true; - this.message = Component.text(message); - } - - public void setKickMessage(Component message) { - this.cancelled = true; - this.message = message; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthCookieEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthCookieEvent.java deleted file mode 100644 index e91a5dad..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthCookieEvent.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftHandleAuthCookieEvent { - - public static enum AuthResponse { - ALLOW, DENY, REQUIRE_AUTH - } - - private final EaglerListenerConfig listener; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final boolean enableCookies; - private final byte[] cookieData; - private final EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod; - private final String eventAuthMessage; - private final Object authAttachment; - - private AuthResponse eventResponse; - private byte[] authUsername; - private String authProfileUsername; - private UUID authProfileUUID; - private String authRequestedServerRespose; - private String authDeniedMessage = "Bad Cookie!"; - private String applyTexturesPropValue; - private String applyTexturesPropSignature; - private boolean overrideEaglerToVanillaSkins; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglercraftHandleAuthCookieEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, byte[] authUsername, String authProfileUsername, UUID authProfileUUID, - boolean enableCookies, byte[] cookieData, EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod, - String eventAuthMessage, Object authAttachment, String authRequestedServerRespose, - Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.authUsername = authUsername; - this.authProfileUsername = authProfileUsername; - this.authProfileUUID = authProfileUUID; - this.enableCookies = enableCookies; - this.cookieData = cookieData; - this.eventAuthMethod = eventAuthMethod; - this.eventAuthMessage = eventAuthMessage; - this.authAttachment = authAttachment; - this.authRequestedServerRespose = authRequestedServerRespose; - this.continueThread = continueThread; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public boolean getCookiesEnabled() { - return enableCookies; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return cookieData != null ? new String(cookieData, StandardCharsets.UTF_8) : null; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public String getProfileUsername() { - return authProfileUsername; - } - - public void setProfileUsername(String username) { - this.authProfileUsername = username; - } - - public UUID getProfileUUID() { - return authProfileUUID; - } - - public void setProfileUUID(UUID uuid) { - this.authProfileUUID = uuid; - } - - public EaglercraftIsAuthRequiredEvent.AuthMethod getAuthType() { - return eventAuthMethod; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public String getAuthRequestedServer() { - return authRequestedServerRespose; - } - - public void setAuthRequestedServer(String server) { - this.authRequestedServerRespose = server; - } - - public void setLoginAllowed() { - this.eventResponse = AuthResponse.ALLOW; - this.authDeniedMessage = null; - } - - public void setLoginPasswordRequired() { - this.eventResponse = AuthResponse.REQUIRE_AUTH; - this.authDeniedMessage = null; - } - - public void setLoginDenied(String message) { - this.eventResponse = AuthResponse.DENY; - this.authDeniedMessage = message; - } - - public AuthResponse getLoginAllowed() { - return eventResponse; - } - - public String getLoginDeniedMessage() { - return authDeniedMessage; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftHandleAuthCookieEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - - public void applyTexturesProperty(String value, String signature) { - applyTexturesPropValue = value; - applyTexturesPropSignature = signature; - } - - public String getApplyTexturesPropertyValue() { - return applyTexturesPropValue; - } - - public String getApplyTexturesPropertySignature() { - return applyTexturesPropSignature; - } - - public void setOverrideEaglerToVanillaSkins(boolean overrideEaglerToVanillaSkins) { - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - } - - public boolean isOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthPasswordEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthPasswordEvent.java deleted file mode 100644 index f4333667..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthPasswordEvent.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftHandleAuthPasswordEvent { - - public static enum AuthResponse { - ALLOW, DENY - } - - private final EaglerListenerConfig listener; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final byte[] authUsername; - private final byte[] authSaltingData; - private final byte[] authPasswordData; - private final boolean enableCookies; - private final byte[] cookieData; - private final EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod; - private final String eventAuthMessage; - private final Object authAttachment; - - private AuthResponse eventResponse; - private String authProfileUsername; - private UUID authProfileUUID; - private String authRequestedServerRespose; - private String authDeniedMessage = "Password Incorrect!"; - private String applyTexturesPropValue; - private String applyTexturesPropSignature; - private boolean overrideEaglerToVanillaSkins; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglercraftHandleAuthPasswordEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, byte[] authUsername, byte[] authSaltingData, String authProfileUsername, - UUID authProfileUUID, byte[] authPasswordData, boolean enableCookies, byte[] cookieData, - EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod, String eventAuthMessage, Object authAttachment, - String authRequestedServerRespose, Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.authUsername = authUsername; - this.authSaltingData = authSaltingData; - this.authProfileUsername = authProfileUsername; - this.authProfileUUID = authProfileUUID; - this.authPasswordData = authPasswordData; - this.enableCookies = enableCookies; - this.cookieData = cookieData; - this.eventAuthMethod = eventAuthMethod; - this.eventAuthMessage = eventAuthMessage; - this.authAttachment = authAttachment; - this.authRequestedServerRespose = authRequestedServerRespose; - this.continueThread = continueThread; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public byte[] getAuthSaltingData() { - return authSaltingData; - } - - public boolean getCookiesEnabled() { - return enableCookies; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return cookieData != null ? new String(cookieData, StandardCharsets.UTF_8) : null; - } - - public String getProfileUsername() { - return authProfileUsername; - } - - public void setProfileUsername(String username) { - this.authProfileUsername = username; - } - - public UUID getProfileUUID() { - return authProfileUUID; - } - - public void setProfileUUID(UUID uuid) { - this.authProfileUUID = uuid; - } - - public byte[] getAuthPasswordDataResponse() { - return authPasswordData; - } - - public EaglercraftIsAuthRequiredEvent.AuthMethod getAuthType() { - return eventAuthMethod; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public String getAuthRequestedServer() { - return authRequestedServerRespose; - } - - public void setAuthRequestedServer(String server) { - this.authRequestedServerRespose = server; - } - - public void setLoginAllowed() { - this.eventResponse = AuthResponse.ALLOW; - this.authDeniedMessage = null; - } - - public void setLoginDenied(String message) { - this.eventResponse = AuthResponse.DENY; - this.authDeniedMessage = message; - } - - public AuthResponse getLoginAllowed() { - return eventResponse; - } - - public String getLoginDeniedMessage() { - return authDeniedMessage; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftHandleAuthPasswordEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - - public void applyTexturesProperty(String value, String signature) { - applyTexturesPropValue = value; - applyTexturesPropSignature = signature; - } - - public String getApplyTexturesPropertyValue() { - return applyTexturesPropValue; - } - - public String getApplyTexturesPropertySignature() { - return applyTexturesPropSignature; - } - - public void setOverrideEaglerToVanillaSkins(boolean overrideEaglerToVanillaSkins) { - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - } - - public boolean isOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftIsAuthRequiredEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftIsAuthRequiredEvent.java deleted file mode 100644 index 6340a108..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftIsAuthRequiredEvent.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftIsAuthRequiredEvent { - - public static enum AuthResponse { - SKIP, REQUIRE, DENY - } - - public static enum AuthMethod { - PLAINTEXT, EAGLER_SHA256, AUTHME_SHA256 - } - - public EaglercraftIsAuthRequiredEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, boolean wantsAuth, byte[] authUsername, - Consumer continueThread) { - this.listener = listener; - this.authRemoteAddress = authRemoteAddress; - this.authOrigin = authOrigin; - this.wantsAuth = wantsAuth; - this.authUsername = authUsername; - this.continueThread = continueThread; - } - - private final EaglerListenerConfig listener; - private AuthResponse authResponse; - private final InetAddress authRemoteAddress; - private final String authOrigin; - private final boolean wantsAuth; - private final byte[] authUsername; - private byte[] authSaltingData; - private AuthMethod eventAuthMethod = null; - private String eventAuthMessage = "enter the code:"; - private String kickUserMessage = "Login Denied"; - private Object authAttachment; - private boolean enableCookieAuth; - private Consumer continueThread; - private Runnable continueRunnable; - private volatile boolean hasContinue = false; - - public EaglerListenerConfig getListener() { - return listener; - } - - public InetAddress getRemoteAddress() { - return authRemoteAddress; - } - - public String getOriginHeader() { - return authOrigin; - } - - public boolean isClientSolicitingPasscode() { - return wantsAuth; - } - - public byte[] getAuthUsername() { - return authUsername; - } - - public byte[] getSaltingData() { - return authSaltingData; - } - - public void setSaltingData(byte[] saltingData) { - authSaltingData = saltingData; - } - - public AuthMethod getUseAuthType() { - return eventAuthMethod; - } - - public void setUseAuthMethod(AuthMethod authMethod) { - this.eventAuthMethod = authMethod; - } - - public AuthResponse getAuthRequired() { - return authResponse; - } - - public void setAuthRequired(AuthResponse required) { - this.authResponse = required; - } - - public String getAuthMessage() { - return eventAuthMessage; - } - - public void setAuthMessage(String eventAuthMessage) { - this.eventAuthMessage = eventAuthMessage; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - - public void setAuthAttachment(Object authAttachment) { - this.authAttachment = authAttachment; - } - - public boolean getEnableCookieAuth() { - return enableCookieAuth; - } - - public void setEnableCookieAuth(boolean enable) { - this.enableCookieAuth = enable; - } - - public boolean shouldKickUser() { - return authResponse == null || authResponse == AuthResponse.DENY; - } - - public String getKickMessage() { - return kickUserMessage; - } - - public void kickUser(String message) { - authResponse = AuthResponse.DENY; - kickUserMessage = message; - } - - public Runnable makeAsyncContinue() { - if(continueRunnable == null) { - continueRunnable = new Runnable() { - @Override - public void run() { - if(!hasContinue) { - hasContinue = true; - continueThread.accept(EaglercraftIsAuthRequiredEvent.this); - }else { - throw new IllegalStateException("Thread was already continued from a different function! Auth plugin conflict?"); - } - } - }; - } - return continueRunnable; - } - - public boolean isAsyncContinue() { - return continueRunnable != null; - } - - public void doDirectContinue() { - continueThread.accept(this); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftMOTDEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftMOTDEvent.java deleted file mode 100644 index dcc7a63d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftMOTDEvent.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query.MOTDConnection; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftMOTDEvent { - - protected final MOTDConnection connection; - - public EaglercraftMOTDEvent(MOTDConnection connection) { - this.connection = connection; - } - - public InetAddress getRemoteAddress() { - return connection.getAddress(); - } - - public EaglerListenerConfig getListener() { - return connection.getListener(); - } - - public String getAccept() { - return connection.getAccept(); - } - - public MOTDConnection getConnection() { - return connection; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterCapeEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterCapeEvent.java deleted file mode 100644 index e473defc..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterCapeEvent.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class EaglercraftRegisterCapeEvent { - - private final Object authAttachment; - private final String username; - private final UUID uuid; - private byte[] customTex = null; - - public EaglercraftRegisterCapeEvent(String username, UUID uuid, Object authAttachment) { - this.username = username; - this.uuid = uuid; - this.authAttachment = authAttachment; - } - - public String getUsername() { - return username; - } - - public UUID getUuid() { - return uuid; - } - - public void setForceUsePreset(int p) { - customTex = new byte[5]; - customTex[0] = (byte)1; - customTex[1] = (byte)(p >>> 24); - customTex[2] = (byte)(p >>> 16); - customTex[3] = (byte)(p >>> 8); - customTex[4] = (byte)(p & 0xFF); - } - - /** - * @param tex raw 32x32 pixel RGBA texture (4096 bytes long), see capes in "sources/resources/assets/eagler/capes" - */ - public void setForceUseCustom(byte[] tex) { - customTex = new byte[1174]; - customTex[0] = (byte)2; - EaglerXVelocityAPIHelper.convertCape32x32RGBAto23x17RGB(tex, 0, customTex, 1); - } - - public void setForceUseCustomByPacket(byte[] packet) { - customTex = packet; - } - - public byte[] getForceSetUseCustomPacket() { - return customTex; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterSkinEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterSkinEvent.java deleted file mode 100644 index 79425f15..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRegisterSkinEvent.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.util.UUID; - -import com.velocitypowered.api.util.GameProfile.Property; - -public class EaglercraftRegisterSkinEvent { - - private final Object authAttachment; - private final String username; - private final UUID uuid; - private Property useMojangProfileProperty = null; - private boolean useLoginResultTextures = false; - private byte[] customTex = null; - - public EaglercraftRegisterSkinEvent(String username, UUID uuid, Object authAttachment) { - this.username = username; - this.uuid = uuid; - this.authAttachment = authAttachment; - } - - public void setForceUseMojangProfileProperty(Property prop) { - useMojangProfileProperty = prop; - useLoginResultTextures = false; - customTex = null; - } - - public void setForceUseLoginResultObjectTextures(boolean b) { - useMojangProfileProperty = null; - useLoginResultTextures = b; - customTex = null; - } - - public void setForceUsePreset(int p) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = new byte[5]; - customTex[0] = (byte)1; - customTex[1] = (byte)(p >>> 24); - customTex[2] = (byte)(p >>> 16); - customTex[3] = (byte)(p >>> 8); - customTex[4] = (byte)(p & 0xFF); - } - - /** - * @param tex raw 64x64 pixel RGBA texture (16384 bytes long) - */ - public void setForceUseCustom(int model, byte[] tex) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = new byte[2 + tex.length]; - customTex[0] = (byte)2; - customTex[1] = (byte)model; - System.arraycopy(tex, 0, customTex, 2, tex.length); - } - - public void setForceUseCustomByPacket(byte[] packet) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = packet; - } - - public String getUsername() { - return username; - } - - public UUID getUuid() { - return uuid; - } - - public Property getForceUseMojangProfileProperty() { - return useMojangProfileProperty; - } - - public boolean getForceUseLoginResultObjectTextures() { - return useLoginResultTextures; - } - - public byte[] getForceSetUseCustomPacket() { - return customTex; - } - - public T getAuthAttachment() { - return (T)authAttachment; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRevokeSessionQueryEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRevokeSessionQueryEvent.java deleted file mode 100644 index 1670174b..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRevokeSessionQueryEvent.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query.RevokeSessionQueryHandler; - -public class EaglercraftRevokeSessionQueryEvent { - - private final InetAddress remoteAddress; - private final String origin; - private final byte[] cookieData; - private final RevokeSessionQueryHandler queryHandler; - private EnumSessionRevokeStatus revokeStatus; - private boolean shouldDeleteCookie; - - public static enum EnumSessionRevokeStatus { - SUCCESS("ok", -1), FAILED_NOT_SUPPORTED("error", 1), FAILED_NOT_ALLOWED("error", 2), - FAILED_NOT_FOUND("error", 3), FAILED_SERVER_ERROR("error", 4); - - public final String status; - public final int code; - - private EnumSessionRevokeStatus(String status, int code) { - this.status = status; - this.code = code; - } - } - - public EaglercraftRevokeSessionQueryEvent(InetAddress remoteAddress, String origin, byte[] cookieData, - RevokeSessionQueryHandler queryHandler) { - this.remoteAddress = remoteAddress; - this.origin = origin; - this.cookieData = cookieData; - this.queryHandler = queryHandler; - this.revokeStatus = EnumSessionRevokeStatus.FAILED_NOT_SUPPORTED; - this.shouldDeleteCookie = false; - } - - public InetAddress getRemoteAddress() { - return remoteAddress; - } - - public String getOrigin() { - return origin; - } - - public byte[] getCookieData() { - return cookieData; - } - - public String getCookieDataString() { - return new String(cookieData, StandardCharsets.UTF_8); - } - - public RevokeSessionQueryHandler getQuery() { - return queryHandler; - } - - public void setResultStatus(EnumSessionRevokeStatus revokeStatus) { - this.revokeStatus = revokeStatus; - } - - public EnumSessionRevokeStatus getResultStatus() { - return revokeStatus; - } - - public boolean getShouldDeleteCookie() { - return shouldDeleteCookie; - } - - public void setShouldDeleteCookie(boolean b) { - this.shouldDeleteCookie = b; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftVoiceStatusChangeEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftVoiceStatusChangeEvent.java deleted file mode 100644 index d012e5cc..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftVoiceStatusChangeEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import com.velocitypowered.api.proxy.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; - -public class EaglercraftVoiceStatusChangeEvent { - - public static enum EnumVoiceState { - SERVER_DISABLE, DISABLED, ENABLED; - } - - private final Player playerObj; - private final EaglerListenerConfig listener; - private final EaglerPlayerData eaglerHandler; - private final EnumVoiceState voiceStateOld; - private final EnumVoiceState voiceStateNew; - - public EaglercraftVoiceStatusChangeEvent(Player playerObj, EaglerListenerConfig listener, - EaglerPlayerData eaglerHandler, EnumVoiceState voiceStateOld, EnumVoiceState voiceStateNew) { - this.playerObj = playerObj; - this.listener = listener; - this.eaglerHandler = eaglerHandler; - this.voiceStateOld = voiceStateOld; - this.voiceStateNew = voiceStateNew; - } - - public Player getPlayerObj() { - return playerObj; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public EaglerPlayerData getEaglerHandler() { - return eaglerHandler; - } - - public EnumVoiceState getVoiceStateOld() { - return voiceStateOld; - } - - public EnumVoiceState getVoiceStateNew() { - return voiceStateNew; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebSocketOpenEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebSocketOpenEvent.java deleted file mode 100644 index c69f263e..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebSocketOpenEvent.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import io.netty.channel.Channel; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftWebSocketOpenEvent { - - private final Channel channel; - private final EaglerListenerConfig listener; - private final String realIP; - private final String origin; - private final String userAgent; - private boolean cancelled = false; - - public EaglercraftWebSocketOpenEvent(Channel channel, EaglerListenerConfig listener, String realIP, String origin, String userAgent) { - this.channel = channel; - this.listener = listener; - this.realIP = realIP; - this.origin = origin; - this.userAgent = userAgent; - } - - public boolean isCancelled() { - return cancelled; - } - - public void setCancelled(boolean var1) { - cancelled = var1; - } - - public Channel getChannel() { - return channel; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public String getRealIP() { - return realIP; - } - - public String getOrigin() { - return origin; - } - - public String getUserAgent() { - return userAgent; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewChannelEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewChannelEvent.java deleted file mode 100644 index ab30df88..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewChannelEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import com.velocitypowered.api.proxy.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class EaglercraftWebViewChannelEvent { - - public static enum EventType { - CHANNEL_OPEN, CHANNEL_CLOSE; - } - - private final Player player; - private final EaglerListenerConfig listener; - private final String channel; - private final EventType type; - - public EaglercraftWebViewChannelEvent(Player player, EaglerListenerConfig listener, String channel, EventType type) { - this.player = player; - this.listener = listener; - this.channel = channel; - this.type = type; - } - - public Player getPlayer() { - return player; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public String getChannel() { - return channel; - } - - public EventType getType() { - return type; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewMessageEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewMessageEvent.java deleted file mode 100644 index d7be8470..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewMessageEvent.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; - -import java.nio.charset.StandardCharsets; - -import com.velocitypowered.api.proxy.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.CPacketWebViewMessageV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketWebViewMessageV4EAG; - -public class EaglercraftWebViewMessageEvent { - - public static enum MessageType { - STRING(SPacketWebViewMessageV4EAG.TYPE_STRING), BINARY(SPacketWebViewMessageV4EAG.TYPE_BINARY); - - private final int id; - - private MessageType(int id) { - this.id = id; - } - - private static MessageType fromId(int id) { - switch(id) { - case CPacketWebViewMessageV4EAG.TYPE_STRING: - return STRING; - default: - case CPacketWebViewMessageV4EAG.TYPE_BINARY: - return BINARY; - } - } - } - - private final Player player; - private final EaglerListenerConfig listener; - private final String currentChannel; - private final EaglerPlayerData eaglerHandler; - private final MessageType type; - private final byte[] data; - private String asString; - - public EaglercraftWebViewMessageEvent(Player player, EaglerListenerConfig listener, String currentChannel, MessageType type, byte[] data) { - this.player = player; - this.listener = listener; - this.currentChannel = currentChannel; - this.eaglerHandler = EaglerXVelocityAPIHelper.getEaglerHandle(player); - this.type = type; - this.data = data; - } - - public EaglercraftWebViewMessageEvent(Player player, EaglerListenerConfig listener, String currentChannel, CPacketWebViewMessageV4EAG packet) { - this.player = player; - this.listener = listener; - this.currentChannel = currentChannel; - this.eaglerHandler = EaglerXVelocityAPIHelper.getEaglerHandle(player); - this.type = MessageType.fromId(packet.type); - this.data = packet.data; - } - - public Player getPlayer() { - return player; - } - - public EaglerListenerConfig getListener() { - return listener; - } - - public EaglerPlayerData getEaglerHandle() { - return eaglerHandler; - } - - public void sendResponse(MessageType type, byte[] data) { - eaglerHandler.sendEaglerMessage(new SPacketWebViewMessageV4EAG(type.id, data)); - } - - public void sendResponse(String str) { - sendResponse(MessageType.STRING, str.getBytes(StandardCharsets.UTF_8)); - } - - public void sendResponse(byte[] data) { - sendResponse(MessageType.BINARY, data); - } - - public MessageType getType() { - return type; - } - - public byte[] getAsBinary() { - return data; - } - - public String getAsString() { - if(asString == null) { - asString = new String(data, StandardCharsets.UTF_8); - } - return asString; - } - - public String getChannelName() { - return currentChannel; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQueryHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQueryHandler.java deleted file mode 100644 index 19fefc01..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQueryHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.HttpServerQueryHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query.QueryManager; - -public abstract class EaglerQueryHandler extends HttpServerQueryHandler { - - public static void registerQueryType(String name, Class clazz) { - QueryManager.registerQueryType(name, clazz); - } - - public static void unregisterQueryType(String name) { - QueryManager.unregisterQueryType(name); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQuerySimpleHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQuerySimpleHandler.java deleted file mode 100644 index 7aef6885..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/EaglerQuerySimpleHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query; - -import com.google.gson.JsonObject; - -public abstract class EaglerQuerySimpleHandler extends EaglerQueryHandler { - - @Override - protected void processString(String str) { - throw new UnexpectedDataException(); - } - - @Override - protected void processJson(JsonObject obj) { - throw new UnexpectedDataException(); - } - - @Override - protected void processBytes(byte[] bytes) { - throw new UnexpectedDataException(); - } - - @Override - protected void acceptText() { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptText(boolean bool) { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptBinary() { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void acceptBinary(boolean bool) { - throw new UnsupportedOperationException("EaglerQuerySimpleHandler does not support duplex"); - } - - @Override - protected void closed() { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/MOTDConnection.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/MOTDConnection.java deleted file mode 100644 index 22349ac0..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/query/MOTDConnection.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query; - -import java.net.InetAddress; -import java.util.List; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public interface MOTDConnection { - - boolean isClosed(); - void close(); - - String getAccept(); - InetAddress getAddress(); - EaglerListenerConfig getListener(); - long getConnectionTimestamp(); - - public default long getConnectionAge() { - return EaglerXVelocityAPIHelper.steadyTimeMillis() - getConnectionTimestamp(); - } - - void sendToUser(); - void setKeepAlive(boolean enable); - - String getLine1(); - String getLine2(); - List getPlayerList(); - int[] getBitmap(); - int getOnlinePlayers(); - int getMaxPlayers(); - String getSubType(); - - void setLine1(String p); - void setLine2(String p); - void setPlayerList(List p); - void setPlayerList(String... p); - void setBitmap(int[] p); - void setOnlinePlayers(int i); - void setMaxPlayers(int i); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/AuthLoadingCache.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/AuthLoadingCache.java deleted file mode 100644 index eb991c05..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/AuthLoadingCache.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class AuthLoadingCache { - - private static class CacheEntry { - - private long lastHit; - private V instance; - - private CacheEntry(V instance) { - this.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - this.instance = instance; - } - - } - - public static interface CacheLoader { - V load(K key); - } - - public static interface CacheVisitor { - boolean shouldEvict(K key, V value); - } - - private final ReadWriteLock cacheMapLock; - private final Map> cacheMap; - private final CacheLoader provider; - private final long cacheTTL; - - private long cacheTimer; - - public AuthLoadingCache(CacheLoader provider, long cacheTTL) { - this.cacheMapLock = new ReentrantReadWriteLock(); - this.cacheMap = new HashMap<>(); - this.provider = provider; - this.cacheTTL = cacheTTL; - } - - public V get(K key) { - CacheEntry etr; - cacheMapLock.readLock().lock(); - try { - etr = cacheMap.get(key); - }finally { - cacheMapLock.readLock().unlock(); - } - if(etr == null) { - cacheMapLock.writeLock().lock(); - V loaded = provider.load(key); - try { - cacheMap.put(key, new CacheEntry<>(loaded)); - }finally { - cacheMapLock.writeLock().unlock(); - } - return loaded; - }else { - etr.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - return etr.instance; - } - } - - public void evict(K key) { - cacheMapLock.writeLock().lock(); - try { - cacheMap.remove(key); - }finally { - cacheMapLock.writeLock().unlock(); - } - } - - public void evictAll(CacheVisitor visitor) { - cacheMapLock.writeLock().lock(); - try { - Iterator>> itr = cacheMap.entrySet().iterator(); - while(itr.hasNext()) { - Entry> etr = itr.next(); - if(visitor.shouldEvict(etr.getKey(), etr.getValue().instance)) { - itr.remove(); - } - } - }finally { - cacheMapLock.writeLock().unlock(); - } - } - - public void tick() { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - if(millis - cacheTimer > (cacheTTL / 2L)) { - cacheTimer = millis; - cacheMapLock.writeLock().lock(); - try { - Iterator> mapItr = cacheMap.values().iterator(); - while(mapItr.hasNext()) { - CacheEntry etr = mapItr.next(); - if(millis - etr.lastHit > cacheTTL) { - mapItr.remove(); - } - } - }finally { - cacheMapLock.writeLock().unlock(); - } - } - } - - public void flush() { - cacheMapLock.writeLock().lock(); - try { - cacheMap.clear(); - }finally { - cacheMapLock.writeLock().unlock(); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/DefaultAuthSystem.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/DefaultAuthSystem.java deleted file mode 100644 index 809fbeba..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/DefaultAuthSystem.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; -import java.util.Properties; -import java.util.Random; -import java.util.UUID; -import com.velocitypowered.api.event.connection.PostLoginEvent; -import com.velocitypowered.api.util.GameProfile; -import com.velocitypowered.api.util.GameProfile.Property; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftHandleAuthPasswordEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent.AuthMethod; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent.AuthResponse; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.Base64; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.sqlite.EaglerDrivers; - -public class DefaultAuthSystem { - - public static class AuthSystemException extends RuntimeException { - - public AuthSystemException() { - } - - public AuthSystemException(String message, Throwable cause) { - super(message, cause); - } - - public AuthSystemException(String message) { - super(message); - } - - public AuthSystemException(Throwable cause) { - super(cause); - } - - } - - protected final String uri; - protected final Connection databaseConnection; - protected final String passwordPromptScreenText; - protected final String wrongPasswordScreenText; - protected final String notRegisteredScreenText; - protected final String eaglerCommandName; - protected final String useRegisterCommandText; - protected final String useChangeCommandText; - protected final String commandSuccessText; - protected final String lastEaglerLoginMessage; - protected final String tooManyRegistrationsMessage; - protected final String needVanillaToRegisterMessage; - protected final boolean overrideEaglerToVanillaSkins; - protected final int maxRegistrationsPerIP; - - protected final SecureRandom secureRandom; - - public static DefaultAuthSystem initializeAuthSystem(EaglerAuthConfig config) throws AuthSystemException { - String databaseURI = config.getDatabaseURI(); - Connection conn; - try { - conn = EaglerDrivers.connectToDatabase(databaseURI, config.getDriverClass(), config.getDriverPath(), new Properties()); - if(conn == null) { - throw new IllegalStateException("Connection is null"); - } - }catch(Throwable t) { - throw new AuthSystemException("Could not initialize '" + databaseURI + "'!", t); - } - EaglerXVelocity.logger().info("Connected to database: " + databaseURI); - try { - try(Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE IF NOT EXISTS \"eaglercraft_accounts\" (" - + "\"Version\" TINYINT NOT NULL," - + "\"MojangUUID\" TEXT(32) NOT NULL," - + "\"MojangUsername\" TEXT(16) NOT NULL," - + "\"HashBase\" BLOB NOT NULL," - + "\"HashSalt\" BLOB NOT NULL," - + "\"MojangTextures\" BLOB," - + "\"Registered\" DATETIME NOT NULL," - + "\"RegisteredIP\" VARCHAR(42) NOT NULL," - + "\"LastLogin\" DATETIME," - + "\"LastLoginIP\" VARCHAR(42)," - + "PRIMARY KEY(\"MojangUUID\"))"); - stmt.execute("CREATE UNIQUE INDEX IF NOT EXISTS \"MojangUsername\" ON " - + "\"eaglercraft_accounts\" (\"MojangUsername\")"); - } - return new DefaultAuthSystem(databaseURI, conn, config.getPasswordPromptScreenText(), - config.getWrongPasswordScreenText(), config.getNotRegisteredScreenText(), - config.getEaglerCommandName(), config.getUseRegisterCommandText(), config.getUseChangeCommandText(), - config.getCommandSuccessText(), config.getLastEaglerLoginMessage(), - config.getTooManyRegistrationsMessage(), config.getNeedVanillaToRegisterMessage(), - config.getOverrideEaglerToVanillaSkins(), config.getMaxRegistrationsPerIP()); - }catch(AuthSystemException ex) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw ex; - }catch(Throwable t) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw new AuthSystemException("Could not initialize '" + databaseURI + "'!", t); - } - } - - protected final PreparedStatement registerUser; - protected final PreparedStatement isRegisteredUser; - protected final PreparedStatement pruneUsers; - protected final PreparedStatement updatePassword; - protected final PreparedStatement updateMojangUsername; - protected final PreparedStatement getRegistrationsOnIP; - protected final PreparedStatement checkRegistrationByUUID; - protected final PreparedStatement checkRegistrationByName; - protected final PreparedStatement setLastLogin; - protected final PreparedStatement updateTextures; - - protected class AccountLoader implements AuthLoadingCache.CacheLoader { - - @Override - public CachedAccountInfo load(String key) { - try { - CachedAccountInfo cachedInfo = null; - synchronized(checkRegistrationByName) { - checkRegistrationByName.setString(1, key); - try(ResultSet res = checkRegistrationByName.executeQuery()) { - if (res.next()) { - cachedInfo = new CachedAccountInfo(res.getInt(1), parseMojangUUID(res.getString(2)), key, - res.getBytes(3), res.getBytes(4), res.getBytes(5), res.getDate(6), res.getString(7), - res.getDate(8), res.getString(9)); - } - } - } - return cachedInfo; - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - - } - - protected class CachedAccountInfo { - - protected int version; - protected UUID mojangUUID; - protected String mojangUsername; - protected byte[] texturesProperty; - protected byte[] hashBase; - protected byte[] hashSalt; - protected long registered; - protected String registeredIP; - protected long lastLogin; - protected String lastLoginIP; - - protected CachedAccountInfo(int version, UUID mojangUUID, String mojangUsername, byte[] texturesProperty, - byte[] hashBase, byte[] hashSalt, Date registered, String registeredIP, Date lastLogin, - String lastLoginIP) { - this(version, mojangUUID, mojangUsername, texturesProperty, hashBase, hashSalt, - registered == null ? 0l : registered.getTime(), registeredIP, - lastLogin == null ? 0l : lastLogin.getTime(), lastLoginIP); - } - - protected CachedAccountInfo(int version, UUID mojangUUID, String mojangUsername, byte[] texturesProperty, - byte[] hashBase, byte[] hashSalt, long registered, String registeredIP, long lastLogin, - String lastLoginIP) { - this.version = version; - this.mojangUUID = mojangUUID; - this.mojangUsername = mojangUsername; - this.texturesProperty = texturesProperty; - this.hashBase = hashBase; - this.hashSalt = hashSalt; - this.registered = registered; - this.registeredIP = registeredIP; - this.lastLogin = lastLogin; - this.lastLoginIP = lastLoginIP; - } - - } - - protected final AuthLoadingCache authLoadingCache; - - protected DefaultAuthSystem(String uri, Connection databaseConnection, String passwordPromptScreenText, - String wrongPasswordScreenText, String notRegisteredScreenText, String eaglerCommandName, - String useRegisterCommandText, String useChangeCommandText, String commandSuccessText, - String lastEaglerLoginMessage, String tooManyRegistrationsMessage, String needVanillaToRegisterMessage, - boolean overrideEaglerToVanillaSkins, int maxRegistrationsPerIP) throws SQLException { - this.uri = uri; - this.databaseConnection = databaseConnection; - this.passwordPromptScreenText = passwordPromptScreenText; - this.wrongPasswordScreenText = wrongPasswordScreenText; - this.notRegisteredScreenText = notRegisteredScreenText; - this.eaglerCommandName = eaglerCommandName; - this.useRegisterCommandText = useRegisterCommandText; - this.useChangeCommandText = useChangeCommandText; - this.commandSuccessText = commandSuccessText; - this.lastEaglerLoginMessage = lastEaglerLoginMessage; - this.tooManyRegistrationsMessage = tooManyRegistrationsMessage; - this.needVanillaToRegisterMessage = needVanillaToRegisterMessage; - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - this.maxRegistrationsPerIP = maxRegistrationsPerIP; - this.registerUser = databaseConnection.prepareStatement("INSERT INTO eaglercraft_accounts (Version, MojangUUID, MojangUsername, MojangTextures, HashBase, HashSalt, Registered, RegisteredIP) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); - this.isRegisteredUser = databaseConnection.prepareStatement("SELECT COUNT(MojangUUID) AS total_accounts FROM eaglercraft_accounts WHERE MojangUUID = ?"); - this.pruneUsers = databaseConnection.prepareStatement("DELETE FROM eaglercraft_accounts WHERE LastLogin < ?"); - this.updatePassword = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET HashBase = ?, HashSalt = ? WHERE MojangUUID = ?"); - this.updateMojangUsername = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET MojangUsername = ? WHERE MojangUUID = ?"); - this.getRegistrationsOnIP = databaseConnection.prepareStatement("SELECT COUNT(MojangUUID) AS total_accounts FROM eaglercraft_accounts WHERE RegisteredIP = ?"); - this.checkRegistrationByUUID = databaseConnection.prepareStatement("SELECT Version, MojangUsername, LastLogin, LastLoginIP FROM eaglercraft_accounts WHERE MojangUUID = ?"); - this.checkRegistrationByName = databaseConnection.prepareStatement("SELECT Version, MojangUUID, MojangTextures, HashBase, HashSalt, Registered, RegisteredIP, LastLogin, LastLoginIP FROM eaglercraft_accounts WHERE MojangUsername = ?"); - this.setLastLogin = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET LastLogin = ?, LastLoginIP = ? WHERE MojangUUID = ?"); - this.updateTextures = databaseConnection.prepareStatement("UPDATE eaglercraft_accounts SET MojangTextures = ? WHERE MojangUUID = ?"); - this.authLoadingCache = new AuthLoadingCache<>(new AccountLoader(), 120000l); - this.secureRandom = new SecureRandom(); - } - - public void handleIsAuthRequiredEvent(EaglercraftIsAuthRequiredEvent event) { - String username = new String(event.getAuthUsername(), StandardCharsets.US_ASCII); - - String usrs = username.toString(); - if(!usrs.equals(usrs.replaceAll("[^A-Za-z0-9_]", "_").trim())) { - event.kickUser("Invalid characters in username"); - return; - } - - if(username.length() < 3) { - event.kickUser("Username must be at least 3 characters"); - return; - } - - if(username.length() > 16) { - event.kickUser("Username must be under 16 characters"); - return; - } - - CachedAccountInfo info = authLoadingCache.get(username); - if(info == null) { - event.kickUser(notRegisteredScreenText); - return; - } - - event.setAuthAttachment(info); - event.setAuthRequired(AuthResponse.REQUIRE); - event.setAuthMessage(passwordPromptScreenText); - event.setUseAuthMethod(AuthMethod.EAGLER_SHA256); - - byte[] randomBytes = new byte[32]; - Random rng; - synchronized(secureRandom) { - rng = new Random(secureRandom.nextLong()); - } - - rng.nextBytes(randomBytes); - - byte[] saltingData = new byte[64]; - System.arraycopy(info.hashSalt, 0, saltingData, 0, 32); - System.arraycopy(randomBytes, 0, saltingData, 32, 32); - - event.setSaltingData(saltingData); - } - - public void handleAuthPasswordEvent(EaglercraftHandleAuthPasswordEvent event) { - CachedAccountInfo info = event.getAuthAttachment(); - - if(info == null) { - event.setLoginDenied(notRegisteredScreenText); - return; - } - - - byte[] responseHash = event.getAuthPasswordDataResponse(); - - if(responseHash.length != 32) { - event.setLoginDenied("Wrong number of bits in checksum!"); - return; - } - - byte[] saltingData = event.getAuthSaltingData(); - - SHA256Digest digest = new SHA256Digest(); - - digest.update(info.hashBase, 0, 32); - digest.update(saltingData, 32, 32); - digest.update(HashUtils.EAGLER_SHA256_SALT_BASE, 0, 32); - - byte[] hashed = new byte[32]; - digest.doFinal(hashed, 0); - - if(!Arrays.equals(hashed, responseHash)) { - event.setLoginDenied(wrongPasswordScreenText); - EaglerXVelocity.logger().warn("User \"{}\" entered the wrong password while logging in from: {}", info.mojangUsername, event.getRemoteAddress().getHostAddress()); - return; - } - - try { - synchronized(setLastLogin) { - setLastLogin.setDate(1, new Date(System.currentTimeMillis())); - setLastLogin.setString(2, event.getRemoteAddress().getHostAddress()); - setLastLogin.setString(3, getMojangUUID(info.mojangUUID)); - if(setLastLogin.executeUpdate() == 0) { - throw new SQLException("Query did not alter the database"); - } - } - }catch(SQLException ex) { - EaglerXVelocity.logger().error("Could not update last login for \"{}\"", info.mojangUUID, ex); - } - - event.setLoginAllowed(); - event.setProfileUsername(info.mojangUsername); - event.setProfileUUID(info.mojangUUID); - - byte[] texturesProp = info.texturesProperty; - if(texturesProp != null) { - try { - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(texturesProp)); - int valueLen = dis.readInt(); - int sigLen = dis.readInt(); - byte[] valueBytes = new byte[valueLen]; - dis.read(valueBytes); - String valueB64 = Base64.encodeBase64String(valueBytes); - String sigB64 = null; - if(sigLen > 0) { - valueBytes = new byte[sigLen]; - dis.read(valueBytes); - sigB64 = Base64.encodeBase64String(valueBytes); - } - event.applyTexturesProperty(valueB64, sigB64); - event.setOverrideEaglerToVanillaSkins(overrideEaglerToVanillaSkins); - }catch(IOException ex) { - } - } - } - - public void processSetPassword(ConnectedPlayer player, String password) throws TooManyRegisteredOnIPException, AuthException { - if(EaglerPipeline.getEaglerHandle(player) != null) { - throw new AuthException("Cannot register from an eaglercraft account!"); - }else if(!player.isOnlineMode()) { - throw new AuthException("Cannot register without online mode enabled!"); - }else { - try { - String uuid = getMojangUUID(player.getUniqueId()); - synchronized(registerUser) { - int cnt; - synchronized(isRegisteredUser) { - isRegisteredUser.setString(1, uuid); - try(ResultSet set = isRegisteredUser.executeQuery()) { - if(set.next()) { - cnt = set.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved while checking if user exists"); - } - } - } - - SHA256Digest digest = new SHA256Digest(); - - int passLen = password.length(); - - digest.update((byte)((passLen >> 8) & 0xFF)); - digest.update((byte)(passLen & 0xFF)); - for(int i = 0; i < passLen; ++i) { - char codePoint = password.charAt(i); - digest.update((byte)((codePoint >> 8) & 0xFF)); - digest.update((byte)(codePoint & 0xFF)); - } - - digest.update(HashUtils.EAGLER_SHA256_SALT_SAVE, 0, 32); - - byte[] hashed = new byte[32]; - digest.doFinal(hashed, 0); - - byte[] randomBytes = new byte[32]; - synchronized(secureRandom) { - secureRandom.nextBytes(randomBytes); - } - - digest.reset(); - - digest.update(hashed, 0, 32); - digest.update(randomBytes, 0, 32); - digest.update(HashUtils.EAGLER_SHA256_SALT_BASE, 0, 32); - - digest.doFinal(hashed, 0); - - String username = player.getUsername(); - authLoadingCache.evict(username); - - if(cnt > 0) { - synchronized(updatePassword) { - updatePassword.setBytes(1, hashed); - updatePassword.setBytes(2, randomBytes); - updatePassword.setString(3, uuid); - if(updatePassword.executeUpdate() <= 0) { - throw new AuthException("Update password query did not alter the database!"); - } - } - }else { - String sockAddr = sockAddrToString(player.getRemoteAddress()); - if(maxRegistrationsPerIP > 0) { - if(countUsersOnIP(sockAddr) >= maxRegistrationsPerIP) { - throw new TooManyRegisteredOnIPException(sockAddr); - } - } - Date nowDate = new Date(System.currentTimeMillis()); - registerUser.setInt(1, 1); - registerUser.setString(2, uuid); - registerUser.setString(3, username); - GameProfile res = player.getGameProfile(); - if(res != null) { - registerUser.setBytes(4, getTexturesProperty(res)); - }else { - registerUser.setBytes(4, null); - } - registerUser.setBytes(5, hashed); - registerUser.setBytes(6, randomBytes); - registerUser.setDate(7, nowDate); - registerUser.setString(8, sockAddr); - if(registerUser.executeUpdate() <= 0) { - throw new AuthException("Registration query did not alter the database!"); - } - } - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - } - - private static byte[] getTexturesProperty(GameProfile profile) { - if(profile == null) { - return null; - } - try { - List props = profile.getProperties(); - for(int i = 0, l = props.size(); i < l; ++i) { - Property prop = props.get(i); - if("textures".equals(prop.getName())) { - byte[] texturesData = Base64.decodeBase64(prop.getValue()); - byte[] signatureData = prop.getSignature() == null ? new byte[0] : Base64.decodeBase64(prop.getSignature()); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dao = new DataOutputStream(bao); - dao.writeInt(texturesData.length); - dao.writeInt(signatureData.length); - dao.write(texturesData); - dao.write(signatureData); - return bao.toByteArray(); - } - } - }catch(Throwable t) { - } - return null; - } - - public int pruneUsers(long before) throws AuthException { - try { - authLoadingCache.flush(); - synchronized(pruneUsers) { - pruneUsers.setDate(1, new Date(before)); - return pruneUsers.executeUpdate(); - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - - public int countUsersOnIP(String addr) throws AuthException { - synchronized(getRegistrationsOnIP) { - try { - getRegistrationsOnIP.setString(1, addr); - try(ResultSet set = getRegistrationsOnIP.executeQuery()) { - if(set.next()) { - return set.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved while counting accounts"); - } - } - }catch(SQLException ex) { - throw new AuthException("Failed to query database!", ex); - } - } - } - - public void handleVanillaLogin(PostLoginEvent loginEvent) { - ConnectedPlayer player = (ConnectedPlayer)loginEvent.getPlayer(); - if(EaglerPipeline.getEaglerHandle(player) == null) { - Date lastLogin = null; - String lastLoginIP = null; - boolean isRegistered = false; - synchronized(checkRegistrationByUUID) { - UUID uuid = player.getUniqueId(); - try { - String uuidString = getMojangUUID(uuid); - checkRegistrationByUUID.setString(1, getMojangUUID(player.getUniqueId())); - try(ResultSet res = checkRegistrationByUUID.executeQuery()) { - if(res.next()) { - isRegistered = true; - int vers = res.getInt(1); - String username = res.getString(2); - lastLogin = res.getDate(3); - lastLoginIP = res.getString(4); - String playerName = player.getUsername(); - if(!playerName.equals(username)) { - EaglerXVelocity.logger().info( - "Player \"{}\" changed their username from \"{}\" to \"{}\", updating authentication database...", - uuid, username, playerName); - synchronized(updateMojangUsername) { - updateMojangUsername.setString(1, playerName); - updateMojangUsername.setString(2, uuidString); - if(updateMojangUsername.executeUpdate() == 0) { - throw new SQLException("Failed to update username to \"" + playerName + "\""); - } - } - } - } - } - byte[] texProperty = getTexturesProperty(player.getGameProfile()); - if(texProperty != null) { - synchronized(updateTextures) { - updateTextures.setBytes(1, texProperty); - updateTextures.setString(2, uuidString); - updateTextures.executeUpdate(); - } - } - }catch(SQLException ex) { - EaglerXVelocity.logger().error("Could not look up UUID \"{}\" in auth database!", uuid, ex); - } - } - if(isRegistered) { - if(lastLogin != null) { - String dateStr; - java.util.Date juLastLogin = new java.util.Date(lastLogin.getTime()); - Calendar calendar = Calendar.getInstance(); - int yearToday = calendar.get(Calendar.YEAR); - calendar.setTime(juLastLogin); - if(calendar.get(Calendar.YEAR) != yearToday) { - dateStr = (new SimpleDateFormat("EE, MMM d, yyyy, HH:mm z")).format(juLastLogin); - }else { - dateStr = (new SimpleDateFormat("EE, MMM d, HH:mm z")).format(juLastLogin); - } - player.sendMessage(Component.text( - lastEaglerLoginMessage.replace("$date", dateStr).replace("$ip", "" + lastLoginIP), - NamedTextColor.GREEN)); - } - player.sendMessage(Component.text(useChangeCommandText)); - }else { - player.sendMessage(Component.text(useRegisterCommandText)); - } - } - } - - private void destroyStatement(Statement stmt) { - try { - stmt.close(); - } catch (SQLException e) { - } - } - - public void flush() { - authLoadingCache.flush(); - } - - public void destroy() { - destroyStatement(registerUser); - destroyStatement(isRegisteredUser); - destroyStatement(pruneUsers); - destroyStatement(updatePassword); - destroyStatement(updateMojangUsername); - destroyStatement(getRegistrationsOnIP); - destroyStatement(checkRegistrationByUUID); - destroyStatement(checkRegistrationByName); - destroyStatement(setLastLogin); - destroyStatement(updateTextures); - try { - databaseConnection.close(); - EaglerXVelocity.logger().info("Successfully disconnected from database '{}'", uri); - } catch (SQLException e) { - EaglerXVelocity.logger().warn("Exception disconnecting from database '{}'!", uri, e); - } - } - - public static class AuthException extends RuntimeException { - - public AuthException(String msg) { - super(msg); - } - - public AuthException(Throwable t) { - super(t); - } - - public AuthException(String msg, Throwable t) { - super(msg, t); - } - - } - - public static class TooManyRegisteredOnIPException extends AuthException { - - public TooManyRegisteredOnIPException(String ip) { - super(ip); - } - - } - - private static final String hexString = "0123456789abcdef"; - - private static final char[] HEX = new char[] { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - public static String getMojangUUID(UUID uuid) { - char[] ret = new char[32]; - long msb = uuid.getMostSignificantBits(); - long lsb = uuid.getLeastSignificantBits(); - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - ret[i] = HEX[(int)((msb >> j) & 15l)]; - ret[i + 16] = HEX[(int)((lsb >> j) & 15l)]; - } - return new String(ret); - } - - public static UUID parseMojangUUID(String uuid) { - long msb = 0l; - long lsb = 0l; - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - msb |= ((long)hexString.indexOf(uuid.charAt(i)) << j); - lsb |= ((long)hexString.indexOf(uuid.charAt(i + 16)) << j); - } - return new UUID(msb, lsb); - } - - private static String sockAddrToString(SocketAddress addr) { - if(addr instanceof InetSocketAddress) { - return ((InetSocketAddress)addr).getAddress().getHostAddress(); - }else { - return "127.0.0.1"; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/GeneralDigest.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/GeneralDigest.java deleted file mode 100644 index 0515b9ed..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/GeneralDigest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -/** - * base implementation of MD4 family style digest as outlined in "Handbook of - * Applied Cryptography", pages 344 - 347. - */ -public abstract class GeneralDigest { - private byte[] xBuf; - private int xBufOff; - - private long byteCount; - - /** - * Standard constructor - */ - protected GeneralDigest() { - xBuf = new byte[4]; - xBufOff = 0; - } - - /** - * Copy constructor. We are using copy constructors in place of the - * Object.clone() interface as this interface is not supported by J2ME. - */ - protected GeneralDigest(GeneralDigest t) { - xBuf = new byte[t.xBuf.length]; - System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length); - - xBufOff = t.xBufOff; - byteCount = t.byteCount; - } - - public void update(byte in) { - xBuf[xBufOff++] = in; - - if (xBufOff == xBuf.length) { - processWord(xBuf, 0); - xBufOff = 0; - } - - byteCount++; - } - - public void update(byte[] in, int inOff, int len) { - // - // fill the current word - // - while ((xBufOff != 0) && (len > 0)) { - update(in[inOff]); - - inOff++; - len--; - } - - // - // process whole words. - // - while (len > xBuf.length) { - processWord(in, inOff); - - inOff += xBuf.length; - len -= xBuf.length; - byteCount += xBuf.length; - } - - // - // load in the remainder. - // - while (len > 0) { - update(in[inOff]); - - inOff++; - len--; - } - } - - public void finish() { - long bitLength = (byteCount << 3); - - // - // add the pad bytes. - // - update((byte) 128); - - while (xBufOff != 0) { - update((byte) 0); - } - - processLength(bitLength); - - processBlock(); - } - - public void reset() { - byteCount = 0; - - xBufOff = 0; - for (int i = 0; i < xBuf.length; i++) { - xBuf[i] = 0; - } - } - - protected abstract void processWord(byte[] in, int inOff); - - protected abstract void processLength(long bitLength); - - protected abstract void processBlock(); -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/HashUtils.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/HashUtils.java deleted file mode 100644 index f38affce..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/HashUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -public class HashUtils { - - public static final byte[] EAGLER_SHA256_SALT_BASE = new byte[] { (byte) 117, (byte) 43, (byte) 1, (byte) 112, - (byte) 75, (byte) 3, (byte) 188, (byte) 61, (byte) 121, (byte) 31, (byte) 34, (byte) 181, (byte) 234, - (byte) 31, (byte) 247, (byte) 72, (byte) 12, (byte) 168, (byte) 138, (byte) 45, (byte) 143, (byte) 77, - (byte) 118, (byte) 245, (byte) 187, (byte) 242, (byte) 188, (byte) 219, (byte) 160, (byte) 235, (byte) 235, - (byte) 68 }; - - public static final byte[] EAGLER_SHA256_SALT_SAVE = new byte[] { (byte) 49, (byte) 25, (byte) 39, (byte) 38, - (byte) 253, (byte) 85, (byte) 70, (byte) 245, (byte) 71, (byte) 150, (byte) 253, (byte) 206, (byte) 4, - (byte) 26, (byte) 198, (byte) 249, (byte) 145, (byte) 251, (byte) 232, (byte) 174, (byte) 186, (byte) 98, - (byte) 27, (byte) 232, (byte) 55, (byte) 144, (byte) 83, (byte) 21, (byte) 36, (byte) 55, (byte) 170, - (byte) 118 }; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA1Digest.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA1Digest.java deleted file mode 100644 index ec0907d3..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA1Digest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -/** - * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", - * pages 346 - 349. - * - * It is interesting to ponder why the, apart from the extra IV, the other - * difference here from MD5 is the "endienness" of the word processing! - */ -public class SHA1Digest extends GeneralDigest { - private static final int DIGEST_LENGTH = 20; - - private int H1, H2, H3, H4, H5; - - private int[] X = new int[80]; - private int xOff; - - /** - * Standard constructor - */ - public SHA1Digest() { - reset(); - } - - /** - * Copy constructor. This will copy the state of the provided message digest. - */ - public SHA1Digest(SHA1Digest t) { - super(t); - - H1 = t.H1; - H2 = t.H2; - H3 = t.H3; - H4 = t.H4; - H5 = t.H5; - - System.arraycopy(t.X, 0, X, 0, t.X.length); - xOff = t.xOff; - } - - public String getAlgorithmName() { - return "SHA-1"; - } - - public int getDigestSize() { - return DIGEST_LENGTH; - } - - protected void processWord(byte[] in, int inOff) { - X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) | ((in[inOff + 2] & 0xff) << 8) - | ((in[inOff + 3] & 0xff)); - - if (xOff == 16) { - processBlock(); - } - } - - private void unpackWord(int word, byte[] out, int outOff) { - out[outOff] = (byte) (word >>> 24); - out[outOff + 1] = (byte) (word >>> 16); - out[outOff + 2] = (byte) (word >>> 8); - out[outOff + 3] = (byte) word; - } - - protected void processLength(long bitLength) { - if (xOff > 14) { - processBlock(); - } - - X[14] = (int) (bitLength >>> 32); - X[15] = (int) (bitLength & 0xffffffff); - } - - public int doFinal(byte[] out, int outOff) { - finish(); - - unpackWord(H1, out, outOff); - unpackWord(H2, out, outOff + 4); - unpackWord(H3, out, outOff + 8); - unpackWord(H4, out, outOff + 12); - unpackWord(H5, out, outOff + 16); - - reset(); - - return DIGEST_LENGTH; - } - - /** - * reset the chaining variables - */ - public void reset() { - super.reset(); - - H1 = 0x67452301; - H2 = 0xefcdab89; - H3 = 0x98badcfe; - H4 = 0x10325476; - H5 = 0xc3d2e1f0; - - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - // - // Additive constants - // - private static final int Y1 = 0x5a827999; - private static final int Y2 = 0x6ed9eba1; - private static final int Y3 = 0x8f1bbcdc; - private static final int Y4 = 0xca62c1d6; - - private int f(int u, int v, int w) { - return ((u & v) | ((~u) & w)); - } - - private int h(int u, int v, int w) { - return (u ^ v ^ w); - } - - private int g(int u, int v, int w) { - return ((u & v) | (u & w) | (v & w)); - } - - private int rotateLeft(int x, int n) { - return (x << n) | (x >>> (32 - n)); - } - - protected void processBlock() { - // - // expand 16 word block into 80 word block. - // - for (int i = 16; i <= 79; i++) { - X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1); - } - - // - // set up working variables. - // - int A = H1; - int B = H2; - int C = H3; - int D = H4; - int E = H5; - - // - // round 1 - // - for (int j = 0; j <= 19; j++) { - int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 2 - // - for (int j = 20; j <= 39; j++) { - int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 3 - // - for (int j = 40; j <= 59; j++) { - int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - // - // round 4 - // - for (int j = 60; j <= 79; j++) { - int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4; - - E = D; - D = C; - C = rotateLeft(B, 30); - B = A; - A = t; - } - - H1 += A; - H2 += B; - H3 += C; - H4 += D; - H5 += E; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - private static final String hex = "0123456789abcdef"; - - public static String hash2string(byte[] b) { - char[] ret = new char[b.length * 2]; - for(int i = 0; i < b.length; ++i) { - int bb = (int)b[i] & 0xFF; - ret[i * 2] = hex.charAt((bb >> 4) & 0xF); - ret[i * 2 + 1] = hex.charAt(bb & 0xF); - } - return new String(ret); - } - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA256Digest.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA256Digest.java deleted file mode 100644 index c10f97a4..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/auth/SHA256Digest.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2000-2021 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth; - -public class SHA256Digest extends GeneralDigest { - - private static final int DIGEST_LENGTH = 32; - - private int H1, H2, H3, H4, H5, H6, H7, H8; - - private int[] X = new int[64]; - private int xOff; - - public SHA256Digest() { - reset(); - } - - public static int bigEndianToInt(byte[] bs, int off) { - int n = bs[off] << 24; - n |= (bs[++off] & 0xff) << 16; - n |= (bs[++off] & 0xff) << 8; - n |= (bs[++off] & 0xff); - return n; - } - - public static void bigEndianToInt(byte[] bs, int off, int[] ns) { - for (int i = 0; i < ns.length; ++i) { - ns[i] = bigEndianToInt(bs, off); - off += 4; - } - } - - public static byte[] intToBigEndian(int n) { - byte[] bs = new byte[4]; - intToBigEndian(n, bs, 0); - return bs; - } - - public static void intToBigEndian(int n, byte[] bs, int off) { - bs[off] = (byte) (n >>> 24); - bs[++off] = (byte) (n >>> 16); - bs[++off] = (byte) (n >>> 8); - bs[++off] = (byte) (n); - } - - protected void processWord(byte[] in, int inOff) { - X[xOff] = bigEndianToInt(in, inOff); - - if (++xOff == 16) { - processBlock(); - } - } - - protected void processLength(long bitLength) { - if (xOff > 14) { - processBlock(); - } - - X[14] = (int) (bitLength >>> 32); - X[15] = (int) (bitLength & 0xffffffff); - } - - public int doFinal(byte[] out, int outOff) { - finish(); - - intToBigEndian(H1, out, outOff); - intToBigEndian(H2, out, outOff + 4); - intToBigEndian(H3, out, outOff + 8); - intToBigEndian(H4, out, outOff + 12); - intToBigEndian(H5, out, outOff + 16); - intToBigEndian(H6, out, outOff + 20); - intToBigEndian(H7, out, outOff + 24); - intToBigEndian(H8, out, outOff + 28); - - reset(); - - return DIGEST_LENGTH; - } - - /** - * reset the chaining variables - */ - public void reset() { - super.reset(); - - /* - * SHA-256 initial hash value The first 32 bits of the fractional parts of the - * square roots of the first eight prime numbers - */ - - H1 = 0x6a09e667; - H2 = 0xbb67ae85; - H3 = 0x3c6ef372; - H4 = 0xa54ff53a; - H5 = 0x510e527f; - H6 = 0x9b05688c; - H7 = 0x1f83d9ab; - H8 = 0x5be0cd19; - - xOff = 0; - for (int i = 0; i != X.length; i++) { - X[i] = 0; - } - } - - protected void processBlock() { - // - // expand 16 word block into 64 word blocks. - // - for (int t = 16; t <= 63; t++) { - X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16]; - } - - // - // set up working variables. - // - int a = H1; - int b = H2; - int c = H3; - int d = H4; - int e = H5; - int f = H6; - int g = H7; - int h = H8; - - int t = 0; - for (int i = 0; i < 8; i++) { - // t = 8 * i - h += Sum1(e) + Ch(e, f, g) + K[t] + X[t]; - d += h; - h += Sum0(a) + Maj(a, b, c); - ++t; - - // t = 8 * i + 1 - g += Sum1(d) + Ch(d, e, f) + K[t] + X[t]; - c += g; - g += Sum0(h) + Maj(h, a, b); - ++t; - - // t = 8 * i + 2 - f += Sum1(c) + Ch(c, d, e) + K[t] + X[t]; - b += f; - f += Sum0(g) + Maj(g, h, a); - ++t; - - // t = 8 * i + 3 - e += Sum1(b) + Ch(b, c, d) + K[t] + X[t]; - a += e; - e += Sum0(f) + Maj(f, g, h); - ++t; - - // t = 8 * i + 4 - d += Sum1(a) + Ch(a, b, c) + K[t] + X[t]; - h += d; - d += Sum0(e) + Maj(e, f, g); - ++t; - - // t = 8 * i + 5 - c += Sum1(h) + Ch(h, a, b) + K[t] + X[t]; - g += c; - c += Sum0(d) + Maj(d, e, f); - ++t; - - // t = 8 * i + 6 - b += Sum1(g) + Ch(g, h, a) + K[t] + X[t]; - f += b; - b += Sum0(c) + Maj(c, d, e); - ++t; - - // t = 8 * i + 7 - a += Sum1(f) + Ch(f, g, h) + K[t] + X[t]; - e += a; - a += Sum0(b) + Maj(b, c, d); - ++t; - } - - H1 += a; - H2 += b; - H3 += c; - H4 += d; - H5 += e; - H6 += f; - H7 += g; - H8 += h; - - // - // reset the offset and clean out the word buffer. - // - xOff = 0; - for (int i = 0; i < 16; i++) { - X[i] = 0; - } - } - - /* SHA-256 functions */ - private static int Ch(int x, int y, int z) { - return (x & y) ^ ((~x) & z); -// return z ^ (x & (y ^ z)); - } - - private static int Maj(int x, int y, int z) { -// return (x & y) ^ (x & z) ^ (y & z); - return (x & y) | (z & (x ^ y)); - } - - private static int Sum0(int x) { - return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10)); - } - - private static int Sum1(int x) { - return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7)); - } - - private static int Theta0(int x) { - return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3); - } - - private static int Theta1(int x) { - return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10); - } - - /* - * SHA-256 Constants (represent the first 32 bits of the fractional parts of the - * cube roots of the first sixty-four prime numbers) - */ - static final int K[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, - 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, - 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, - 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, - 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, - 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandClientBrand.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandClientBrand.java deleted file mode 100644 index a807906e..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandClientBrand.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import java.util.Optional; - -import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.proxy.Player; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; - -public class CommandClientBrand extends EaglerCommand { - - public CommandClientBrand() { - super("client-brand", "eaglercraft.command.clientbrand", "clientbrand"); - } - - @Override - public void execute(CommandSource var1, String[] var2) { - if(var2.length == 1) { - Optional player = EaglerXVelocity.proxy().getPlayer(var2[0]); - if(player.isPresent()) { - EaglerPlayerData playerData = EaglerPipeline.getEaglerHandle(player.get()); - if(playerData != null) { - var1.sendMessage(Component.text("Eagler Client Brand: ", NamedTextColor.BLUE).append(Component.text(playerData.getEaglerBrandString(), NamedTextColor.WHITE))); - var1.sendMessage(Component.text("Eagler Client Version: ", NamedTextColor.BLUE).append(Component.text(playerData.getEaglerVersionString(), NamedTextColor.WHITE))); - var1.sendMessage(Component.text("Eagler Client UUID: ", NamedTextColor.BLUE).append(Component.text(playerData.getClientBrandUUID().toString(), NamedTextColor.WHITE))); - var1.sendMessage(Component.text("Minecraft Client Brand: ", NamedTextColor.BLUE).append(Component.text(player.get().getClientBrand(), NamedTextColor.WHITE))); - }else { - var1.sendMessage(Component.text("That player is not using eaglercraft!", NamedTextColor.RED)); - } - }else { - var1.sendMessage(Component.text("That player was not found!", NamedTextColor.RED)); - } - return; - } - if(var2.length == 2) { - Optional player = EaglerXVelocity.proxy().getPlayer(var2[1]); - if(player.isPresent()) { - EaglerPlayerData playerData = EaglerPipeline.getEaglerHandle(player.get()); - if(playerData != null) { - if("uuid".equalsIgnoreCase(var2[0])) { - var1.sendMessage(Component.text("Eagler Client UUID: ", NamedTextColor.BLUE).append(Component.text(playerData.getClientBrandUUID().toString(), NamedTextColor.WHITE))); - return; - }else if("name".equalsIgnoreCase(var2[0])) { - var1.sendMessage(Component.text("Eagler Client Brand: ", NamedTextColor.BLUE).append(Component.text(playerData.getEaglerBrandString(), NamedTextColor.WHITE))); - var1.sendMessage(Component.text("Eagler Client Version: ", NamedTextColor.BLUE).append(Component.text(playerData.getEaglerVersionString(), NamedTextColor.WHITE))); - return; - }else if("mc".equalsIgnoreCase(var2[0])) { - var1.sendMessage(Component.text("Minecraft Client Brand: ", NamedTextColor.BLUE).append(Component.text(player.get().getClientBrand(), NamedTextColor.WHITE))); - return; - } - }else { - var1.sendMessage(Component.text("That player is not using eaglercraft!", NamedTextColor.RED)); - return; - } - }else { - var1.sendMessage(Component.text("That player was not found!", NamedTextColor.RED)); - return; - } - } - var1.sendMessage(Component.text("Usage: /client-brand [uuid|name|mc] ", NamedTextColor.RED)); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandConfirmCode.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandConfirmCode.java deleted file mode 100644 index 2302f38f..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandConfirmCode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import java.nio.charset.StandardCharsets; - -import com.velocitypowered.api.command.CommandSource; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.SHA1Digest; - -public class CommandConfirmCode extends EaglerCommand { - - public static String confirmHash = null; - - public CommandConfirmCode() { - super("confirm-code", "eaglercraft.command.confirmcode", "confirmcode"); - } - - @Override - public void execute(CommandSource var1, String[] var2) { - if(var2.length != 1) { - var1.sendMessage(Component.text("How to use: ", NamedTextColor.RED).append(Component.text("/confirm-code ", NamedTextColor.WHITE))); - }else { - var1.sendMessage(Component.text("Server list 2FA code has been set to: ", NamedTextColor.YELLOW).append(Component.text(var2[0], NamedTextColor.GREEN))); - var1.sendMessage(Component.text("You can now return to the server list site and continue", NamedTextColor.YELLOW)); - byte[] bts = var2[0].getBytes(StandardCharsets.US_ASCII); - SHA1Digest dg = new SHA1Digest(); - dg.update(bts, 0, bts.length); - byte[] f = new byte[20]; - dg.doFinal(f, 0); - confirmHash = SHA1Digest.hash2string(f); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandDomain.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandDomain.java deleted file mode 100644 index 020ace7a..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandDomain.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import java.util.Optional; - -import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.proxy.Player; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; - -public class CommandDomain extends EaglerCommand { - - public CommandDomain() { - super("domain", "eaglercraft.command.domain"); - } - - @Override - public void execute(CommandSource var1, String[] var2) { - if(var2.length != 1) { - var1.sendMessage(Component.text("How to use: ", NamedTextColor.RED).append(Component.text("/domain ", NamedTextColor.WHITE))); - }else { - Optional playerOpt = EaglerXVelocity.proxy().getPlayer(var2[0]); - if(playerOpt.isEmpty()) { - var1.sendMessage(Component.text("That user is not online", NamedTextColor.RED)); - return; - } - EaglerPlayerData eagPlayer = EaglerPipeline.getEaglerHandle(playerOpt.get()); - if(eagPlayer == null) { - var1.sendMessage(Component.text("That user is not using Eaglercraft", NamedTextColor.RED)); - return; - } - String origin = eagPlayer.getOrigin(); - if(origin != null) { - var1.sendMessage(Component.text("Domain of " + var2[0] + " is '" + origin + "'", NamedTextColor.BLUE)); - }else { - var1.sendMessage(Component.text("That user's browser did not send an origin header", NamedTextColor.RED)); - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerPurge.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerPurge.java deleted file mode 100644 index 7c8ad29e..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerPurge.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.proxy.ConsoleCommandSource; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem.AuthException; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerAuthConfig; - -public class CommandEaglerPurge extends EaglerCommand { - - public CommandEaglerPurge(String name) { - super(name + "-purge", "eaglercraft.command.purge"); - } - - @Override - public void execute(CommandSource var1, String[] var2) { - if(var1 instanceof ConsoleCommandSource) { - if(var2.length != 1) { - var1.sendMessage(Component.text("Use /" + name + " ", NamedTextColor.RED)); - return; - } - int mx; - try { - mx = Integer.parseInt(var2[0]); - }catch(NumberFormatException ex) { - var1.sendMessage(Component.text("'" + var2[0] + "' is not an integer!", NamedTextColor.RED)); - return; - } - EaglerAuthConfig authConf = EaglerXVelocity.getEagler().getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = EaglerXVelocity.getEagler().getAuthService(); - if(srv != null) { - int cnt; - try { - EaglerXVelocity.logger().warn("Console is attempting to purge all accounts with {} days of inactivity", mx); - cnt = srv.pruneUsers(System.currentTimeMillis() - mx * 86400000l); - }catch(AuthException ex) { - EaglerXVelocity.logger().error("Failed to purge accounts", ex); - var1.sendMessage(Component.text("Failed to purge, check log! Reason: " + ex.getMessage(), NamedTextColor.AQUA)); - return; - } - EaglerXVelocity.logger().warn("Console purged {} accounts from auth database", cnt); - var1.sendMessage(Component.text("Purged " + cnt + " old accounts from the database", NamedTextColor.AQUA)); - } - } - }else { - var1.sendMessage(Component.text("This command can only be run from the console!", NamedTextColor.RED)); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerRegister.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerRegister.java deleted file mode 100644 index 58093462..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandEaglerRegister.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; - -public class CommandEaglerRegister extends EaglerCommand { - - public CommandEaglerRegister(String name) { - super(name, null); - } - - @Override - public void execute(CommandSource sender, String[] args) { - if(sender instanceof ConnectedPlayer) { - ConnectedPlayer player = (ConnectedPlayer)sender; - if(args.length != 1) { - player.sendMessage(Component.text("Use: /" + name + " ", NamedTextColor.RED)); - return; - } - EaglerAuthConfig authConf = EaglerXVelocity.getEagler().getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = EaglerXVelocity.getEagler().getAuthService(); - if(srv != null) { - if(EaglerPipeline.getEaglerHandle(player) == null) { - try { - srv.processSetPassword(player, args[0]); - sender.sendMessage(Component.text(authConf.getCommandSuccessText())); - }catch(DefaultAuthSystem.TooManyRegisteredOnIPException ex) { - String tooManyReg = authConf.getTooManyRegistrationsMessage(); - sender.sendMessage(Component.text(tooManyReg)); - }catch(DefaultAuthSystem.AuthException ex) { - EaglerXVelocity.logger().error("Internal exception while processing password change from \"{}\"", player.getUsername(), ex); - sender.sendMessage(Component.text("Internal error, check console logs")); - } - }else { - player.sendMessage(Component.text(authConf.getNeedVanillaToRegisterMessage())); - } - } - } - }else { - sender.sendMessage(Component.text("You must be a player to use this command!", NamedTextColor.RED)); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandRatelimit.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandRatelimit.java deleted file mode 100644 index 0a918eb5..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandRatelimit.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import com.velocitypowered.api.command.CommandSource; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerRateLimiter; - -public class CommandRatelimit extends EaglerCommand { - - public CommandRatelimit() { - super("ratelimit", "eaglercraft.command.ratelimit"); - } - - @Override - public void execute(CommandSource sender, String[] args) { - if((args.length != 1 && args.length != 2) || !args[0].equalsIgnoreCase("reset")) { - sender.sendMessage(Component.text("Usage: /ratelimit reset [ip|login|motd|query]", NamedTextColor.RED)); //TODO: allow reset ratelimit on specific listeners - }else { - int resetNum = 0; - if(args.length == 2) { - if(args[1].equalsIgnoreCase("ip")) { - resetNum = 1; - }else if(args[1].equalsIgnoreCase("login")) { - resetNum = 2; - }else if(args[1].equalsIgnoreCase("motd")) { - resetNum = 3; - }else if(args[1].equalsIgnoreCase("query")) { - resetNum = 4; - }else { - sender.sendMessage(Component.text("Unknown ratelimit '" + args[1] + "'!", NamedTextColor.RED)); - return; - } - } - EaglerVelocityConfig conf = EaglerXVelocity.getEagler().getConfig(); - for(EaglerListenerConfig listener : conf.getServerListeners()) { - if(resetNum == 0 || resetNum == 1) { - EaglerRateLimiter limiter = listener.getRatelimitIp(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 2) { - EaglerRateLimiter limiter = listener.getRatelimitLogin(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 3) { - EaglerRateLimiter limiter = listener.getRatelimitMOTD(); - if(limiter != null) { - limiter.reset(); - } - } - if(resetNum == 0 || resetNum == 4) { - EaglerRateLimiter limiter = listener.getRatelimitQuery(); - if(limiter != null) { - limiter.reset(); - } - } - } - sender.sendMessage(Component.text("Ratelimits reset.")); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/EaglerCommand.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/EaglerCommand.java deleted file mode 100644 index ac2cfaa1..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/EaglerCommand.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command; - -import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.command.SimpleCommand; -import com.velocitypowered.proxy.command.VelocityCommandManager; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; - -public abstract class EaglerCommand implements SimpleCommand { - - public final String name; - public final String permission; - public final String[] alias; - - public EaglerCommand(String name, String perm, String...alias) { - this.name = name; - this.permission = perm; - this.alias = alias; - } - - @Override - public void execute(final Invocation invocation) { - this.execute(invocation.source(), invocation.arguments()); - } - - @Override - public boolean hasPermission(Invocation invocation) { - if(permission != null) { - return invocation.source().hasPermission(permission); - }else { - return true; - } - } - - protected abstract void execute(CommandSource invocation, String[] args); - - public static void register(EaglerXVelocity plugin, EaglerCommand cmd) { - VelocityCommandManager cmdManager = EaglerXVelocity.proxy().getCommandManager(); - cmdManager.register(cmdManager.metaBuilder(cmd.name).aliases(cmd.alias).plugin(plugin).build(), cmd); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerAuthConfig.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerAuthConfig.java deleted file mode 100644 index 0da0e316..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerAuthConfig.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.ChatColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; - -public class EaglerAuthConfig { - - static EaglerAuthConfig loadConfig(Configuration config) { - boolean enableAuthentication = config.getBoolean("enable_authentication_system"); - boolean useBuiltInAuthentication = config.getBoolean("use_onboard_eaglerx_system"); - String databaseURI = config.getString("auth_db_uri"); - String driverClass = config.getString("sql_driver_class", "internal"); - String driverPath = config.getString("sql_driver_path", null); - String passwordPromptScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("password_prompt_screen_text", "")); - String notRegisteredScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("not_registered_screen_text", "")); - String wrongPasswordScreenText = ChatColor.translateAlternateColorCodes('&', config.getString("wrong_password_screen_text", "")); - String eaglerCommandName = config.getString("eagler_command_name"); - String useRegisterCommandText = ChatColor.translateAlternateColorCodes('&', config.getString("use_register_command_text", "")); - String useChangeCommandText = ChatColor.translateAlternateColorCodes('&', config.getString("use_change_command_text", "")); - String commandSuccessText = ChatColor.translateAlternateColorCodes('&', config.getString("command_success_text", "")); - String lastEaglerLoginMessage = ChatColor.translateAlternateColorCodes('&', config.getString("last_eagler_login_message", "")); - String tooManyRegistrationsMessage = ChatColor.translateAlternateColorCodes('&', config.getString("too_many_registrations_message", "")); - String needVanillaToRegisterMessage = ChatColor.translateAlternateColorCodes('&', config.getString("need_vanilla_to_register_message", "")); - boolean overrideEaglerToVanillaSkins = config.getBoolean("override_eagler_to_vanilla_skins"); - int maxRegistrationsPerIP = config.getInt("max_registration_per_ip", -1); - return new EaglerAuthConfig(enableAuthentication, useBuiltInAuthentication, databaseURI, driverClass, - driverPath, passwordPromptScreenText, wrongPasswordScreenText, notRegisteredScreenText, - eaglerCommandName, useRegisterCommandText, useChangeCommandText, commandSuccessText, - lastEaglerLoginMessage, tooManyRegistrationsMessage, needVanillaToRegisterMessage, - overrideEaglerToVanillaSkins, maxRegistrationsPerIP); - } - - private boolean enableAuthentication; - private boolean useBuiltInAuthentication; - - private final String databaseURI; - private final String driverClass; - private final String driverPath; - private final String passwordPromptScreenText; - private final String wrongPasswordScreenText; - private final String notRegisteredScreenText; - private final String eaglerCommandName; - private final String useRegisterCommandText; - private final String useChangeCommandText; - private final String commandSuccessText; - private final String lastEaglerLoginMessage; - private final String tooManyRegistrationsMessage; - private final String needVanillaToRegisterMessage; - private final boolean overrideEaglerToVanillaSkins; - private final int maxRegistrationsPerIP; - - private EaglerAuthConfig(boolean enableAuthentication, boolean useBuiltInAuthentication, String databaseURI, - String driverClass, String driverPath, String passwordPromptScreenText, String wrongPasswordScreenText, - String notRegisteredScreenText, String eaglerCommandName, String useRegisterCommandText, - String useChangeCommandText, String commandSuccessText, String lastEaglerLoginMessage, - String tooManyRegistrationsMessage, String needVanillaToRegisterMessage, - boolean overrideEaglerToVanillaSkins, int maxRegistrationsPerIP) { - this.enableAuthentication = enableAuthentication; - this.useBuiltInAuthentication = useBuiltInAuthentication; - this.databaseURI = databaseURI; - this.driverClass = driverClass; - this.driverPath = driverPath; - this.passwordPromptScreenText = passwordPromptScreenText; - this.wrongPasswordScreenText = wrongPasswordScreenText; - this.notRegisteredScreenText = notRegisteredScreenText; - this.eaglerCommandName = eaglerCommandName; - this.useRegisterCommandText = useRegisterCommandText; - this.useChangeCommandText = useChangeCommandText; - this.commandSuccessText = commandSuccessText; - this.lastEaglerLoginMessage = lastEaglerLoginMessage; - this.tooManyRegistrationsMessage = tooManyRegistrationsMessage; - this.needVanillaToRegisterMessage = needVanillaToRegisterMessage; - this.overrideEaglerToVanillaSkins = overrideEaglerToVanillaSkins; - this.maxRegistrationsPerIP = maxRegistrationsPerIP; - } - - public boolean isEnableAuthentication() { - return enableAuthentication; - } - - public boolean isUseBuiltInAuthentication() { - return useBuiltInAuthentication; - } - - public void triggerOnlineModeDisabled() { - enableAuthentication = false; - useBuiltInAuthentication = false; - } - - public String getDatabaseURI() { - return databaseURI; - } - - public String getDriverClass() { - return driverClass; - } - - public String getDriverPath() { - return driverPath; - } - - public String getPasswordPromptScreenText() { - return passwordPromptScreenText; - } - - public String getWrongPasswordScreenText() { - return wrongPasswordScreenText; - } - - public String getNotRegisteredScreenText() { - return notRegisteredScreenText; - } - - public String getEaglerCommandName() { - return eaglerCommandName; - } - - public String getUseRegisterCommandText() { - return useRegisterCommandText; - } - - public String getUseChangeCommandText() { - return useChangeCommandText; - } - - public String getCommandSuccessText() { - return commandSuccessText; - } - - public String getLastEaglerLoginMessage() { - return lastEaglerLoginMessage; - } - - public String getTooManyRegistrationsMessage() { - return tooManyRegistrationsMessage; - } - - public String getNeedVanillaToRegisterMessage() { - return needVanillaToRegisterMessage; - } - - public boolean getOverrideEaglerToVanillaSkins() { - return overrideEaglerToVanillaSkins; - } - - public int getMaxRegistrationsPerIP() { - return maxRegistrationsPerIP; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerListenerConfig.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerListenerConfig.java deleted file mode 100644 index 9d6424fa..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerListenerConfig.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.io.File; -import java.net.InetSocketAddress; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import io.netty.handler.codec.http.HttpRequest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.ChatColor; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpContentType; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpWebServer; - -public class EaglerListenerConfig { - - static EaglerListenerConfig loadConfig(Configuration config, Map contentTypes) { - - String host = config.getString("address", "0.0.0.0:8081"); - InetSocketAddress hostv4 = null; - if(host != null && !host.equalsIgnoreCase("null") && !host.equalsIgnoreCase("none")) { - int i = host.lastIndexOf(':'); - if(i == -1) { - throw new IllegalArgumentException("Invalid address: " + host + "! Must be an ipv4:port combo"); - } - hostv4 = new InetSocketAddress(host.substring(0, i), Integer.parseInt(host.substring(i + 1))); - } - - String hostV6 = config.getString("address_v6", "null"); - InetSocketAddress hostv6 = null; - if(hostV6 != null && !hostV6.equalsIgnoreCase("null") && !hostV6.equalsIgnoreCase("none") && hostV6.length() > 0) { - int i = hostV6.lastIndexOf(':'); - if(i == -1) { - throw new IllegalArgumentException("Invalid address: " + host + "! Must be an ipv6:port combo"); - } - hostv6 = new InetSocketAddress(hostV6.substring(0, i), Integer.parseInt(hostV6.substring(i + 1))); - } - - if(hostv4 == null && hostv6 == null) { - throw new IllegalArgumentException("Invalid host specifies no addresses, both v4 and v6 address are null"); - } - - int maxPlayer = config.getInt("max_players", 60); - boolean forwardIp = config.getBoolean("forward_ip", false); - String forwardIpHeader = config.getString("forward_ip_header", "X-Real-IP"); - String redirectLegacyClientsTo = config.getString("redirect_legacy_clients_to", "null"); - if(redirectLegacyClientsTo != null && (redirectLegacyClientsTo.equalsIgnoreCase("null") || redirectLegacyClientsTo.length() == 0)) { - redirectLegacyClientsTo = null; - } - String serverIcon = config.getString("server_icon", "server-icon.png"); - List serverMOTD = (List) config.getList("server_motd", Arrays.asList("&6An EaglercraftX server")); - for(int i = 0, l = serverMOTD.size(); i < l; ++i) { - serverMOTD.set(i, ChatColor.translateAlternateColorCodes('&', serverMOTD.get(i))); - } - boolean allowMOTD = config.getBoolean("allow_motd", true); - boolean allowQuery = config.getBoolean("allow_query", true); - int minMCProtocol = config.getInt("min_minecraft_protocol", 47); - int maxMCProtocol = config.getInt("max_minecraft_protocol", 340); - boolean allowV3 = config.getBoolean("allow_protocol_v3", true); - boolean allowV4 = config.getBoolean("allow_protocol_v4", true); - if(!allowV3 && !allowV4) { - throw new IllegalArgumentException("Both v3 and v4 protocol are disabled!"); - } - int defragSendDelay = config.getInt("protocol_v4_defrag_send_delay", 10); - boolean haproxyProtocol = config.getBoolean("use_haproxy_protocol", false); - - int cacheTTL = 7200; - boolean cacheAnimation = false; - boolean cacheResults = true; - boolean cacheTrending = true; - boolean cachePortfolios = false; - - Configuration cacheConf = config.getSection("request_motd_cache"); - if(cacheConf != null) { - cacheTTL = cacheConf.getInt("cache_ttl", 7200); - cacheAnimation = cacheConf.getBoolean("online_server_list_animation", false); - cacheResults = cacheConf.getBoolean("online_server_list_results", true); - cacheTrending = cacheConf.getBoolean("online_server_list_trending", true); - cachePortfolios = cacheConf.getBoolean("online_server_list_portfolios", false); - } - - HttpWebServer httpServer = null; - Configuration httpServerConf = config.getSection("http_server"); - - if(httpServerConf != null && httpServerConf.getBoolean("enabled", false)) { - String rootDirectory = httpServerConf.getString("root", "web"); - String page404 = httpServerConf.getString("page_404_not_found", "default"); - if(page404 != null && (page404.length() == 0 || page404.equalsIgnoreCase("null") || page404.equalsIgnoreCase("default"))) { - page404 = null; - } - List defaultIndex = Arrays.asList("index.html", "index.htm"); - List indexPageRaw = httpServerConf.getList("page_index_name", defaultIndex); - List indexPage = new ArrayList<>(indexPageRaw.size()); - - for(int i = 0, l = indexPageRaw.size(); i < l; ++i) { - Object o = indexPageRaw.get(i); - if(o instanceof String) { - indexPage.add((String)o); - } - } - - if(indexPage.size() == 0) { - indexPage.addAll(defaultIndex); - } - - httpServer = new HttpWebServer(new File(EaglerXVelocity.getEagler().getDataFolder(), rootDirectory), - contentTypes, indexPage, page404); - } - - boolean enableVoiceChat = config.getBoolean("allow_voice", false); - - EaglerRateLimiter ratelimitIp = null; - EaglerRateLimiter ratelimitLogin = null; - EaglerRateLimiter ratelimitMOTD = null; - EaglerRateLimiter ratelimitQuery = null; - - Configuration rateLimitConfig = config.getSection("ratelimit"); - if(rateLimitConfig != null) { - Configuration ratelimitIpConfig = rateLimitConfig.getSection("ip"); - if(ratelimitIpConfig != null && ratelimitIpConfig.getBoolean("enable", false)) { - ratelimitIp = EaglerRateLimiter.loadConfig(ratelimitIpConfig); - } - Configuration ratelimitLoginConfig = rateLimitConfig.getSection("login"); - if(ratelimitLoginConfig != null && ratelimitLoginConfig.getBoolean("enable", false)) { - ratelimitLogin = EaglerRateLimiter.loadConfig(ratelimitLoginConfig); - } - Configuration ratelimitMOTDConfig = rateLimitConfig.getSection("motd"); - if(ratelimitMOTDConfig != null && ratelimitMOTDConfig.getBoolean("enable", false)) { - ratelimitMOTD = EaglerRateLimiter.loadConfig(ratelimitMOTDConfig); - } - Configuration ratelimitQueryConfig = rateLimitConfig.getSection("query"); - if(ratelimitQueryConfig != null && ratelimitQueryConfig.getBoolean("enable", false)) { - ratelimitQuery = EaglerRateLimiter.loadConfig(ratelimitQueryConfig); - } - } - - MOTDCacheConfiguration cacheConfig = new MOTDCacheConfiguration(cacheTTL, cacheAnimation, cacheResults, - cacheTrending, cachePortfolios); - return new EaglerListenerConfig(hostv4, hostv6, maxPlayer, - forwardIp, forwardIpHeader, redirectLegacyClientsTo, serverIcon, serverMOTD, allowMOTD, allowQuery, - minMCProtocol, maxMCProtocol, allowV3, allowV4, defragSendDelay, haproxyProtocol, cacheConfig, - httpServer, enableVoiceChat, ratelimitIp, ratelimitLogin, ratelimitMOTD, ratelimitQuery); - } - - private final InetSocketAddress address; - private final InetSocketAddress addressV6; - private final int maxPlayer; - private final boolean forwardIp; - private final String forwardIpHeader; - private final String redirectLegacyClientsTo; - private final String serverIcon; - private final List serverMOTD; - private final boolean allowMOTD; - private final boolean allowQuery; - private final int minMCProtocol; - private final int maxMCProtocol; - private final boolean allowV3; - private final boolean allowV4; - private final int defragSendDelay; - private final boolean haproxyProtocol; - private final MOTDCacheConfiguration motdCacheConfig; - private final HttpWebServer webServer; - private boolean serverIconSet = false; - private int[] serverIconPixels = null; - private final boolean enableVoiceChat; - private final EaglerRateLimiter ratelimitIp; - private final EaglerRateLimiter ratelimitLogin; - private final EaglerRateLimiter ratelimitMOTD; - private final EaglerRateLimiter ratelimitQuery; - - public EaglerListenerConfig(InetSocketAddress address, InetSocketAddress addressV6, int maxPlayer, - boolean forwardIp, String forwardIpHeader, String redirectLegacyClientsTo, String serverIcon, - List serverMOTD, boolean allowMOTD, boolean allowQuery, int minMCProtocol, int maxMCProtocol, - boolean allowV3, boolean allowV4, int defragSendDelay, boolean haproxyProtocol, - MOTDCacheConfiguration motdCacheConfig, HttpWebServer webServer, boolean enableVoiceChat, - EaglerRateLimiter ratelimitIp, EaglerRateLimiter ratelimitLogin, EaglerRateLimiter ratelimitMOTD, - EaglerRateLimiter ratelimitQuery) { - this.address = address; - this.addressV6 = addressV6; - this.maxPlayer = maxPlayer; - this.forwardIp = forwardIp; - this.forwardIpHeader = forwardIpHeader; - this.redirectLegacyClientsTo = redirectLegacyClientsTo; - this.serverIcon = serverIcon; - this.serverMOTD = serverMOTD; - this.allowMOTD = allowMOTD; - this.allowQuery = allowQuery; - this.minMCProtocol = minMCProtocol; - this.maxMCProtocol = maxMCProtocol; - this.allowV3 = allowV3; - this.allowV4 = allowV4; - this.defragSendDelay = defragSendDelay; - this.haproxyProtocol = haproxyProtocol; - this.motdCacheConfig = motdCacheConfig; - this.webServer = webServer; - this.enableVoiceChat = enableVoiceChat; - this.ratelimitIp = ratelimitIp; - this.ratelimitLogin = ratelimitLogin; - this.ratelimitMOTD = ratelimitMOTD; - this.ratelimitQuery = ratelimitQuery; - } - - public InetSocketAddress getAddress() { - return address; - } - - public InetSocketAddress getAddressV6() { - return addressV6; - } - - public int getMaxPlayer() { - return maxPlayer; - } - - public boolean isForwardIp() { - return forwardIp; - } - - public String getForwardIpHeader() { - return forwardIpHeader; - } - - public String getServerIconName() { - return serverIcon; - } - - public int[] getServerIconPixels() { - if(!serverIconSet) { - if(serverIcon != null) { - File f = new File(serverIcon); - if(f.isFile()) { - serverIconPixels = ServerIconLoader.createServerIcon(f); - if(serverIconPixels == null) { - EaglerXVelocity.logger().warn("Server icon could not be loaded: {}", f.getAbsolutePath()); - } - }else { - EaglerXVelocity.logger().warn("Server icon is not a file: {}", f.getAbsolutePath()); - } - } - serverIconSet = true; - } - return serverIconPixels; - } - - public List getServerMOTD() { - return serverMOTD; - } - - public boolean isAllowMOTD() { - return allowMOTD; - } - - public boolean isAllowQuery() { - return allowQuery; - } - - public int getMinMCProtocol() { - return minMCProtocol; - } - - public int getMaxMCProtocol() { - return maxMCProtocol; - } - - public boolean isAllowV3() { - return allowV3; - } - - public boolean isAllowV4() { - return allowV4; - } - - public int getDefragSendDelay() { - return defragSendDelay; - } - - public boolean isHAProxyProtocol() { - return haproxyProtocol; - } - - public HttpWebServer getWebServer() { - return webServer; - } - - public MOTDCacheConfiguration getMOTDCacheConfig() { - return motdCacheConfig; - } - - public boolean blockRequest(HttpRequest request) { - return false; - } - - public String redirectLegacyClientsTo() { - return redirectLegacyClientsTo; - } - - public boolean getEnableVoiceChat() { - return enableVoiceChat; - } - - public EaglerRateLimiter getRatelimitIp() { - return ratelimitIp; - } - - public EaglerRateLimiter getRatelimitLogin() { - return ratelimitLogin; - } - - public EaglerRateLimiter getRatelimitMOTD() { - return ratelimitMOTD; - } - - public EaglerRateLimiter getRatelimitQuery() { - return ratelimitQuery; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerPauseMenuConfig.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerPauseMenuConfig.java deleted file mode 100644 index f3333504..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerPauseMenuConfig.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.WeakHashMap; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketServerInfoDataChunkV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleOutputBufferImpl; - -public class EaglerPauseMenuConfig { - - private boolean enableCustomPauseMenu; - private SPacketCustomizePauseMenuV4EAG customPauseMenuPacket; - private byte[] serverInfoHash; - private List serverInfoChunks; - private int infoSendRate; - - static EaglerPauseMenuConfig loadConfig(Configuration conf, File baseDir) throws IOException { - boolean enabled = conf.getBoolean("enable_custom_pause_menu", false); - if(!enabled) { - return new EaglerPauseMenuConfig(false, null, null, 1); - } - - Configuration server_info_button = conf.getSection("server_info_button"); - boolean enableInfoButton = server_info_button.getBoolean("enable_button", false); - String infoButtonText = server_info_button.getString("button_text", "Server Info"); - boolean infoButtonModeNewTab = server_info_button.getBoolean("button_mode_open_new_tab", false); - String infoButtonEmbedURL = server_info_button.getString("server_info_embed_url", ""); - boolean infoButtonModeEmbedFile = server_info_button.getBoolean("button_mode_embed_file", true); - String infoButtonEmbedFile = server_info_button.getString("server_info_embed_file", "server_info.html"); - String infoButtonEmbedScreenTitle = server_info_button.getString("server_info_embed_screen_title", "Server Info"); - int infoSendRate = server_info_button.getInt("server_info_embed_send_chunk_rate", 1); - int infoChunkSize = server_info_button.getInt("server_info_embed_send_chunk_size", 24576); - if(infoChunkSize > 32720) { - throw new IOException("Chunk size " +infoChunkSize + " is too large! Max is 32720 bytes"); - } - boolean infoButtonEnableTemplateMacros = server_info_button.getBoolean("enable_template_macros", true); - Configuration globals = server_info_button.getSection("server_info_embed_template_globals"); - for(String s : globals.getKeys()) { - EaglerXVelocityAPIHelper.getTemplateGlobals().put(s, globals.getString(s)); - } - boolean infoButtonAllowTemplateEvalMacro = server_info_button.getBoolean("allow_embed_template_eval_macro", false); - boolean infoButtonEnableWebviewJavascript = server_info_button.getBoolean("enable_webview_javascript", false); - boolean infoButtonEnableWebviewMessageAPI = server_info_button.getBoolean("enable_webview_message_api", false); - boolean infoButtonEnableWebviewStrictCSP = server_info_button.getBoolean("enable_webview_strict_csp", true); - - Configuration discord_button = conf.getSection("discord_button"); - boolean enableDiscordButton = discord_button.getBoolean("enable_button", false); - String discordButtonText = discord_button.getString("button_text", "Discord"); - String discordButtonURL = discord_button.getString("button_url", "https://invite url here"); - - int infoButtonMode = enableInfoButton - ? (infoButtonModeEmbedFile - ? (infoButtonEmbedFile.length() > 0 - ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE) - : (infoButtonEmbedURL.length() > 0 - ? (infoButtonModeNewTab ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_EXTERNAL_URL - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP) - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE)) - : SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE; - - int discordButtonMode = (enableDiscordButton && discordButtonURL.length() > 0) - ? SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_INVITE_URL - : SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_NONE; - - int webviewPerms = (infoButtonEnableWebviewJavascript ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_JAVASCRIPT : 0) | - (infoButtonEnableWebviewMessageAPI ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_MESSAGE_API : 0) | - (infoButtonEnableWebviewStrictCSP ? SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_STRICT_CSP : 0); - - Map imagesToActuallyLoad = new WeakHashMap<>(); - - Configuration custom_images = conf.getSection("custom_images"); - for(String s : custom_images.getKeys()) { - String fileName = custom_images.getString(s, ""); - if(fileName.length() > 0) { - imagesToActuallyLoad.put(s, fileName); - } - } - - Map imageMappings = null; - List customImageDatas = null; - - if(imagesToActuallyLoad.size() > 0) { - Map imageLoadingCache = new HashMap<>(); - Int2ObjectMap imageDumbHashTable = new Int2ObjectOpenHashMap<>(); - - imageMappings = new HashMap<>(); - customImageDatas = new ArrayList<>(); - - outer_loop: for(Entry etr : imagesToActuallyLoad.entrySet()) { - String key = etr.getKey(); - String value = etr.getValue(); - PacketImageData existing = imageLoadingCache.get(value); - if(existing != null) { - for(int i = 0, l = customImageDatas.size(); i < l; ++i) { - if(customImageDatas.get(i) == existing) { - imageMappings.put(key, i); - continue outer_loop; - } - } - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(existing); - continue outer_loop; - }else { - PacketImageData img = EaglerXVelocityAPIHelper.loadPacketImageData(new File(baseDir, value), 64, 64); - int hashCode = Arrays.hashCode(img.rgba); - PacketImageData possibleClone = imageDumbHashTable.get(hashCode); - if (possibleClone != null && possibleClone.width == img.width && possibleClone.height == img.height - && Arrays.equals(img.rgba, possibleClone.rgba)) { - for(int i = 0, l = customImageDatas.size(); i < l; ++i) { - if(customImageDatas.get(i) == possibleClone) { - imageMappings.put(key, i); - continue outer_loop; - } - } - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(possibleClone); - continue outer_loop; - }else { - imageMappings.put(key, customImageDatas.size()); - customImageDatas.add(img); - imageDumbHashTable.put(hashCode, img); - continue outer_loop; - } - } - } - } - - SPacketCustomizePauseMenuV4EAG pausePacket = new SPacketCustomizePauseMenuV4EAG(); - List serverInfoChunks = null; - - pausePacket.serverInfoMode = infoButtonMode; - switch(infoButtonMode) { - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_NONE: - default: - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_EXTERNAL_URL: - pausePacket.serverInfoButtonText = infoButtonText; - pausePacket.serverInfoURL = infoButtonEmbedURL; - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP: - pausePacket.serverInfoButtonText = infoButtonText; - pausePacket.serverInfoURL = infoButtonEmbedURL; - pausePacket.serverInfoEmbedPerms = webviewPerms; - pausePacket.serverInfoEmbedTitle = infoButtonEmbedScreenTitle; - break; - case SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS: - pausePacket.serverInfoButtonText = infoButtonText; - byte[] hash = new byte[20]; - String rawData = EaglerXVelocityAPIHelper.loadFileToStringServerInfo(new File(baseDir, infoButtonEmbedFile)); - if(infoButtonEnableTemplateMacros) { - rawData = EaglerXVelocityAPIHelper.loadServerInfoTemplateEagler(rawData, baseDir, infoButtonAllowTemplateEvalMacro); - } - serverInfoChunks = EaglerXVelocityAPIHelper.convertServerInfoToChunks(rawData.getBytes(StandardCharsets.UTF_8), hash, infoChunkSize); - if(!serverInfoChunks.isEmpty()) { - SPacketServerInfoDataChunkV4EAG pk = serverInfoChunks.get(0); - EaglerXVelocity.logger().info("Total server info embed size: {} bytes {}", pk.finalSize, serverInfoChunks.size() > 1 ? (" (" + serverInfoChunks.size() + " chunks)") : ""); - } - pausePacket.serverInfoEmbedPerms = webviewPerms; - pausePacket.serverInfoEmbedTitle = infoButtonEmbedScreenTitle; - pausePacket.serverInfoHash = hash; - break; - } - - pausePacket.discordButtonMode = discordButtonMode; - switch(discordButtonMode) { - case SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_NONE: - default: - break; - case SPacketCustomizePauseMenuV4EAG.DISCORD_MODE_INVITE_URL: - pausePacket.discordButtonMode = discordButtonMode; - pausePacket.discordButtonText = discordButtonText; - pausePacket.discordInviteURL = discordButtonURL; - break; - } - - pausePacket.imageMappings = imageMappings; - pausePacket.imageData = customImageDatas; - - SimpleOutputBufferImpl ob = new SimpleOutputBufferImpl(new TestOutputStream()); - pausePacket.writePacket(ob); - int cnt = ob.size(); - - EaglerXVelocity.logger().info("Total pause menu packet size: {} bytes", cnt); - if(cnt > 32760) { - throw new IOException("Pause menu packet is " + (cnt - 32760) + " bytes too large! Try making the images smaller or reusing the same image file for multiple icons!"); - } - - return new EaglerPauseMenuConfig(enabled, pausePacket, serverInfoChunks, infoSendRate); - } - - private EaglerPauseMenuConfig(boolean enableCustomPauseMenu, SPacketCustomizePauseMenuV4EAG customPauseMenuPacket, - List serverInfoChunks, int infoSendRate) { - this.enableCustomPauseMenu = enableCustomPauseMenu; - this.customPauseMenuPacket = customPauseMenuPacket; - this.serverInfoHash = customPauseMenuPacket != null ? customPauseMenuPacket.serverInfoHash : null; - this.serverInfoChunks = serverInfoChunks; - this.infoSendRate = infoSendRate; - } - - public boolean getEnabled() { - return enableCustomPauseMenu; - } - - public SPacketCustomizePauseMenuV4EAG getPacket() { - return customPauseMenuPacket; - } - - public byte[] getServerInfoHash() { - return serverInfoHash; - } - - public List getServerInfo() { - return serverInfoChunks; - } - - public int getInfoSendRate() { - return infoSendRate; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerRateLimiter.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerRateLimiter.java deleted file mode 100644 index 11cf45e3..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerRateLimiter.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; - -public class EaglerRateLimiter { - - private final int period; - private final int limit; - private final int limitLockout; - private int effectiveLimit; - private int effectiveLimitLockout; - private final int lockoutDuration; - private final List exceptions; - - private EaglerRateLimiter(int period, int limit, int limitLockout, int lockoutDuration, List exceptions) { - this.period = period * 1000 / limit; - this.limit = this.effectiveLimit = limit; - this.limitLockout = this.effectiveLimitLockout = limitLockout; - this.lockoutDuration = lockoutDuration * 1000; - this.exceptions = exceptions; - } - - public void setDivisor(int d) { - this.effectiveLimit = this.limit * d; - this.effectiveLimitLockout = this.limitLockout * d; - } - - public int getPeriod() { - return period; - } - - public int getLimit() { - return effectiveLimit; - } - - public int getLimitLockout() { - return effectiveLimitLockout; - } - - public int getLockoutDuration() { - return lockoutDuration; - } - - public List getExceptions() { - return exceptions; - } - - public boolean isException(String addr) { - for(int i = 0, l = exceptions.size(); i < l; ++i) { - String str = exceptions.get(i); - int ll = str.length() - 1; - if(str.indexOf('*') == 0) { - if(addr.endsWith(str.substring(1))) { - return true; - } - }else if(str.lastIndexOf('*') == ll) { - if(addr.startsWith(str.substring(ll))) { - return true; - } - }else { - if(addr.equals(str)) { - return true; - } - } - } - return false; - } - - protected class RateLimiter { - - protected int requestCounter = 0; - protected long lockoutTimestamp = 0l; - protected long cooldownTimestamp = 0l; - - protected RateLimitStatus rateLimit() { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - tick(millis); - if(lockoutTimestamp != 0l) { - return RateLimitStatus.LOCKED_OUT; - }else { - if(++requestCounter > EaglerRateLimiter.this.effectiveLimitLockout) { - lockoutTimestamp = millis; - requestCounter = 0; - return RateLimitStatus.LIMITED_NOW_LOCKED_OUT; - }else if(requestCounter > EaglerRateLimiter.this.effectiveLimit) { - return RateLimitStatus.LIMITED; - }else { - return RateLimitStatus.OK; - } - } - } - - protected void tick(long millis) { - if(lockoutTimestamp != 0l) { - if(millis - lockoutTimestamp > EaglerRateLimiter.this.lockoutDuration) { - requestCounter = 0; - lockoutTimestamp = 0l; - cooldownTimestamp = millis; - } - }else { - long delta = millis - cooldownTimestamp; - long decr = delta / EaglerRateLimiter.this.period; - if(decr >= requestCounter) { - requestCounter = 0; - cooldownTimestamp = millis; - }else { - requestCounter -= decr; - cooldownTimestamp += decr * EaglerRateLimiter.this.period; - if(requestCounter < 0) { - requestCounter = 0; - } - } - } - } - } - - private final Map ratelimiters = new HashMap<>(); - - public RateLimitStatus rateLimit(String addr) { - addr = addr.toLowerCase(); - if(isException(addr)) { - return RateLimitStatus.OK; - }else { - RateLimiter limiter; - synchronized(ratelimiters) { - limiter = ratelimiters.get(addr); - if(limiter == null) { - limiter = new RateLimiter(); - ratelimiters.put(addr, limiter); - } - } - return limiter.rateLimit(); - } - } - - public void tick() { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - synchronized(ratelimiters) { - Iterator itr = ratelimiters.values().iterator(); - while(itr.hasNext()) { - RateLimiter i = itr.next(); - i.tick(millis); - if(i.requestCounter <= 0 && i.lockoutTimestamp <= 0l) { - itr.remove(); - } - } - } - } - - public void reset() { - synchronized(ratelimiters) { - ratelimiters.clear(); - } - } - - static EaglerRateLimiter loadConfig(Configuration config) { - int period = config.getInt("period", -1); - int limit = config.getInt("limit", -1); - int limitLockout = config.getInt("limit_lockout", -1); - int lockoutDuration = config.getInt("lockout_duration", -1); - Collection exc = (Collection) config.getList("exceptions"); - List exceptions = new ArrayList<>(); - for(String str : exc) { - exceptions.add(str.toLowerCase()); - } - if(period != -1 && limit != -1 && limitLockout != -1 && lockoutDuration != -1) { - return new EaglerRateLimiter(period, limit, limitLockout, lockoutDuration, exceptions); - }else { - return null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerUpdateConfig.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerUpdateConfig.java deleted file mode 100644 index d13312b7..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerUpdateConfig.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.util.Collection; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; - -public class EaglerUpdateConfig { - - static EaglerUpdateConfig loadConfig(Configuration config) { - boolean blockAllClientUpdates = config.getBoolean("block_all_client_updates", false); - boolean discardLoginPacketCerts = config.getBoolean("discard_login_packet_certs", false); - int certPacketDataRateLimit = config.getInt("cert_packet_data_rate_limit", 524288); - boolean enableEagcertFolder = config.getBoolean("enable_eagcert_folder", true); - boolean downloadLatestCerts = config.getBoolean("download_latest_certs", true); - int checkForUpdatesEvery = config.getInt("check_for_update_every", 28800); - Collection downloadCertURLs = (Collection)config.getList("download_certs_from"); - return new EaglerUpdateConfig(blockAllClientUpdates, discardLoginPacketCerts, certPacketDataRateLimit, - enableEagcertFolder, downloadLatestCerts, checkForUpdatesEvery, downloadCertURLs); - } - - private final boolean blockAllClientUpdates; - private final boolean discardLoginPacketCerts; - private final int certPacketDataRateLimit; - private final boolean enableEagcertFolder; - private final boolean downloadLatestCerts; - private final int checkForUpdatesEvery; - private final Collection downloadCertURLs; - - public EaglerUpdateConfig(boolean blockAllClientUpdates, boolean discardLoginPacketCerts, - int certPacketDataRateLimit, boolean enableEagcertFolder, boolean downloadLatestCerts, - int checkForUpdatesEvery, Collection downloadCertURLs) { - this.blockAllClientUpdates = blockAllClientUpdates; - this.discardLoginPacketCerts = discardLoginPacketCerts; - this.certPacketDataRateLimit = certPacketDataRateLimit; - this.enableEagcertFolder = enableEagcertFolder; - this.downloadLatestCerts = downloadLatestCerts; - this.checkForUpdatesEvery = checkForUpdatesEvery; - this.downloadCertURLs = downloadCertURLs; - } - - public boolean isBlockAllClientUpdates() { - return blockAllClientUpdates; - } - - public boolean isDiscardLoginPacketCerts() { - return discardLoginPacketCerts; - } - - public int getCertPacketDataRateLimit() { - return certPacketDataRateLimit; - } - - public boolean isEnableEagcertFolder() { - return enableEagcertFolder; - } - - public boolean isDownloadLatestCerts() { - return downloadLatestCerts && enableEagcertFolder; - } - - public int getCheckForUpdatesEvery() { - return checkForUpdatesEvery; - } - - public Collection getDownloadCertURLs() { - return downloadCertURLs; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerVelocityConfig.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerVelocityConfig.java deleted file mode 100644 index a60cdd25..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerVelocityConfig.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import com.velocitypowered.api.util.GameProfile.Property; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.Configuration; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.ConfigurationProvider; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee.YamlConfiguration; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpContentType; - -public class EaglerVelocityConfig { - - public static EaglerVelocityConfig loadConfig(File directory) throws IOException { - Map contentTypes = new HashMap<>(); - - try(InputStream is = new FileInputStream(getConfigFile(directory, "http_mime_types.json"))) { - loadMimeTypes(is, contentTypes); - }catch(Throwable t) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_http_mime_types.json")) { - loadMimeTypes(is, contentTypes); - }catch(IOException ex) { - EaglerXVelocity.logger().error("Could not load default_http_mime_types.json!"); - throw new RuntimeException(ex); - } - } - - directory.mkdirs(); - ConfigurationProvider prov = ConfigurationProvider.getProvider(YamlConfiguration.class); - - Configuration configYml = prov.load(getConfigFile(directory, "settings.yml")); - String serverName = configYml.getString("server_name", "EaglercraftXVelocity Server"); - EaglerXVelocityAPIHelper.getTemplateGlobals().put("server_name", serverName); - String serverUUIDString = configYml.getString("server_uuid", null); - if(serverUUIDString == null) { - throw new IOException("You must specify a server_uuid!"); - } - - UUID serverUUID = null; - try { - serverUUID = UUID.fromString(serverUUIDString); - }catch(Throwable t) { - } - - if(serverUUID == null) { - throw new IOException("The server_uuid \"" + serverUUIDString + "\" is invalid!"); - } - - Configuration listenerYml = prov.load(getConfigFile(directory, "listeners.yml")); - Iterator listeners = listenerYml.getKeys().iterator(); - Map serverListeners = new HashMap<>(); - boolean voiceChat = false; - - while(listeners.hasNext()) { - String name = listeners.next(); - EaglerListenerConfig conf = EaglerListenerConfig.loadConfig(listenerYml.getSection(name), contentTypes); - if(conf != null) { - serverListeners.put(name, conf); - voiceChat |= conf.getEnableVoiceChat(); - }else { - EaglerXVelocity.logger().error("Invalid listener config: {}", name); - } - } - - if(serverListeners.size() == 0) { - EaglerXVelocity.logger().error("No Listeners Configured!"); - } - - Configuration authserivceYml = prov.load(getConfigFile(directory, "authservice.yml")); - EaglerAuthConfig authConfig = EaglerAuthConfig.loadConfig(authserivceYml); - - Configuration updatesYml = prov.load(getConfigFile(directory, "updates.yml")); - EaglerUpdateConfig updatesConfig = EaglerUpdateConfig.loadConfig(updatesYml); - - Configuration iceServersYml = prov.load(getConfigFile(directory, "ice_servers.yml")); - Collection iceServers = loadICEServers(iceServersYml); - - if(authConfig.isEnableAuthentication()) { - for(EaglerListenerConfig lst : serverListeners.values()) { - if(lst.getRatelimitLogin() != null) lst.getRatelimitLogin().setDivisor(2); - if(lst.getRatelimitIp() != null) lst.getRatelimitIp().setDivisor(2); - } - } - - File pauseMenuFolder = new File(directory, "pause_menu"); - if(!pauseMenuFolder.isDirectory() && !pauseMenuFolder.mkdir()) { - throw new IOException("Could not create directory: " + pauseMenuFolder.getAbsolutePath()); - } - - File pauseMenuYml = new File(pauseMenuFolder, "pause_menu.yml"); - if(!pauseMenuYml.isFile()) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_pause_menu.yml")) { - copyConfigFile(is, pauseMenuYml); - } - File f2 = new File(pauseMenuFolder, "server_info.html"); - if(!f2.isFile()) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_pause_menu_server_info.html")) { - copyConfigFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "test_image.png"); - if(!f2.isFile()) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_pause_menu_test_image.png")) { - copyBinaryFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "message_api_example.html"); - if(!f2.isFile()) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_message_api_example.html")) { - copyConfigFile(is, f2); - } - } - f2 = new File(pauseMenuFolder, "message_api_v1.js"); - if(!f2.isFile()) { - try(InputStream is = EaglerVelocityConfig.class.getResourceAsStream("default_message_api_v1.js")) { - copyConfigFile(is, f2); - } - } - } - EaglerPauseMenuConfig pauseMenuConfig = EaglerPauseMenuConfig.loadConfig(prov.load(pauseMenuYml), pauseMenuFolder); - - long websocketKeepAliveTimeout = configYml.getInt("websocket_connection_timeout", 15000); - long websocketHandshakeTimeout = configYml.getInt("websocket_handshake_timeout", 5000); - long builtinHttpServerTimeout = configYml.getInt("builtin_http_server_timeout", 10000); - int websocketCompressionLevel = configYml.getInt("http_websocket_compression_level", 6); - - boolean downloadVanillaSkins = configYml.getBoolean("download_vanilla_skins_to_clients", false); - Collection validSkinUrls = (Collection)configYml.getList("valid_skin_download_urls"); - int uuidRateLimitPlayer = configYml.getInt("uuid_lookup_ratelimit_player", 50); - int uuidRateLimitGlobal = configYml.getInt("uuid_lookup_ratelimit_global", 175); - int skinRateLimitPlayer = configYml.getInt("skin_download_ratelimit_player", 1000); - int skinRateLimitGlobal = configYml.getInt("skin_download_ratelimit_global", 30000); - - String skinCacheURI = configYml.getString("skin_cache_db_uri", "jdbc:sqlite:eaglercraft_skins_cache.db"); - int keepObjectsDays = configYml.getInt("skin_cache_keep_objects_days", 45); - int keepProfilesDays = configYml.getInt("skin_cache_keep_profiles_days", 7); - int maxObjects = configYml.getInt("skin_cache_max_objects", 32768); - int maxProfiles = configYml.getInt("skin_cache_max_profiles", 32768); - int antagonistsRateLimit = configYml.getInt("skin_cache_antagonists_ratelimit", 15); - String sqliteDriverClass = configYml.getString("sql_driver_class", "internal"); - String sqliteDriverPath = configYml.getString("sql_driver_path", null); - String eaglerPlayersVanillaSkin = configYml.getString("eagler_players_vanilla_skin", null); - if(eaglerPlayersVanillaSkin != null && eaglerPlayersVanillaSkin.length() == 0) { - eaglerPlayersVanillaSkin = null; - } - boolean enableIsEaglerPlayerProperty = configYml.getBoolean("enable_is_eagler_player_property", true); - Set disableVoiceOnServers = new HashSet<>((Collection)configYml.getList("disable_voice_chat_on_servers")); - boolean disableFNAWSkinsEverywhere = configYml.getBoolean("disable_fnaw_skins_everywhere", false); - Set disableFNAWSkinsOnServers = new HashSet<>((Collection)configYml.getList("disable_fnaw_skins_on_servers")); - boolean enableBackendRPCAPI = configYml.getBoolean("enable_backend_rpc_api", false); - boolean useModernizedChannelNames = configYml.getBoolean("use_modernized_channel_names", false); - - final EaglerVelocityConfig ret = new EaglerVelocityConfig(serverName, serverUUID, websocketKeepAliveTimeout, - websocketHandshakeTimeout, builtinHttpServerTimeout, websocketCompressionLevel, serverListeners, - contentTypes, downloadVanillaSkins, validSkinUrls, uuidRateLimitPlayer, uuidRateLimitGlobal, - skinRateLimitPlayer, skinRateLimitGlobal, skinCacheURI, keepObjectsDays, keepProfilesDays, maxObjects, - maxProfiles, antagonistsRateLimit, sqliteDriverClass, sqliteDriverPath, eaglerPlayersVanillaSkin, - enableIsEaglerPlayerProperty, authConfig, updatesConfig, iceServers, voiceChat, disableVoiceOnServers, - disableFNAWSkinsEverywhere, disableFNAWSkinsOnServers, enableBackendRPCAPI, useModernizedChannelNames, - pauseMenuConfig); - - if(eaglerPlayersVanillaSkin != null) { - VanillaDefaultSkinProfileLoader.lookupVanillaSkinUser(ret); - } - - return ret; - } - - private static File getConfigFile(File directory, String fileName) throws IOException { - File file = new File(directory, fileName); - if(!file.isFile()) { - try (BufferedReader is = new BufferedReader(new InputStreamReader( - EaglerVelocityConfig.class.getResourceAsStream("default_" + fileName), StandardCharsets.UTF_8)); - PrintWriter os = new PrintWriter(new FileWriter(file))) { - String line; - while((line = is.readLine()) != null) { - if(line.contains("${")) { - line = line.replace("${random_uuid}", UUID.randomUUID().toString()); - } - os.println(line); - } - } - } - return file; - } - - private static void copyConfigFile(InputStream is, File file) throws IOException { - try(PrintWriter os = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - String line; - while((line = reader.readLine()) != null) { - os.println(line); - } - } - } - - private static void copyBinaryFile(InputStream is, File file) throws IOException { - try(OutputStream os = new FileOutputStream(file)) { - byte[] copyBuffer = new byte[1024]; - int i; - while((i = is.read(copyBuffer)) != -1) { - os.write(copyBuffer, 0, i); - } - } - } - - private static void loadMimeTypes(InputStream file, Map contentTypes) throws IOException { - JsonObject obj = parseJsonObject(file); - for(Entry etr : obj.entrySet()) { - String mime = etr.getKey(); - try { - JsonObject e = etr.getValue().getAsJsonObject(); - JsonArray arr = e.getAsJsonArray("files"); - if(arr == null || arr.size() == 0) { - EaglerXVelocity.logger().warn("MIME type '{}' defines no extensions!", mime); - continue; - } - HashSet exts = new HashSet<>(); - for(int i = 0, l = arr.size(); i < l; ++i) { - exts.add(arr.get(i).getAsString()); - } - long expires = 0l; - JsonElement ex = e.get("expires"); - if(ex != null) { - expires = ex.getAsInt() * 1000l; - } - String charset = null; - ex = e.get("charset"); - if(ex != null) { - charset = ex.getAsString(); - } - HttpContentType typeObj = new HttpContentType(exts, mime, charset, expires); - for(String s : exts) { - contentTypes.put(s, typeObj); - } - }catch(Throwable t) { - EaglerXVelocity.logger().warn("Exception parsing MIME type '{}' - {}", mime, t); - } - } - } - - private static Collection loadICEServers(Configuration config) { - Collection ret = new ArrayList<>((Collection)config.getList("voice_stun_servers")); - Configuration turnServers = config.getSection("voice_turn_servers"); - Iterator turnItr = turnServers.getKeys().iterator(); - while(turnItr.hasNext()) { - String name = turnItr.next(); - Configuration turnSvr = turnServers.getSection(name); - ret.add(turnSvr.getString("url") + ";" + turnSvr.getString("username") + ";" + turnSvr.getString("password")); - } - return ret; - } - - private static JsonObject parseJsonObject(InputStream file) throws IOException { - try { - return JsonParser.parseReader(new InputStreamReader(file, StandardCharsets.UTF_8)).getAsJsonObject(); - }catch(JsonSyntaxException ex) { - throw new IOException("Invalid JSONObject", ex); - } - } - - public static final Property isEaglerProperty = new Property("isEaglerPlayer", "true", ""); //TODO: how to have null signature? - - private final String serverName; - private final UUID serverUUID; - private final long websocketKeepAliveTimeout; - private final long websocketHandshakeTimeout; - private final long builtinHttpServerTimeout; - private final int httpWebsocketCompressionLevel; - private final Map serverListeners; - private final Map contentTypes; - private final boolean downloadVanillaSkins; - private final Collection validSkinUrls; - private final int uuidRateLimitPlayer; - private final int uuidRateLimitGlobal; - private final int skinRateLimitPlayer; - private final int skinRateLimitGlobal; - private final String skinCacheURI; - private final int keepObjectsDays; - private final int keepProfilesDays; - private final int maxObjects; - private final int maxProfiles; - private final int antagonistsRateLimit; - private final String sqliteDriverClass; - private final String sqliteDriverPath; - private final String eaglerPlayersVanillaSkin; - private final boolean enableIsEaglerPlayerProperty; - private final EaglerAuthConfig authConfig; - private final EaglerUpdateConfig updateConfig; - private final Collection iceServers; - private final boolean enableVoiceChat; - private final Set disableVoiceOnServers; - private final boolean disableFNAWSkinsEverywhere; - private final Set disableFNAWSkinsOnServers; - private boolean isCrackedFlag; - private final boolean enableBackendRPCAPI; - private final boolean useModernizedChannelNames; - private final EaglerPauseMenuConfig pauseMenuConf; - Property[] eaglerPlayersVanillaSkinCached = new Property[] { isEaglerProperty }; - - public String getServerName() { - return serverName; - } - - public UUID getServerUUID() { - return serverUUID; - } - - public long getWebsocketKeepAliveTimeout() { - return websocketKeepAliveTimeout; - } - - public long getWebsocketHandshakeTimeout() { - return websocketHandshakeTimeout; - } - - public long getBuiltinHttpServerTimeout() { - return builtinHttpServerTimeout; - } - - public int getHttpWebsocketCompressionLevel() { - return httpWebsocketCompressionLevel; - } - - public Collection getServerListeners() { - return serverListeners.values(); - } - - public EaglerListenerConfig getServerListenersByName(String name) { - return serverListeners.get(name); - } - - public Map getContentType() { - return contentTypes; - } - - public Map getContentTypes() { - return contentTypes; - } - - public boolean getDownloadVanillaSkins() { - return downloadVanillaSkins; - } - - public Collection getValidSkinUrls() { - return validSkinUrls; - } - - public boolean isValidSkinHost(String host) { - host = host.toLowerCase(); - for(String str : validSkinUrls) { - if(str.length() > 0) { - str = str.toLowerCase(); - if(str.charAt(0) == '*') { - if(host.endsWith(str.substring(1))) { - return true; - } - }else { - if(host.equals(str)) { - return true; - } - } - } - } - return false; - } - - public int getUuidRateLimitPlayer() { - return uuidRateLimitPlayer; - } - - public int getUuidRateLimitGlobal() { - return uuidRateLimitGlobal; - } - - public int getSkinRateLimitPlayer() { - return skinRateLimitPlayer; - } - - public int getSkinRateLimitGlobal() { - return skinRateLimitGlobal; - } - - public String getSkinCacheURI() { - return skinCacheURI; - } - - public String getSQLiteDriverClass() { - return sqliteDriverClass; - } - - public String getSQLiteDriverPath() { - return sqliteDriverPath; - } - - public int getKeepObjectsDays() { - return keepObjectsDays; - } - - public int getKeepProfilesDays() { - return keepProfilesDays; - } - - public int getMaxObjects() { - return maxObjects; - } - - public int getMaxProfiles() { - return maxProfiles; - } - - public int getAntagonistsRateLimit() { - return antagonistsRateLimit; - } - - public String getEaglerPlayersVanillaSkin() { - return eaglerPlayersVanillaSkin; - } - - public boolean getEnableIsEaglerPlayerProperty() { - return enableIsEaglerPlayerProperty; - } - - public Property[] getEaglerPlayersVanillaSkinProperties() { - return eaglerPlayersVanillaSkinCached; - } - - public boolean isCracked() { - return isCrackedFlag; - } - - public void setCracked(boolean cracked) { - isCrackedFlag = cracked; - } - - public EaglerAuthConfig getAuthConfig() { - return authConfig; - } - - public EaglerUpdateConfig getUpdateConfig() { - return updateConfig; - } - - public Collection getICEServers() { - return iceServers; - } - - public boolean getEnableVoiceChat() { - return enableVoiceChat; - } - - public Set getDisableVoiceOnServersSet() { - return disableVoiceOnServers; - } - - public boolean getDisableFNAWSkinsEverywhere() { - return disableFNAWSkinsEverywhere; - } - - public Set getDisableFNAWSkinsOnServersSet() { - return disableFNAWSkinsOnServers; - } - - public boolean getEnableBackendRPCAPI() { - return enableBackendRPCAPI; - } - - public boolean getUseModernizedChannelNames() { - return useModernizedChannelNames; - } - - public EaglerPauseMenuConfig getPauseMenuConf() { - return pauseMenuConf; - } - - private EaglerVelocityConfig(String serverName, UUID serverUUID, long websocketKeepAliveTimeout, - long websocketHandshakeTimeout, long builtinHttpServerTimeout, int httpWebsocketCompressionLevel, - Map serverListeners, Map contentTypes, - boolean downloadVanillaSkins, Collection validSkinUrls, int uuidRateLimitPlayer, - int uuidRateLimitGlobal, int skinRateLimitPlayer, int skinRateLimitGlobal, String skinCacheURI, - int keepObjectsDays, int keepProfilesDays, int maxObjects, int maxProfiles, int antagonistsRateLimit, - String sqliteDriverClass, String sqliteDriverPath, String eaglerPlayersVanillaSkin, - boolean enableIsEaglerPlayerProperty, EaglerAuthConfig authConfig, EaglerUpdateConfig updateConfig, - Collection iceServers, boolean enableVoiceChat, Set disableVoiceOnServers, - boolean disableFNAWSkinsEverywhere, Set disableFNAWSkinsOnServers, boolean enableBackendRPCAPI, - boolean useModernizedChannelNames, EaglerPauseMenuConfig pauseMenuConf) { - this.serverName = serverName; - this.serverUUID = serverUUID; - this.serverListeners = serverListeners; - this.websocketHandshakeTimeout = websocketHandshakeTimeout; - this.websocketKeepAliveTimeout = websocketKeepAliveTimeout; - this.builtinHttpServerTimeout = builtinHttpServerTimeout; - this.httpWebsocketCompressionLevel = httpWebsocketCompressionLevel; - this.contentTypes = contentTypes; - this.downloadVanillaSkins = downloadVanillaSkins; - this.validSkinUrls = validSkinUrls; - this.uuidRateLimitPlayer = uuidRateLimitPlayer; - this.uuidRateLimitGlobal = uuidRateLimitGlobal; - this.skinRateLimitPlayer = skinRateLimitPlayer; - this.skinRateLimitGlobal = skinRateLimitGlobal; - this.skinCacheURI = skinCacheURI; - this.keepObjectsDays = keepObjectsDays; - this.keepProfilesDays = keepProfilesDays; - this.maxObjects = maxObjects; - this.maxProfiles = maxProfiles; - this.antagonistsRateLimit = antagonistsRateLimit; - this.sqliteDriverClass = sqliteDriverClass; - this.sqliteDriverPath = sqliteDriverPath; - this.eaglerPlayersVanillaSkin = eaglerPlayersVanillaSkin; - this.enableIsEaglerPlayerProperty = enableIsEaglerPlayerProperty; - this.authConfig = authConfig; - this.updateConfig = updateConfig; - this.iceServers = iceServers; - this.enableVoiceChat = enableVoiceChat; - this.disableVoiceOnServers = disableVoiceOnServers; - this.disableFNAWSkinsEverywhere = disableFNAWSkinsEverywhere; - this.disableFNAWSkinsOnServers = disableFNAWSkinsOnServers; - this.enableBackendRPCAPI = enableBackendRPCAPI; - this.useModernizedChannelNames = useModernizedChannelNames; - this.pauseMenuConf = pauseMenuConf; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/MOTDCacheConfiguration.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/MOTDCacheConfiguration.java deleted file mode 100644 index e6a0073d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/MOTDCacheConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -public class MOTDCacheConfiguration { - - public final int cacheTTL; - public final boolean cacheServerListAnimation; - public final boolean cacheServerListResults; - public final boolean cacheServerListTrending; - public final boolean cacheServerListPortfolios; - - public MOTDCacheConfiguration(int cacheTTL, boolean cacheServerListAnimation, boolean cacheServerListResults, - boolean cacheServerListTrending, boolean cacheServerListPortfolios) { - this.cacheTTL = cacheTTL; - this.cacheServerListAnimation = cacheServerListAnimation; - this.cacheServerListResults = cacheServerListResults; - this.cacheServerListTrending = cacheServerListTrending; - this.cacheServerListPortfolios = cacheServerListPortfolios; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/RateLimitStatus.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/RateLimitStatus.java deleted file mode 100644 index e4af61b9..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/RateLimitStatus.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -public enum RateLimitStatus { - OK, LIMITED, LIMITED_NOW_LOCKED_OUT, LOCKED_OUT; -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerIconLoader.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerIconLoader.java deleted file mode 100644 index 79f0e41c..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerIconLoader.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -class ServerIconLoader { - - static int[] createServerIcon(BufferedImage awtIcon) { - BufferedImage icon = awtIcon; - boolean gotScaled = false; - if(icon.getWidth() != 64 || icon.getHeight() != 64) { - icon = new BufferedImage(64, 64, awtIcon.getType()); - Graphics2D g = (Graphics2D) icon.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ? - RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, 64, 64); - int ow = awtIcon.getWidth(); - int oh = awtIcon.getHeight(); - int nw, nh; - float aspectRatio = (float)oh / (float)ow; - if(aspectRatio >= 1.0f) { - nw = (int)(64 / aspectRatio); - nh = 64; - }else { - nw = 64; - nh = (int)(64 * aspectRatio); - } - g.drawImage(awtIcon, (64 - nw) / 2, (64 - nh) / 2, (64 - nw) / 2 + nw, (64 - nh) / 2 + nh, 0, 0, awtIcon.getWidth(), awtIcon.getHeight(), null); - g.dispose(); - gotScaled = true; - } - int[] pxls = icon.getRGB(0, 0, 64, 64, new int[4096], 0, 64); - if(gotScaled) { - for(int i = 0; i < pxls.length; ++i) { - if((pxls[i] & 0xFFFFFF) == 0) { - pxls[i] = 0; - } - } - } - return pxls; - } - - static int[] createServerIcon(InputStream f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - - static int[] createServerIcon(File f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerInfoTemplateParser.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerInfoTemplateParser.java deleted file mode 100644 index 09f16773..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerInfoTemplateParser.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; - - -import com.google.common.html.HtmlEscapers; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.kyori.adventure.translation.GlobalTranslator; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.repackage.lang3.StrTokenizer; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.Base64; - -public class ServerInfoTemplateParser { - - private static final Gson jsonEscaper = (new GsonBuilder()).disableHtmlEscaping().create(); - - private static class State { - private boolean evalAllowed; - private File baseDir; - private Map globals; - private boolean htmlEscape; - private boolean strEscape; - private boolean disableMacros; - private boolean enableEval; - private State(File baseDir, boolean evalAllowed, Map globals) { - this.baseDir = baseDir; - this.evalAllowed = evalAllowed; - this.globals = globals; - } - private State push() { - return new State(baseDir, evalAllowed, globals); - } - } - - public static String loadTemplate(String content, File baseDir, boolean evalAllowed, Map globals) throws IOException { - return loadTemplate(content, new State(baseDir, evalAllowed, globals)); - } - - private static String loadTemplate(String content, State state) throws IOException { - StringBuilder ret = new StringBuilder(); - int i = 0, j = 0; - while((i = content.indexOf("{%", j)) != -1) { - ret.append(content, j, i); - j = i; - i = content.indexOf("%}", j + 2); - if(i != -1) { - ret.append(processMacro(content.substring(j + 2, i), state)); - j = i + 2; - }else { - break; - } - } - ret.append(content, j, content.length()); - return ret.toString(); - } - - public static class InvalidMacroException extends RuntimeException { - - public InvalidMacroException(String message, Throwable cause) { - super(message, cause); - } - - public InvalidMacroException(String message) { - super(message); - } - - } - - private static String processMacro(String content, State state) throws IOException { - String trimmed = content.trim(); - try { - String[] strs = (new StrTokenizer(trimmed, ' ', '`')).getTokenArray(); - if(strs.length < 1) { - return "{%" + content + "%}"; - } - if(strs[0].equals("disablemacros") && strs.length == 2) { - switch(strs[1]) { - case "on": - if(state.disableMacros) { - return "{%" + content + "%}"; - }else { - state.disableMacros = true; - return ""; - } - case "off": - state.disableMacros = false; - return ""; - default: - if(state.disableMacros) { - return "{%" + content + "%}"; - }else { - throw new InvalidMacroException("Unknown disablemacros mode: " + strs[1] + " (Expected: on, off)"); - } - } - }else if(!state.disableMacros) { - switch(strs[0]) { - case "embed": - argCheck(3, strs.length); - switch(strs[1]) { - case "base64": - return Base64.encodeBase64String(EaglerXVelocityAPIHelper.loadFileToByteArrayServerInfo(new File(state.baseDir, strs[2]))); - case "text": - return escapeMacroResult(EaglerXVelocityAPIHelper.loadFileToStringServerInfo(new File(state.baseDir, strs[2])), state); - case "eval": - if(state.evalAllowed) { - return escapeMacroResult(loadTemplate(EaglerXVelocityAPIHelper.loadFileToStringServerInfo(new File(state.baseDir, strs[2])), state.push()), state); - }else { - throw new InvalidMacroException("Template tried to eval file \"" + strs[2] + "\"! (eval is disabled)"); - } - default: - throw new InvalidMacroException("Unknown embed mode: " + strs[1] + " (Expected: base64, text, eval)"); - } - case "htmlescape": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - state.htmlEscape = true; - return ""; - case "off": - state.htmlEscape = false; - return ""; - default: - throw new InvalidMacroException("Unknown htmlescape mode: " + strs[1] + " (Expected: on, off)"); - } - case "strescape": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - state.strEscape = true; - return ""; - case "off": - state.strEscape = false; - return ""; - default: - throw new InvalidMacroException("Unknown strescape mode: " + strs[1] + " (Expected: on, off)"); - } - case "eval": - argCheck(2, strs.length); - switch(strs[1]) { - case "on": - if(!state.evalAllowed) { - throw new InvalidMacroException("Template tried to enable eval! (eval is disabled)"); - } - state.enableEval = true; - return ""; - case "off": - state.enableEval = false; - return ""; - default: - throw new InvalidMacroException("Unknown eval mode: " + strs[1] + " (Expected: on, off)"); - } - case "global": - argCheck(2, 3, strs.length); - String ret = state.globals.get(strs[1]); - if(ret == null) { - if(strs.length == 3) { - ret = strs[2]; - }else { - throw new InvalidMacroException("Unknown global \"" + strs[1] + "\"! (Available: " + String.join(", ", state.globals.keySet()) + ")"); - } - } - return escapeMacroResult(ret, state); - case "property": - argCheck(2, 3, strs.length); - ret = System.getProperty(strs[1]); - if(ret == null) { - if(strs.length == 3) { - ret = strs[2]; - }else { - throw new InvalidMacroException("Unknown system property \"" + strs[1] + "\"!"); - } - } - return escapeMacroResult(ret, state); - case "text": - argCheck(2, strs.length); - return escapeMacroResult(strs[1], state); - case "translate": - argCheckMin(2, strs.length); - TextComponent[] additionalArgs = new TextComponent[strs.length - 2]; - for(int i = 0; i < additionalArgs.length; ++i) { - additionalArgs[i] = Component.text(strs[i + 2]); - } - return escapeMacroResult(LegacyComponentSerializer.legacySection().serialize( - GlobalTranslator.render(Component.translatable(strs[1]).arguments(Arrays.asList(additionalArgs)), Locale.getDefault())), state); - default: - return "{%" + content + "%}"; - } - }else { - return "{%" + content + "%}"; - } - }catch(InvalidMacroException ex) { - throw new IOException("Invalid macro: {% " + trimmed + " %}, message: " + ex.getMessage(), ex); - }catch(Throwable th) { - throw new IOException("Error processing: {% " + trimmed + " %}, raised: " + th.toString(), th); - } - } - - private static String escapeMacroResult(String str, State state) throws IOException { - if(str.length() > 0) { - if(state.evalAllowed && state.enableEval) { - str = loadTemplate(str, state.push()); - } - if(state.strEscape) { - str = jsonEscaper.toJson(str); - if(str.length() >= 2) { - str = str.substring(1, str.length() - 1); - } - } - if(state.htmlEscape) { - str = HtmlEscapers.htmlEscaper().escape(str); - } - } - return str; - } - - private static void argCheck(int expect, int actual) { - if(expect != actual) { - throw new InvalidMacroException("Wrong number of arguments (" + actual + ", expected " + expect + ")"); - } - } - - private static void argCheck(int expectMin, int expectMax, int actual) { - if(expectMin > actual || expectMax < actual) { - throw new InvalidMacroException("Wrong number of arguments (" + actual + ", expected " + expectMin + " to " + expectMax + ")"); - } - } - - private static void argCheckMin(int expectMin, int actual) { - if(expectMin > actual) { - throw new InvalidMacroException("Wrong number of arguments (expected " + expectMin + " or more, got " + actual + ")"); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/TestOutputStream.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/TestOutputStream.java deleted file mode 100644 index 92136b0d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/TestOutputStream.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.io.IOException; -import java.io.OutputStream; - -public class TestOutputStream extends OutputStream { - - @Override - public void write(int b) throws IOException { - } - - @Override - public void write(byte[] b, int o, int l) throws IOException { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/VanillaDefaultSkinProfileLoader.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/VanillaDefaultSkinProfileLoader.java deleted file mode 100644 index 7622addd..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/VanillaDefaultSkinProfileLoader.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.function.Consumer; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.velocitypowered.api.util.GameProfile.Property; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.BinaryHttpClient; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.BinaryHttpClient.Response; - -class VanillaDefaultSkinProfileLoader implements Consumer { - - private class ProfileSkinConsumerImpl implements Consumer { - - private final String uuid; - - private ProfileSkinConsumerImpl(String uuid) { - this.uuid = uuid; - } - - @Override - public void accept(Response response) { - if(response == null) { - EaglerXVelocity.logger().error("Request error (null)"); - doNotify(); - }else if(response.exception != null) { - EaglerXVelocity.logger().error("Exception loading vanilla default profile!", response.exception); - doNotify(); - }else if(response.code != 200) { - EaglerXVelocity.logger().error("Recieved code {} while looking up profile of {}", response.code, uuid); - doNotify(); - }else if (response.data == null) { - EaglerXVelocity.logger().error("Recieved null payload while looking up profile of {}", uuid); - doNotify(); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - JsonElement propsElement = json.get("properties"); - if(propsElement != null) { - JsonArray properties = propsElement.getAsJsonArray(); - if(properties.size() > 0) { - for(int i = 0, l = properties.size(); i < l; ++i) { - JsonElement prop = properties.get(i); - if(prop.isJsonObject()) { - JsonObject propObj = prop.getAsJsonObject(); - if(propObj.get("name").getAsString().equals("textures")) { - JsonElement value = propObj.get("value"); - JsonElement signature = propObj.get("signature"); - if(value != null) { - Property newProp = new Property("textures", value.getAsString(), - signature != null ? signature.getAsString() : ""); - config.eaglerPlayersVanillaSkinCached = new Property[] { newProp, EaglerVelocityConfig.isEaglerProperty }; - } - EaglerXVelocity.logger().info("Loaded vanilla profile: " + config.getEaglerPlayersVanillaSkin()); - doNotify(); - return; - } - } - } - } - } - EaglerXVelocity.logger().warn("No skin was found for: {}", config.getEaglerPlayersVanillaSkin()); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception processing name to UUID lookup response!", t); - } - doNotify(); - } - } - - } - - private final EaglerVelocityConfig config; - private volatile boolean isLocked = true; - private final Object lock = new Object(); - - private VanillaDefaultSkinProfileLoader(EaglerVelocityConfig config) { - this.config = config; - } - - @Override - public void accept(Response response) { - if(response == null) { - EaglerXVelocity.logger().error("Request error (null)"); - doNotify(); - }else if(response.exception != null) { - EaglerXVelocity.logger().error("Exception loading vanilla default profile!", response.exception); - doNotify(); - }else if(response.code != 200) { - EaglerXVelocity.logger().error("Recieved code {} while looking up UUID of {}", response.code, config.getEaglerPlayersVanillaSkin()); - doNotify(); - }else if (response.data == null) { - EaglerXVelocity.logger().error("Recieved null payload while looking up UUID of {}", config.getEaglerPlayersVanillaSkin()); - doNotify(); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String uuid = json.get("id").getAsString(); - URI requestURI = URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); - BinaryHttpClient.asyncRequest("GET", requestURI, new ProfileSkinConsumerImpl(uuid)); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception processing name to UUID lookup response!", t); - doNotify(); - } - } - } - - private void doNotify() { - synchronized(lock) { - if(isLocked) { - isLocked = false; - lock.notify(); - } - } - } - - static void lookupVanillaSkinUser(EaglerVelocityConfig config) { - String user = config.getEaglerPlayersVanillaSkin(); - EaglerXVelocity.logger().info("Loading vanilla profile: " + user); - URI requestURI = URI.create("https://api.mojang.com/users/profiles/minecraft/" + user); - VanillaDefaultSkinProfileLoader loader = new VanillaDefaultSkinProfileLoader(config); - synchronized(loader.lock) { - BinaryHttpClient.asyncRequest("GET", requestURI, loader); - if(loader.isLocked) { - try { - loader.lock.wait(5000l); - } catch (InterruptedException e) { - } - if(loader.isLocked) { - EaglerXVelocity.logger().warn("Profile load timed out"); - } - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ChatColor.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ChatColor.java deleted file mode 100644 index 388b35c3..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ChatColor.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, md_5. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The name of the author may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * You may not use the software for commercial software hosting services without - * written permission from the author. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee; - -public class ChatColor { - - public static final char COLOR_CHAR = '\u00A7'; - public static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx"; - - public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) { - char[] b = textToTranslate.toCharArray(); - for (int i = 0; i < b.length - 1; i++) { - if (b[i] == altColorChar && ALL_CODES.indexOf(b[i + 1]) > -1) { - b[i] = ChatColor.COLOR_CHAR; - b[i + 1] = Character.toLowerCase(b[i + 1]); - } - } - return new String(b); - } - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/Configuration.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/Configuration.java deleted file mode 100644 index 3c9c74b2..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/Configuration.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (c) 2012, md_5. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The name of the author may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * You may not use the software for commercial software hosting services without - * written permission from the author. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; - -public final class Configuration { - - private static final char SEPARATOR = '.'; - final Map self; - private final Configuration defaults; - - public Configuration() { - this(null); - } - - public Configuration(Configuration defaults) { - this(new LinkedHashMap(), defaults); - } - - Configuration(Map map, Configuration defaults) { - this.self = new LinkedHashMap<>(); - this.defaults = defaults; - - for (Map.Entry entry : map.entrySet()) { - String key = (entry.getKey() == null) ? "null" : entry.getKey().toString(); - - if (entry.getValue() instanceof Map) { - this.self.put(key, new Configuration((Map) entry.getValue(), - (defaults == null) ? null : defaults.getSection(key))); - } else { - this.self.put(key, entry.getValue()); - } - } - } - - private Configuration getSectionFor(String path) { - int index = path.indexOf(SEPARATOR); - if (index == -1) { - return this; - } - - String root = path.substring(0, index); - Object section = self.get(root); - if (section == null) { - section = new Configuration((defaults == null) ? null : defaults.getSection(root)); - self.put(root, section); - } - - return (Configuration) section; - } - - private String getChild(String path) { - int index = path.indexOf(SEPARATOR); - return (index == -1) ? path : path.substring(index + 1); - } - - /*------------------------------------------------------------------------*/ - @SuppressWarnings("unchecked") - public T get(String path, T def) { - Configuration section = getSectionFor(path); - Object val; - if (section == this) { - val = self.get(path); - } else { - val = section.get(getChild(path), def); - } - - if (val == null && def instanceof Configuration) { - self.put(path, def); - } - - return (val != null) ? (T) val : def; - } - - public boolean contains(String path) { - return get(path, null) != null; - } - - public Object get(String path) { - return get(path, getDefault(path)); - } - - public Object getDefault(String path) { - return (defaults == null) ? null : defaults.get(path); - } - - public void set(String path, Object value) { - if (value instanceof Map) { - value = new Configuration((Map) value, (defaults == null) ? null : defaults.getSection(path)); - } - - Configuration section = getSectionFor(path); - if (section == this) { - if (value == null) { - self.remove(path); - } else { - self.put(path, value); - } - } else { - section.set(getChild(path), value); - } - } - - /*------------------------------------------------------------------------*/ - public Configuration getSection(String path) { - Object def = getDefault(path); - return (Configuration) get(path, (def instanceof Configuration) ? def - : new Configuration((defaults == null) ? null : defaults.getSection(path))); - } - - /** - * Gets keys, not deep by default. - * - * @return top level keys for this section - */ - public Collection getKeys() { - return new LinkedHashSet<>(self.keySet()); - } - - /*------------------------------------------------------------------------*/ - public byte getByte(String path) { - Object def = getDefault(path); - return getByte(path, (def instanceof Number) ? ((Number) def).byteValue() : 0); - } - - public byte getByte(String path, byte def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).byteValue() : def; - } - - public List getByteList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).byteValue()); - } - } - - return result; - } - - public short getShort(String path) { - Object def = getDefault(path); - return getShort(path, (def instanceof Number) ? ((Number) def).shortValue() : 0); - } - - public short getShort(String path, short def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).shortValue() : def; - } - - public List getShortList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).shortValue()); - } - } - - return result; - } - - public int getInt(String path) { - Object def = getDefault(path); - return getInt(path, (def instanceof Number) ? ((Number) def).intValue() : 0); - } - - public int getInt(String path, int def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).intValue() : def; - } - - public List getIntList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).intValue()); - } - } - - return result; - } - - public long getLong(String path) { - Object def = getDefault(path); - return getLong(path, (def instanceof Number) ? ((Number) def).longValue() : 0); - } - - public long getLong(String path, long def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).longValue() : def; - } - - public List getLongList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).longValue()); - } - } - - return result; - } - - public float getFloat(String path) { - Object def = getDefault(path); - return getFloat(path, (def instanceof Number) ? ((Number) def).floatValue() : 0); - } - - public float getFloat(String path, float def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).floatValue() : def; - } - - public List getFloatList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).floatValue()); - } - } - - return result; - } - - public double getDouble(String path) { - Object def = getDefault(path); - return getDouble(path, (def instanceof Number) ? ((Number) def).doubleValue() : 0); - } - - public double getDouble(String path, double def) { - Object val = get(path, def); - return (val instanceof Number) ? ((Number) val).doubleValue() : def; - } - - public List getDoubleList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Number) { - result.add(((Number) object).doubleValue()); - } - } - - return result; - } - - public boolean getBoolean(String path) { - Object def = getDefault(path); - return getBoolean(path, (def instanceof Boolean) ? (Boolean) def : false); - } - - public boolean getBoolean(String path, boolean def) { - Object val = get(path, def); - return (val instanceof Boolean) ? (Boolean) val : def; - } - - public List getBooleanList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Boolean) { - result.add((Boolean) object); - } - } - - return result; - } - - public char getChar(String path) { - Object def = getDefault(path); - return getChar(path, (def instanceof Character) ? (Character) def : '\u0000'); - } - - public char getChar(String path, char def) { - Object val = get(path, def); - return (val instanceof Character) ? (Character) val : def; - } - - public List getCharList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof Character) { - result.add((Character) object); - } - } - - return result; - } - - public String getString(String path) { - Object def = getDefault(path); - return getString(path, (def instanceof String) ? (String) def : ""); - } - - public String getString(String path, String def) { - Object val = get(path, def); - return (val instanceof String) ? (String) val : def; - } - - public List getStringList(String path) { - List list = getList(path); - List result = new ArrayList<>(); - - for (Object object : list) { - if (object instanceof String) { - result.add((String) object); - } - } - - return result; - } - - /*------------------------------------------------------------------------*/ - public List getList(String path) { - Object def = getDefault(path); - return getList(path, (def instanceof List) ? (List) def : Collections.EMPTY_LIST); - } - - public List getList(String path, List def) { - Object val = get(path, def); - return (val instanceof List) ? (List) val : def; - } -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ConfigurationProvider.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ConfigurationProvider.java deleted file mode 100644 index 40b8a0c1..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/ConfigurationProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012, md_5. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The name of the author may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * You may not use the software for commercial software hosting services without - * written permission from the author. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.Writer; -import java.util.HashMap; -import java.util.Map; - -public abstract class ConfigurationProvider { - - private static final Map, ConfigurationProvider> providers = new HashMap<>(); - - static { - try { - providers.put(YamlConfiguration.class, new YamlConfiguration()); - } catch (NoClassDefFoundError ex) { - // Ignore, no SnakeYAML - } - - try { - providers.put(JsonConfiguration.class, new JsonConfiguration()); - } catch (NoClassDefFoundError ex) { - // Ignore, no Gson - } - } - - public static ConfigurationProvider getProvider(Class provider) { - return providers.get(provider); - } - - /*------------------------------------------------------------------------*/ - public abstract void save(Configuration config, File file) throws IOException; - - public abstract void save(Configuration config, Writer writer); - - public abstract Configuration load(File file) throws IOException; - - public abstract Configuration load(File file, Configuration defaults) throws IOException; - - public abstract Configuration load(Reader reader); - - public abstract Configuration load(Reader reader, Configuration defaults); - - public abstract Configuration load(InputStream is); - - public abstract Configuration load(InputStream is, Configuration defaults); - - public abstract Configuration load(String string); - - public abstract Configuration load(String string, Configuration defaults); -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/JsonConfiguration.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/JsonConfiguration.java deleted file mode 100644 index 78d45c90..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/JsonConfiguration.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2012, md_5. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The name of the author may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * You may not use the software for commercial software hosting services without - * written permission from the author. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; -import java.util.Map; - -public class JsonConfiguration extends ConfigurationProvider { - - private final Gson json = new GsonBuilder().serializeNulls().setPrettyPrinting() - .registerTypeAdapter(Configuration.class, new JsonSerializer() { - @Override - public JsonElement serialize(Configuration src, Type typeOfSrc, JsonSerializationContext context) { - return context.serialize(((Configuration) src).self); - } - }).create(); - - @Override - public void save(Configuration config, File file) throws IOException { - try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { - save(config, writer); - } - } - - @Override - public void save(Configuration config, Writer writer) { - json.toJson(config.self, writer); - } - - @Override - public Configuration load(File file) throws IOException { - return load(file, null); - } - - @Override - public Configuration load(File file, Configuration defaults) throws IOException { - try (FileInputStream is = new FileInputStream(file)) { - return load(is, defaults); - } - } - - @Override - public Configuration load(Reader reader) { - return load(reader, null); - } - - @Override - @SuppressWarnings("unchecked") - public Configuration load(Reader reader, Configuration defaults) { - Map map = json.fromJson(reader, LinkedHashMap.class); - if (map == null) { - map = new LinkedHashMap<>(); - } - return new Configuration(map, defaults); - } - - @Override - public Configuration load(InputStream is) { - return load(is, null); - } - - @Override - public Configuration load(InputStream is, Configuration defaults) { - return load(new InputStreamReader(is, StandardCharsets.UTF_8), defaults); - } - - @Override - public Configuration load(String string) { - return load(string, null); - } - - @Override - @SuppressWarnings("unchecked") - public Configuration load(String string, Configuration defaults) { - Map map = json.fromJson(string, LinkedHashMap.class); - if (map == null) { - map = new LinkedHashMap<>(); - } - return new Configuration(map, defaults); - } -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/YamlConfiguration.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/YamlConfiguration.java deleted file mode 100644 index 50360a44..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/bungee/YamlConfiguration.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2012, md_5. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * The name of the author may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * You may not use the software for commercial software hosting services without - * written permission from the author. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.bungee; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.util.LinkedHashMap; -import java.util.Map; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.LoaderOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.representer.Represent; -import org.yaml.snakeyaml.representer.Representer; - -public class YamlConfiguration extends ConfigurationProvider { - - private final ThreadLocal yaml = new ThreadLocal() { - @Override - protected Yaml initialValue() { - DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - - Representer representer = new Representer(options) { - { - representers.put(Configuration.class, new Represent() { - @Override - public Node representData(Object data) { - return represent(((Configuration) data).self); - } - }); - } - }; - - return new Yaml(new Constructor(new LoaderOptions()), representer, options); - } - }; - - @Override - public void save(Configuration config, File file) throws IOException { - try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { - save(config, writer); - } - } - - @Override - public void save(Configuration config, Writer writer) { - yaml.get().dump(config.self, writer); - } - - @Override - public Configuration load(File file) throws IOException { - return load(file, null); - } - - @Override - public Configuration load(File file, Configuration defaults) throws IOException { - try (FileInputStream is = new FileInputStream(file)) { - return load(is, defaults); - } - } - - @Override - public Configuration load(Reader reader) { - return load(reader, null); - } - - @Override - @SuppressWarnings("unchecked") - public Configuration load(Reader reader, Configuration defaults) { - Map map = yaml.get().loadAs(reader, LinkedHashMap.class); - if (map == null) { - map = new LinkedHashMap<>(); - } - return new Configuration(map, defaults); - } - - @Override - public Configuration load(InputStream is) { - return load(is, null); - } - - @Override - @SuppressWarnings("unchecked") - public Configuration load(InputStream is, Configuration defaults) { - Map map = yaml.get().loadAs(is, LinkedHashMap.class); - if (map == null) { - map = new LinkedHashMap<>(); - } - return new Configuration(map, defaults); - } - - @Override - public Configuration load(String string) { - return load(string, null); - } - - @Override - @SuppressWarnings("unchecked") - public Configuration load(String string, Configuration defaults) { - Map map = yaml.get().loadAs(string, LinkedHashMap.class); - if (map == null) { - map = new LinkedHashMap<>(); - } - return new Configuration(map, defaults); - } -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/handlers/EaglerPacketEventListener.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/handlers/EaglerPacketEventListener.java deleted file mode 100644 index fae2bd1c..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/handlers/EaglerPacketEventListener.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.handlers; - -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.UUID; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.velocitypowered.api.event.PostOrder; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.connection.DisconnectEvent; -import com.velocitypowered.api.event.connection.PluginMessageEvent; -import com.velocitypowered.api.event.connection.PluginMessageEvent.ForwardResult; -import com.velocitypowered.api.event.connection.PostLoginEvent; -import com.velocitypowered.api.event.player.ServerPostConnectEvent; -import com.velocitypowered.api.event.player.ServerPreConnectEvent; -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.api.proxy.messages.ChannelIdentifier; -import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; -import com.velocitypowered.api.proxy.server.ServerInfo; -import com.velocitypowered.api.util.GameProfile; -import com.velocitypowered.api.util.GameProfile.Property; -import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.kyori.adventure.text.Component; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerAuthConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.BackendRPCSessionHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.Base64; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinPackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketEnableFNAWSkinsEAG; - -public class EaglerPacketEventListener { - - public static final ChannelIdentifier GET_DOMAIN_CHANNEL = new LegacyChannelIdentifier("EAG|GetDomain"); - - private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - - public final EaglerXVelocity plugin; - - public EaglerPacketEventListener(EaglerXVelocity plugin) { - this.plugin = plugin; - } - - @Subscribe(order = PostOrder.FIRST) - public void onPluginMessage(final PluginMessageEvent event) { - ChannelIdentifier tagObj = event.getIdentifier(); - String tag = tagObj.getId(); - if(event.getSource() instanceof ConnectedPlayer) { - final ConnectedPlayer player = (ConnectedPlayer)event.getSource(); - EaglerPlayerData eagPlayer = EaglerPipeline.getEaglerHandle(player); - if(eagPlayer != null) { - GameProtocolMessageController msgController = eagPlayer.getEaglerMessageController(); - if(msgController != null) { - try { - if(msgController.handlePacket(tag, event.getData())) { - event.setResult(ForwardResult.handled()); - return; - } - } catch (Throwable e) { - player.disconnect(Component.text("Eaglercraft packet error!")); - event.setResult(ForwardResult.handled()); - return; - } - } - if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(tag) || EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN.equals(tag)) { - player.disconnect(Component.text("Nope!")); - event.setResult(ForwardResult.handled()); - return; - } - if(EaglerBackendRPCProtocol.CHANNEL_NAME_READY.equals(tag) || EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN.equals(tag)) { - event.setResult(ForwardResult.handled()); - return; - } - } - }else if(event.getSource() instanceof ServerConnection && event.getTarget() instanceof ConnectedPlayer) { - ConnectedPlayer player = (ConnectedPlayer)event.getTarget(); - EaglerPlayerData eagPlayerData = EaglerPipeline.getEaglerHandle(player); - if(eagPlayerData != null) { - if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(tag) || EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN.equals(tag)) { - event.setResult(ForwardResult.handled()); - try { - eagPlayerData.handleBackendRPCPacket((ServerConnection)event.getSource(), event.getData()); - }catch(Throwable t) { - EaglerXVelocity.logger().error("[{}]: Caught an exception handling backend RPC packet!", player.getUsername(), t); - } - }else if("EAG|GetDomain".equals(tag)) { - event.setResult(ForwardResult.handled()); - String domain = eagPlayerData.getOrigin(); - if(domain == null) { - ((ServerConnection)event.getSource()).sendPluginMessage(GET_DOMAIN_CHANNEL, new byte[] { 0 }); - }else { - ((ServerConnection)event.getSource()).sendPluginMessage(GET_DOMAIN_CHANNEL, domain.getBytes(StandardCharsets.UTF_8)); - } - } - }else { - if(EaglerBackendRPCProtocol.CHANNEL_NAME.equals(tag) || EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN.equals(tag)) { - event.setResult(ForwardResult.handled()); - try { - BackendRPCSessionHandler.handlePacketOnVanilla((ServerConnection)event.getSource(), player, event.getData()); - }catch(Throwable t) { - EaglerXVelocity.logger().error("[{}]: Caught an exception handling backend RPC packet!", player.getUsername(), t); - } - } - } - } - } - - @Subscribe - public void onPostLogin(PostLoginEvent event) { - Player p = event.getPlayer(); - if(p instanceof ConnectedPlayer) { - ConnectedPlayer player = (ConnectedPlayer)p; - GameProfile res = player.getGameProfile(); - if(res != null) { - List props = res.getProperties(); - if(props.size() > 0) { - for(int i = 0, l = props.size(); i < l; ++i) { - Property pp = props.get(i); - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = SkinService.sanitizeTextureURL(url.getAsString()); - plugin.getSkinService().registerTextureToPlayerAssociation(urlStr, player.getUniqueId()); - } - } - }catch(Throwable t) { - } - } - } - } - } - EaglerAuthConfig authConf = plugin.getConfig().getAuthConfig(); - if(authConf.isEnableAuthentication() && authConf.isUseBuiltInAuthentication()) { - DefaultAuthSystem srv = plugin.getAuthService(); - if(srv != null) { - srv.handleVanillaLogin(event); - } - } - } - } - - @Subscribe - public void onConnectionLost(DisconnectEvent event) { - UUID uuid = event.getPlayer().getUniqueId(); - plugin.getSkinService().unregisterPlayer(uuid); - plugin.getCapeService().unregisterPlayer(uuid); - if(event.getPlayer() instanceof ConnectedPlayer) { - ConnectedPlayer player = (ConnectedPlayer)event.getPlayer(); - EaglerPlayerData eagData = EaglerPipeline.getEaglerHandle(player); - if(eagData != null && eagData.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handlePlayerLoggedOut(eagData); - } - } - } - - @Subscribe - public void onServerConnected(ServerPostConnectEvent event) { - try { - ConnectedPlayer player = (ConnectedPlayer) event.getPlayer(); - ServerConnection server = player.getConnectedServer(); - BackendRPCSessionHandler.sendPluginMessage(server, - BackendRPCSessionHandler.getReadyChNameFor((VelocityServerConnection) server), EMPTY_BYTE_ARRAY); - EaglerPlayerData playerObj = EaglerPipeline.getEaglerHandle(player); - if(playerObj != null) { - ServerInfo sv = server.getServerInfo(); - boolean fnawSkins = !plugin.getConfig().getDisableFNAWSkinsEverywhere() - && !plugin.getConfig().getDisableFNAWSkinsOnServersSet().contains(sv.getName()); - if(fnawSkins != playerObj.currentFNAWSkinEnableStatus.getAndSet(fnawSkins)) { - playerObj.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(fnawSkins, false)); - } - if(playerObj.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerConnected(playerObj, sv); - } - } - }catch(Throwable t) { - EaglerXVelocity.logger().error("Failed to process server connection ready handler for player \"{}\"", - event.getPlayer().getUsername(), t); - } - } - - @Subscribe - public void onServerDisconnected(ServerPreConnectEvent event) { - if(event.getPreviousServer() != null && (event.getPlayer() instanceof ConnectedPlayer)) { - ConnectedPlayer player = (ConnectedPlayer)event.getPlayer(); - EaglerPlayerData eagData = EaglerPipeline.getEaglerHandle(player); - if(eagData != null) { - BackendRPCSessionHandler rpcHandler = eagData.getRPCSessionHandler(); - if(rpcHandler != null) { - rpcHandler.handleConnectionLost(); - } - if(eagData.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerDisconnected(eagData, event.getPreviousServer().getServerInfo()); - } - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrBuilder.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrBuilder.java deleted file mode 100644 index 4cb24c7b..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrBuilder.java +++ /dev/null @@ -1,3136 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.repackage.lang3; - -import java.io.IOException; -import java.io.Reader; -import java.io.Serializable; -import java.io.Writer; -import java.nio.CharBuffer; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; - -/** - * Builds a string from constituent parts providing a more flexible and powerful - * API than StringBuffer. - *

    - * The main differences from StringBuffer/StringBuilder are: - *

    - *
      - *
    • Not synchronized
    • - *
    • Not final
    • - *
    • Subclasses have direct access to character array
    • - *
    • Additional methods - *
        - *
      • appendWithSeparators - adds an array of values, with a separator
      • - *
      • appendPadding - adds a length padding characters
      • - *
      • appendFixedLength - adds a fixed width field to the builder
      • - *
      • toCharArray/getChars - simpler ways to get a range of the character - * array
      • - *
      • delete - delete char or string
      • - *
      • replace - search and replace for a char or string
      • - *
      • leftString/rightString/midString - substring without exceptions
      • - *
      • contains - whether the builder contains a char or string
      • - *
      • size/clear/isEmpty - collections style API methods
      • - *
      - *
    • - *
    • Views - *
        - *
      • asTokenizer - uses the internal buffer as the source of a - * StrTokenizer
      • - *
      • asReader - uses the internal buffer as the source of a Reader
      • - *
      • asWriter - allows a Writer to write directly to the internal buffer
      • - *
      - *
    • - *
    - *

    - * The aim has been to provide an API that mimics very closely what StringBuffer - * provides, but with additional methods. It should be noted that some edge - * cases, with invalid indices or null input, have been altered - see individual - * methods. The biggest of these changes is that by default, null will not - * output the text 'null'. This can be controlled by a property, - * {@link #setNullText(String)}. - *

    - * Prior to 3.0, this class implemented Cloneable but did not implement the - * clone method so could not be used. From 3.0 onwards it no longer implements - * the interface. - * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * TextStringBuilder instead - */ -//@Deprecated -public class StrBuilder implements CharSequence, Appendable, Serializable { - - /** - * The extra capacity for new builders. - */ - static final int CAPACITY = 32; - - /** - * Required for serialization support. - * - * @see java.io.Serializable - */ - private static final long serialVersionUID = 7628716375283629643L; - - /** Internal data storage. */ - protected char[] buffer; // TODO make private? - /** Current size of the buffer. */ - protected int size; // TODO make private? - /** The new line. */ - private String newLine; - /** The null text. */ - private String nullText; - - // ----------------------------------------------------------------------- - /** - * Constructor that creates an empty builder initial capacity 32 characters. - */ - public StrBuilder() { - this(CAPACITY); - } - - /** - * Constructor that creates an empty builder the specified initial capacity. - * - * @param initialCapacity the initial capacity, zero or less will be converted - * to 32 - */ - public StrBuilder(int initialCapacity) { - if (initialCapacity <= 0) { - initialCapacity = CAPACITY; - } - buffer = new char[initialCapacity]; - } - - /** - * Constructor that creates a builder from the string, allocating 32 extra - * characters for growth. - * - * @param str the string to copy, null treated as blank string - */ - public StrBuilder(final String str) { - if (str == null) { - buffer = new char[CAPACITY]; - } else { - buffer = new char[str.length() + CAPACITY]; - append(str); - } - } - - // ----------------------------------------------------------------------- - /** - * Gets the text to be appended when a new line is added. - * - * @return the new line text, null means use system default - */ - public String getNewLineText() { - return newLine; - } - - /** - * Sets the text to be appended when a new line is added. - * - * @param newLine the new line text, null means use system default - * @return this, to enable chaining - */ - public StrBuilder setNewLineText(final String newLine) { - this.newLine = newLine; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the text to be appended when null is added. - * - * @return the null text, null means no append - */ - public String getNullText() { - return nullText; - } - - /** - * Sets the text to be appended when null is added. - * - * @param nullText the null text, null means no append - * @return this, to enable chaining - */ - public StrBuilder setNullText(String nullText) { - if (nullText != null && nullText.isEmpty()) { - nullText = null; - } - this.nullText = nullText; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the length of the string builder. - * - * @return the length - */ - @Override - public int length() { - return size; - } - - /** - * Updates the length of the builder by either dropping the last characters or - * adding filler of Unicode zero. - * - * @param length the length to set to, must be zero or positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the length is negative - */ - public StrBuilder setLength(final int length) { - if (length < 0) { - throw new StringIndexOutOfBoundsException(length); - } - if (length < size) { - size = length; - } else if (length > size) { - ensureCapacity(length); - final int oldEnd = size; - final int newEnd = length; - size = length; - for (int i = oldEnd; i < newEnd; i++) { - buffer[i] = '\0'; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the current size of the internal character array buffer. - * - * @return the capacity - */ - public int capacity() { - return buffer.length; - } - - /** - * Checks the capacity and ensures that it is at least the size specified. - * - * @param capacity the capacity to ensure - * @return this, to enable chaining - */ - public StrBuilder ensureCapacity(final int capacity) { - if (capacity > buffer.length) { - final char[] old = buffer; - buffer = new char[capacity * 2]; - System.arraycopy(old, 0, buffer, 0, size); - } - return this; - } - - /** - * Minimizes the capacity to the actual length of the string. - * - * @return this, to enable chaining - */ - public StrBuilder minimizeCapacity() { - if (buffer.length > length()) { - final char[] old = buffer; - buffer = new char[length()]; - System.arraycopy(old, 0, buffer, 0, size); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the length of the string builder. - *

    - * This method is the same as {@link #length()} and is provided to match the API - * of Collections. - * - * @return the length - */ - public int size() { - return size; - } - - /** - * Checks is the string builder is empty (convenience Collections API style - * method). - *

    - * This method is the same as checking {@link #length()} and is provided to - * match the API of Collections. - * - * @return {@code true} if the size is {@code 0}. - */ - public boolean isEmpty() { - return size == 0; - } - - /** - * Checks is the string builder is not empty (convenience Collections API style - * method). - *

    - * This method is the same as checking {@link #length()} and is provided to - * match the API of Collections. - * - * @return {@code true} if the size is greater than {@code 0}. - * @since 3.12.0 - */ - public boolean isNotEmpty() { - return size > 0; - } - - /** - * Clears the string builder (convenience Collections API style method). - *

    - * This method does not reduce the size of the internal character buffer. To do - * that, call {@code clear()} followed by {@link #minimizeCapacity()}. - *

    - * This method is the same as {@link #setLength(int)} called with zero and is - * provided to match the API of Collections. - * - * @return this, to enable chaining - */ - public StrBuilder clear() { - size = 0; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the character at the specified index. - * - * @see #setCharAt(int, char) - * @see #deleteCharAt(int) - * @param index the index to retrieve, must be valid - * @return the character at the index - * @throws IndexOutOfBoundsException if the index is invalid - */ - @Override - public char charAt(final int index) { - if (index < 0 || index >= length()) { - throw new StringIndexOutOfBoundsException(index); - } - return buffer[index]; - } - - /** - * Sets the character at the specified index. - * - * @see #charAt(int) - * @see #deleteCharAt(int) - * @param index the index to set - * @param ch the new character - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder setCharAt(final int index, final char ch) { - if (index < 0 || index >= length()) { - throw new StringIndexOutOfBoundsException(index); - } - buffer[index] = ch; - return this; - } - - /** - * Deletes the character at the specified index. - * - * @see #charAt(int) - * @see #setCharAt(int, char) - * @param index the index to delete - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder deleteCharAt(final int index) { - if (index < 0 || index >= size) { - throw new StringIndexOutOfBoundsException(index); - } - deleteImpl(index, index + 1, 1); - return this; - } - - // ----------------------------------------------------------------------- - /** - * Copies the builder's character array into a new character array. - * - * @return a new array that represents the contents of the builder - */ - public char[] toCharArray() { - if (size == 0) { - return new char[0]; - } - final char[] chars = new char[size]; - System.arraycopy(buffer, 0, chars, 0, size); - return chars; - } - - /** - * Copies part of the builder's character array into a new character array. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return a new array that holds part of the contents of the builder - * @throws IndexOutOfBoundsException if startIndex is invalid, or if endIndex is - * invalid (but endIndex greater than size is - * valid) - */ - public char[] toCharArray(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - final int len = endIndex - startIndex; - if (len == 0) { - return new char[0]; - } - final char[] chars = new char[len]; - System.arraycopy(buffer, startIndex, chars, 0, len); - return chars; - } - - /** - * Copies the character array into the specified array. - * - * @param destination the destination array, null will cause an array to be - * created - * @return the input array, unless that was null or too small - */ - public char[] getChars(char[] destination) { - final int len = length(); - if (destination == null || destination.length < len) { - destination = new char[len]; - } - System.arraycopy(buffer, 0, destination, 0, len); - return destination; - } - - /** - * Copies the character array into the specified array. - * - * @param startIndex first index to copy, inclusive, must be valid - * @param endIndex last index, exclusive, must be valid - * @param destination the destination array, must not be null or too small - * @param destinationIndex the index to start copying in destination - * @throws NullPointerException if the array is null - * @throws IndexOutOfBoundsException if any index is invalid - */ - public void getChars(final int startIndex, final int endIndex, final char[] destination, - final int destinationIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex < 0 || endIndex > length()) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException("end < start"); - } - System.arraycopy(buffer, startIndex, destination, destinationIndex, endIndex - startIndex); - } - - // ----------------------------------------------------------------------- - /** - * If possible, reads chars from the provided {@link Readable} directly into - * underlying character buffer without making extra copies. - * - * @param readable object to read from - * @return the number of characters read - * @throws IOException if an I/O error occurs. - * - * @since 3.4 - * @see #appendTo(Appendable) - */ - public int readFrom(final Readable readable) throws IOException { - final int oldSize = size; - if (readable instanceof Reader) { - final Reader r = (Reader) readable; - ensureCapacity(size + 1); - int read; - while ((read = r.read(buffer, size, buffer.length - size)) != -1) { - size += read; - ensureCapacity(size + 1); - } - } else if (readable instanceof CharBuffer) { - final CharBuffer cb = (CharBuffer) readable; - final int remaining = cb.remaining(); - ensureCapacity(size + remaining); - cb.get(buffer, size, remaining); - size += remaining; - } else { - while (true) { - ensureCapacity(size + 1); - final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size); - final int read = readable.read(buf); - if (read == -1) { - break; - } - size += read; - } - } - return size - oldSize; - } - - // ----------------------------------------------------------------------- - /** - * Appends the new line string to this string builder. - *

    - * The new line string can be altered using {@link #setNewLineText(String)}. - * This might be used to force the output to always use Unix line endings even - * when on Windows. - * - * @return this, to enable chaining - */ - public StrBuilder appendNewLine() { - if (newLine == null) { - append(System.lineSeparator()); - return this; - } - return append(newLine); - } - - /** - * Appends the text representing {@code null} to this string builder. - * - * @return this, to enable chaining - */ - public StrBuilder appendNull() { - if (nullText == null) { - return this; - } - return append(nullText); - } - - /** - * Appends an object to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param obj the object to append - * @return this, to enable chaining - */ - public StrBuilder append(final Object obj) { - if (obj == null) { - return appendNull(); - } - if (obj instanceof CharSequence) { - return append((CharSequence) obj); - } - return append(obj.toString()); - } - - /** - * Appends a CharSequence to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param seq the CharSequence to append - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final CharSequence seq) { - if (seq == null) { - return appendNull(); - } - if (seq instanceof StrBuilder) { - return append((StrBuilder) seq); - } - if (seq instanceof StringBuilder) { - return append((StringBuilder) seq); - } - if (seq instanceof StringBuffer) { - return append((StringBuffer) seq); - } - if (seq instanceof CharBuffer) { - return append((CharBuffer) seq); - } - return append(seq.toString()); - } - - /** - * Appends part of a CharSequence to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param seq the CharSequence to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final CharSequence seq, final int startIndex, final int length) { - if (seq == null) { - return appendNull(); - } - return append(seq.toString(), startIndex, length); - } - - /** - * Appends a string to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string to append - * @return this, to enable chaining - */ - public StrBuilder append(final String str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a string to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final String str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Calls {@link String#format(String, Object...)} and appends the result. - * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining - * @see String#format(String, Object...) - * @since 3.2 - */ - public StrBuilder append(final String format, final Object... objs) { - return append(String.format(format, objs)); - } - - /** - * Appends the contents of a char buffer to this string builder. Appending null - * will call {@link #appendNull()}. - * - * @param buf the char buffer to append - * @return this, to enable chaining - * @since 3.4 - */ - public StrBuilder append(final CharBuffer buf) { - if (buf == null) { - return appendNull(); - } - if (buf.hasArray()) { - final int length = buf.remaining(); - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length); - size += length; - } else { - append(buf.toString()); - } - return this; - } - - /** - * Appends the contents of a char buffer to this string builder. Appending null - * will call {@link #appendNull()}. - * - * @param buf the char buffer to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.4 - */ - public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) { - if (buf == null) { - return appendNull(); - } - if (buf.hasArray()) { - final int totalLength = buf.remaining(); - if (startIndex < 0 || startIndex > totalLength) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > totalLength) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length); - size += length; - } else { - append(buf.toString(), startIndex, length); - } - return this; - } - - /** - * Appends a string buffer to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the string buffer to append - * @return this, to enable chaining - */ - public StrBuilder append(final StringBuffer str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a string buffer to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final StringBuffer str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends a StringBuilder to this string builder. Appending null will call - * {@link #appendNull()}. - * - * @param str the StringBuilder to append - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder append(final StringBuilder str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - str.getChars(0, strLen, buffer, len); - size += strLen; - } - return this; - } - - /** - * Appends part of a StringBuilder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the StringBuilder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder append(final StringBuilder str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends another string builder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - */ - public StrBuilder append(final StrBuilder str) { - if (str == null) { - return appendNull(); - } - final int strLen = str.length(); - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - System.arraycopy(str.buffer, 0, buffer, len, strLen); - size += strLen; - } - return this; - } - - /** - * Appends part of a string builder to this string builder. Appending null will - * call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final StrBuilder str, final int startIndex, final int length) { - if (str == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > str.length()) { - throw new StringIndexOutOfBoundsException("startIndex must be valid"); - } - if (length < 0 || (startIndex + length) > str.length()) { - throw new StringIndexOutOfBoundsException("length must be valid"); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - str.getChars(startIndex, startIndex + length, buffer, len); - size += length; - } - return this; - } - - /** - * Appends a char array to the string builder. Appending null will call - * {@link #appendNull()}. - * - * @param chars the char array to append - * @return this, to enable chaining - */ - public StrBuilder append(final char[] chars) { - if (chars == null) { - return appendNull(); - } - final int strLen = chars.length; - if (strLen > 0) { - final int len = length(); - ensureCapacity(len + strLen); - System.arraycopy(chars, 0, buffer, len, strLen); - size += strLen; - } - return this; - } - - /** - * Appends a char array to the string builder. Appending null will call - * {@link #appendNull()}. - * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - */ - public StrBuilder append(final char[] chars, final int startIndex, final int length) { - if (chars == null) { - return appendNull(); - } - if (startIndex < 0 || startIndex > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid startIndex: " + length); - } - if (length < 0 || (startIndex + length) > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid length: " + length); - } - if (length > 0) { - final int len = length(); - ensureCapacity(len + length); - System.arraycopy(chars, startIndex, buffer, len, length); - size += length; - } - return this; - } - - /** - * Appends a boolean value to the string builder. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final boolean value) { - if (value) { - ensureCapacity(size + 4); - buffer[size++] = 't'; - buffer[size++] = 'r'; - buffer[size++] = 'u'; - buffer[size++] = 'e'; - } else { - ensureCapacity(size + 5); - buffer[size++] = 'f'; - buffer[size++] = 'a'; - buffer[size++] = 'l'; - buffer[size++] = 's'; - buffer[size++] = 'e'; - } - return this; - } - - /** - * Appends a char value to the string builder. - * - * @param ch the value to append - * @return this, to enable chaining - * @since 3.0 - */ - @Override - public StrBuilder append(final char ch) { - final int len = length(); - ensureCapacity(len + 1); - buffer[size++] = ch; - return this; - } - - /** - * Appends an int value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final int value) { - return append(String.valueOf(value)); - } - - /** - * Appends a long value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final long value) { - return append(String.valueOf(value)); - } - - /** - * Appends a float value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final float value) { - return append(String.valueOf(value)); - } - - /** - * Appends a double value to the string builder using {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - */ - public StrBuilder append(final double value) { - return append(String.valueOf(value)); - } - - // ----------------------------------------------------------------------- - /** - * Appends an object followed by a new line to this string builder. Appending - * null will call {@link #appendNull()}. - * - * @param obj the object to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final Object obj) { - return append(obj).appendNewLine(); - } - - /** - * Appends a string followed by a new line to this string builder. Appending - * null will call {@link #appendNull()}. - * - * @param str the string to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final String str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final String str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Calls {@link String#format(String, Object...)} and appends the result. - * - * @param format the format string - * @param objs the objects to use in the format string - * @return {@code this} to enable chaining - * @see String#format(String, Object...) - * @since 3.2 - */ - public StrBuilder appendln(final String format, final Object... objs) { - return append(format, objs).appendNewLine(); - } - - /** - * Appends a string buffer followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string buffer to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StringBuffer str) { - return append(str).appendNewLine(); - } - - /** - * Appends a string builder followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder appendln(final StringBuilder str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string builder followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 3.2 - */ - public StrBuilder appendln(final StringBuilder str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends part of a string buffer followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StringBuffer str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends another string builder followed by a new line to this string builder. - * Appending null will call {@link #appendNull()}. - * - * @param str the string builder to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StrBuilder str) { - return append(str).appendNewLine(); - } - - /** - * Appends part of a string builder followed by a new line to this string - * builder. Appending null will call {@link #appendNull()}. - * - * @param str the string to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final StrBuilder str, final int startIndex, final int length) { - return append(str, startIndex, length).appendNewLine(); - } - - /** - * Appends a char array followed by a new line to the string builder. Appending - * null will call {@link #appendNull()}. - * - * @param chars the char array to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char[] chars) { - return append(chars).appendNewLine(); - } - - /** - * Appends a char array followed by a new line to the string builder. Appending - * null will call {@link #appendNull()}. - * - * @param chars the char array to append - * @param startIndex the start index, inclusive, must be valid - * @param length the length to append, must be valid - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char[] chars, final int startIndex, final int length) { - return append(chars, startIndex, length).appendNewLine(); - } - - /** - * Appends a boolean value followed by a new line to the string builder. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final boolean value) { - return append(value).appendNewLine(); - } - - /** - * Appends a char value followed by a new line to the string builder. - * - * @param ch the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final char ch) { - return append(ch).appendNewLine(); - } - - /** - * Appends an int value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final int value) { - return append(value).appendNewLine(); - } - - /** - * Appends a long value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final long value) { - return append(value).appendNewLine(); - } - - /** - * Appends a float value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final float value) { - return append(value).appendNewLine(); - } - - /** - * Appends a double value followed by a new line to the string builder using - * {@code String.valueOf}. - * - * @param value the value to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendln(final double value) { - return append(value).appendNewLine(); - } - - // ----------------------------------------------------------------------- - /** - * Appends each item in an array to the builder without any separators. - * Appending a null array will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param the element type - * @param array the array to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(@SuppressWarnings("unchecked") final T... array) { - /* - * @SuppressWarnings used to hide warning about vararg usage. We cannot - * use @SafeVarargs, since this method is not final. Using @SuppressWarnings is - * fine, because it isn't inherited by subclasses, so each subclass must vouch - * for itself whether its use of 'array' is safe. - */ - if (array.length > 0) { - for (final Object element : array) { - append(element); - } - } - return this; - } - - /** - * Appends each item in an iterable to the builder without any separators. - * Appending a null iterable will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param iterable the iterable to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(final Iterable iterable) { - if (iterable != null) { - for (final Object o : iterable) { - append(o); - } - } - return this; - } - - /** - * Appends each item in an iterator to the builder without any separators. - * Appending a null iterator will have no effect. Each object is appended using - * {@link #append(Object)}. - * - * @param it the iterator to append - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendAll(final Iterator it) { - if (it != null) { - while (it.hasNext()) { - append(it.next()); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends an array placing separators between each value, but not before the - * first or after the last. Appending a null array will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param array the array to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Object[] array, final String separator) { - if (array != null && array.length > 0) { - final String sep = Objects.toString(separator, ""); - append(array[0]); - for (int i = 1; i < array.length; i++) { - append(sep); - append(array[i]); - } - } - return this; - } - - /** - * Appends an iterable placing separators between each value, but not before the - * first or after the last. Appending a null iterable will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param iterable the iterable to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Iterable iterable, final String separator) { - if (iterable != null) { - final String sep = Objects.toString(separator, ""); - final Iterator it = iterable.iterator(); - while (it.hasNext()) { - append(it.next()); - if (it.hasNext()) { - append(sep); - } - } - } - return this; - } - - /** - * Appends an iterator placing separators between each value, but not before the - * first or after the last. Appending a null iterator will have no effect. Each - * object is appended using {@link #append(Object)}. - * - * @param it the iterator to append - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - */ - public StrBuilder appendWithSeparators(final Iterator it, final String separator) { - if (it != null) { - final String sep = Objects.toString(separator, ""); - while (it.hasNext()) { - append(it.next()); - if (it.hasNext()) { - append(sep); - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends a separator if the builder is currently non-empty. Appending a null - * separator will have no effect. The separator is appended using - * {@link #append(String)}. - *

    - * This method is useful for adding a separator each time around the loop except - * the first. - * - *

    -	 * for (Iterator it = list.iterator(); it.hasNext();) {
    -	 * 	appendSeparator(",");
    -	 * 	append(it.next());
    -	 * }
    -	 * 
    - * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use, null means no separator - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final String separator) { - return appendSeparator(separator, null); - } - - /** - * Appends one of both separators to the StrBuilder. If the builder is currently - * empty it will append the defaultIfEmpty-separator Otherwise it will append - * the standard-separator - * - * Appending a null separator will have no effect. The separator is appended - * using {@link #append(String)}. - *

    - * This method is for example useful for constructing queries - * - *

    -	 * StrBuilder whereClause = new StrBuilder();
    -	 * if (searchCommand.getPriority() != null) {
    -	 *  whereClause.appendSeparator(" and", " where");
    -	 *  whereClause.append(" priority = ?")
    -	 * }
    -	 * if (searchCommand.getComponent() != null) {
    -	 *  whereClause.appendSeparator(" and", " where");
    -	 *  whereClause.append(" component = ?")
    -	 * }
    -	 * selectClause.append(whereClause)
    -	 * 
    - * - * @param standard the separator if builder is not empty, null means no - * separator - * @param defaultIfEmpty the separator if builder is empty, null means no - * separator - * @return this, to enable chaining - * @since 2.5 - */ - public StrBuilder appendSeparator(final String standard, final String defaultIfEmpty) { - final String str = isEmpty() ? defaultIfEmpty : standard; - if (str != null) { - append(str); - } - return this; - } - - /** - * Appends a separator if the builder is currently non-empty. The separator is - * appended using {@link #append(char)}. - *

    - * This method is useful for adding a separator each time around the loop except - * the first. - * - *

    -	 * for (Iterator it = list.iterator(); it.hasNext();) {
    -	 * 	appendSeparator(',');
    -	 * 	append(it.next());
    -	 * }
    -	 * 
    - * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final char separator) { - if (isNotEmpty()) { - append(separator); - } - return this; - } - - /** - * Append one of both separators to the builder If the builder is currently - * empty it will append the defaultIfEmpty-separator Otherwise it will append - * the standard-separator - * - * The separator is appended using {@link #append(char)}. - * - * @param standard the separator if builder is not empty - * @param defaultIfEmpty the separator if builder is empty - * @return this, to enable chaining - * @since 2.5 - */ - public StrBuilder appendSeparator(final char standard, final char defaultIfEmpty) { - if (isNotEmpty()) { - append(standard); - } else { - append(defaultIfEmpty); - } - return this; - } - - /** - * Appends a separator to the builder if the loop index is greater than zero. - * Appending a null separator will have no effect. The separator is appended - * using {@link #append(String)}. - *

    - * This method is useful for adding a separator each time around the loop except - * the first. - *

    - * - *
    -	 * for (int i = 0; i < list.size(); i++) {
    -	 * 	appendSeparator(",", i);
    -	 * 	append(list.get(i));
    -	 * }
    -	 * 
    - * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use, null means no separator - * @param loopIndex the loop index - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final String separator, final int loopIndex) { - if (separator != null && loopIndex > 0) { - append(separator); - } - return this; - } - - /** - * Appends a separator to the builder if the loop index is greater than zero. - * The separator is appended using {@link #append(char)}. - *

    - * This method is useful for adding a separator each time around the loop except - * the first. - *

    - * - *
    -	 * for (int i = 0; i < list.size(); i++) {
    -	 * 	appendSeparator(",", i);
    -	 * 	append(list.get(i));
    -	 * }
    -	 * 
    - * - * Note that for this simple example, you should use - * {@link #appendWithSeparators(Iterable, String)}. - * - * @param separator the separator to use - * @param loopIndex the loop index - * @return this, to enable chaining - * @since 2.3 - */ - public StrBuilder appendSeparator(final char separator, final int loopIndex) { - if (loopIndex > 0) { - append(separator); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends the pad character to the builder the specified number of times. - * - * @param length the length to append, negative means no append - * @param padChar the character to append - * @return this, to enable chaining - */ - public StrBuilder appendPadding(final int length, final char padChar) { - if (length >= 0) { - ensureCapacity(size + length); - for (int i = 0; i < length; i++) { - buffer[size++] = padChar; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Appends an object to the builder padding on the left to a fixed width. The - * {@code toString} of the object is used. If the object is larger than the - * length, the left hand side is lost. If the object is null, the null text - * value is used. - * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadLeft(final Object obj, final int width, final char padChar) { - if (width > 0) { - ensureCapacity(size + width); - String str = (obj == null ? getNullText() : obj.toString()); - if (str == null) { - str = ""; - } - final int strLen = str.length(); - if (strLen >= width) { - str.getChars(strLen - width, strLen, buffer, size); - } else { - final int padLen = width - strLen; - for (int i = 0; i < padLen; i++) { - buffer[size + i] = padChar; - } - str.getChars(0, strLen, buffer, size + padLen); - } - size += width; - } - return this; - } - - /** - * Appends an object to the builder padding on the left to a fixed width. The - * {@code String.valueOf} of the {@code int} value is used. If the formatted - * value is larger than the length, the left hand side is lost. - * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadLeft(final int value, final int width, final char padChar) { - return appendFixedWidthPadLeft(String.valueOf(value), width, padChar); - } - - /** - * Appends an object to the builder padding on the right to a fixed length. The - * {@code toString} of the object is used. If the object is larger than the - * length, the right hand side is lost. If the object is null, null text value - * is used. - * - * @param obj the object to append, null uses null text - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadRight(final Object obj, final int width, final char padChar) { - if (width > 0) { - ensureCapacity(size + width); - String str = (obj == null ? getNullText() : obj.toString()); - if (str == null) { - str = ""; - } - final int strLen = str.length(); - if (strLen >= width) { - str.getChars(0, width, buffer, size); - } else { - final int padLen = width - strLen; - str.getChars(0, strLen, buffer, size); - for (int i = 0; i < padLen; i++) { - buffer[size + strLen + i] = padChar; - } - } - size += width; - } - return this; - } - - /** - * Appends an object to the builder padding on the right to a fixed length. The - * {@code String.valueOf} of the {@code int} value is used. If the object is - * larger than the length, the right hand side is lost. - * - * @param value the value to append - * @param width the fixed field width, zero or negative has no effect - * @param padChar the pad character to use - * @return this, to enable chaining - */ - public StrBuilder appendFixedWidthPadRight(final int value, final int width, final char padChar) { - return appendFixedWidthPadRight(String.valueOf(value), width, padChar); - } - - // ----------------------------------------------------------------------- - /** - * Inserts the string representation of an object into this builder. Inserting - * null will use the stored null text value. - * - * @param index the index to add at, must be valid - * @param obj the object to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final Object obj) { - if (obj == null) { - return insert(index, nullText); - } - return insert(index, obj.toString()); - } - - /** - * Inserts the string into this builder. Inserting null will use the stored null - * text value. - * - * @param index the index to add at, must be valid - * @param str the string to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, String str) { - validateIndex(index); - if (str == null) { - str = nullText; - } - if (str != null) { - final int strLen = str.length(); - if (strLen > 0) { - final int newSize = size + strLen; - ensureCapacity(newSize); - System.arraycopy(buffer, index, buffer, index + strLen, size - index); - size = newSize; - str.getChars(0, strLen, buffer, index); - } - } - return this; - } - - /** - * Inserts the character array into this builder. Inserting null will use the - * stored null text value. - * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final char[] chars) { - validateIndex(index); - if (chars == null) { - return insert(index, nullText); - } - final int len = chars.length; - if (len > 0) { - ensureCapacity(size + len); - System.arraycopy(buffer, index, buffer, index + len, size - index); - System.arraycopy(chars, 0, buffer, index, len); - size += len; - } - return this; - } - - /** - * Inserts part of the character array into this builder. Inserting null will - * use the stored null text value. - * - * @param index the index to add at, must be valid - * @param chars the char array to insert - * @param offset the offset into the character array to start at, must be valid - * @param length the length of the character array part to copy, must be - * positive - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid - */ - public StrBuilder insert(final int index, final char[] chars, final int offset, final int length) { - validateIndex(index); - if (chars == null) { - return insert(index, nullText); - } - if (offset < 0 || offset > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid offset: " + offset); - } - if (length < 0 || offset + length > chars.length) { - throw new StringIndexOutOfBoundsException("Invalid length: " + length); - } - if (length > 0) { - ensureCapacity(size + length); - System.arraycopy(buffer, index, buffer, index + length, size - index); - System.arraycopy(chars, offset, buffer, index, length); - size += length; - } - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(int index, final boolean value) { - validateIndex(index); - if (value) { - ensureCapacity(size + 4); - System.arraycopy(buffer, index, buffer, index + 4, size - index); - buffer[index++] = 't'; - buffer[index++] = 'r'; - buffer[index++] = 'u'; - buffer[index] = 'e'; - size += 4; - } else { - ensureCapacity(size + 5); - System.arraycopy(buffer, index, buffer, index + 5, size - index); - buffer[index++] = 'f'; - buffer[index++] = 'a'; - buffer[index++] = 'l'; - buffer[index++] = 's'; - buffer[index] = 'e'; - size += 5; - } - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final char value) { - validateIndex(index); - ensureCapacity(size + 1); - System.arraycopy(buffer, index, buffer, index + 1, size - index); - buffer[index] = value; - size++; - return this; - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final int value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final long value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final float value) { - return insert(index, String.valueOf(value)); - } - - /** - * Inserts the value into this builder. - * - * @param index the index to add at, must be valid - * @param value the value to insert - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder insert(final int index, final double value) { - return insert(index, String.valueOf(value)); - } - - // ----------------------------------------------------------------------- - /** - * Internal method to delete a range without validation. - * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param len the length, must be valid - * @throws IndexOutOfBoundsException if any index is invalid - */ - private void deleteImpl(final int startIndex, final int endIndex, final int len) { - System.arraycopy(buffer, endIndex, buffer, startIndex, size - endIndex); - size -= len; - } - - /** - * Deletes the characters between the two specified indices. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder delete(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - final int len = endIndex - startIndex; - if (len > 0) { - deleteImpl(startIndex, endIndex, len); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes the character wherever it occurs in the builder. - * - * @param ch the character to delete - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final char ch) { - for (int i = 0; i < size; i++) { - if (buffer[i] == ch) { - final int start = i; - while (++i < size) { - if (buffer[i] != ch) { - break; - } - } - final int len = i - start; - deleteImpl(start, i, len); - i -= len; - } - } - return this; - } - - /** - * Deletes the character wherever it occurs in the builder. - * - * @param ch the character to delete - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final char ch) { - for (int i = 0; i < size; i++) { - if (buffer[i] == ch) { - deleteImpl(i, i + 1, 1); - break; - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes the string wherever it occurs in the builder. - * - * @param str the string to delete, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final String str) { - final int len = (str == null ? 0 : str.length()); - if (len > 0) { - int index = indexOf(str, 0); - while (index >= 0) { - deleteImpl(index, index + len, len); - index = indexOf(str, index); - } - } - return this; - } - - /** - * Deletes the string wherever it occurs in the builder. - * - * @param str the string to delete, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final String str) { - final int len = (str == null ? 0 : str.length()); - if (len > 0) { - final int index = indexOf(str, 0); - if (index >= 0) { - deleteImpl(index, index + len, len); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Deletes all parts of the builder that the matcher matches. - *

    - * Matchers can be used to perform advanced deletion behavior. For example you - * could write a matcher to delete all occurrences where the character 'a' is - * followed by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteAll(final StrMatcher matcher) { - return replace(matcher, null, 0, size, -1); - } - - /** - * Deletes the first match within the builder using the specified matcher. - *

    - * Matchers can be used to perform advanced deletion behavior. For example you - * could write a matcher to delete where the character 'a' is followed by a - * number. - * - * @param matcher the matcher to use to find the deletion, null causes no action - * @return this, to enable chaining - */ - public StrBuilder deleteFirst(final StrMatcher matcher) { - return replace(matcher, null, 0, size, 1); - } - - // ----------------------------------------------------------------------- - /** - * Internal method to delete a range without validation. - * - * @param startIndex the start index, must be valid - * @param endIndex the end index (exclusive), must be valid - * @param removeLen the length to remove (endIndex - startIndex), must be valid - * @param insertStr the string to replace with, null means delete range - * @param insertLen the length of the insert string, must be valid - * @throws IndexOutOfBoundsException if any index is invalid - */ - private void replaceImpl(final int startIndex, final int endIndex, final int removeLen, final String insertStr, - final int insertLen) { - final int newSize = size - removeLen + insertLen; - if (insertLen != removeLen) { - ensureCapacity(newSize); - System.arraycopy(buffer, endIndex, buffer, startIndex + insertLen, size - endIndex); - size = newSize; - } - if (insertLen > 0) { - insertStr.getChars(0, insertLen, buffer, startIndex); - } - } - - /** - * Replaces a portion of the string builder with another string. The length of - * the inserted string does not have to match the removed length. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @param replaceStr the string to replace with, null means delete range - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if the index is invalid - */ - public StrBuilder replace(final int startIndex, int endIndex, final String replaceStr) { - endIndex = validateRange(startIndex, endIndex); - final int insertLen = (replaceStr == null ? 0 : replaceStr.length()); - replaceImpl(startIndex, endIndex, endIndex - startIndex, replaceStr, insertLen); - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces the search character with the replace character throughout the - * builder. - * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final char search, final char replace) { - if (search != replace) { - for (int i = 0; i < size; i++) { - if (buffer[i] == search) { - buffer[i] = replace; - } - } - } - return this; - } - - /** - * Replaces the first instance of the search character with the replace - * character in the builder. - * - * @param search the search character - * @param replace the replace character - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final char search, final char replace) { - if (search != replace) { - for (int i = 0; i < size; i++) { - if (buffer[i] == search) { - buffer[i] = replace; - break; - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces the search string with the replace string throughout the builder. - * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final String searchStr, final String replaceStr) { - final int searchLen = (searchStr == null ? 0 : searchStr.length()); - if (searchLen > 0) { - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - int index = indexOf(searchStr, 0); - while (index >= 0) { - replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen); - index = indexOf(searchStr, index + replaceLen); - } - } - return this; - } - - /** - * Replaces the first instance of the search string with the replace string. - * - * @param searchStr the search string, null causes no action to occur - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final String searchStr, final String replaceStr) { - final int searchLen = (searchStr == null ? 0 : searchStr.length()); - if (searchLen > 0) { - final int index = indexOf(searchStr, 0); - if (index >= 0) { - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - replaceImpl(index, index + searchLen, searchLen, replaceStr, replaceLen); - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Replaces all matches within the builder with the replace string. - *

    - * Matchers can be used to perform advanced replace behavior. For example you - * could write a matcher to replace all occurrences where the character 'a' is - * followed by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceAll(final StrMatcher matcher, final String replaceStr) { - return replace(matcher, replaceStr, 0, size, -1); - } - - /** - * Replaces the first match within the builder with the replace string. - *

    - * Matchers can be used to perform advanced replace behavior. For example you - * could write a matcher to replace where the character 'a' is followed by a - * number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the replace string, null is equivalent to an empty string - * @return this, to enable chaining - */ - public StrBuilder replaceFirst(final StrMatcher matcher, final String replaceStr) { - return replace(matcher, replaceStr, 0, size, 1); - } - - // ----------------------------------------------------------------------- - /** - * Advanced search and replaces within the builder using a matcher. - *

    - * Matchers can be used to perform advanced behavior. For example you could - * write a matcher to delete all occurrences where the character 'a' is followed - * by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the string to replace the match with, null is a delete - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if - * too large it is treated as end of string - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if start index is invalid - */ - public StrBuilder replace(final StrMatcher matcher, final String replaceStr, final int startIndex, int endIndex, - final int replaceCount) { - endIndex = validateRange(startIndex, endIndex); - return replaceImpl(matcher, replaceStr, startIndex, endIndex, replaceCount); - } - - /** - * Replaces within the builder using a matcher. - *

    - * Matchers can be used to perform advanced behavior. For example you could - * write a matcher to delete all occurrences where the character 'a' is followed - * by a number. - * - * @param matcher the matcher to use to find the deletion, null causes no - * action - * @param replaceStr the string to replace the match with, null is a delete - * @param from the start index, must be valid - * @param to the end index (exclusive), must be valid - * @param replaceCount the number of times to replace, -1 for replace all - * @return this, to enable chaining - * @throws IndexOutOfBoundsException if any index is invalid - */ - private StrBuilder replaceImpl(final StrMatcher matcher, final String replaceStr, final int from, int to, - int replaceCount) { - if (matcher == null || size == 0) { - return this; - } - final int replaceLen = (replaceStr == null ? 0 : replaceStr.length()); - for (int i = from; i < to && replaceCount != 0; i++) { - final char[] buf = buffer; - final int removeLen = matcher.isMatch(buf, i, from, to); - if (removeLen > 0) { - replaceImpl(i, i + removeLen, removeLen, replaceStr, replaceLen); - to = to - removeLen + replaceLen; - i = i + replaceLen - 1; - if (replaceCount > 0) { - replaceCount--; - } - } - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Reverses the string builder placing each character in the opposite index. - * - * @return this, to enable chaining - */ - public StrBuilder reverse() { - if (size == 0) { - return this; - } - - final int half = size / 2; - final char[] buf = buffer; - for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) { - final char swap = buf[leftIdx]; - buf[leftIdx] = buf[rightIdx]; - buf[rightIdx] = swap; - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Trims the builder by removing characters less than or equal to a space from - * the beginning and end. - * - * @return this, to enable chaining - */ - public StrBuilder trim() { - if (size == 0) { - return this; - } - int len = size; - final char[] buf = buffer; - int pos = 0; - while (pos < len && buf[pos] <= ' ') { - pos++; - } - while (pos < len && buf[len - 1] <= ' ') { - len--; - } - if (len < size) { - delete(len, size); - } - if (pos > 0) { - delete(0, pos); - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Checks whether this builder starts with the specified string. - *

    - * Note that this method handles null input quietly, unlike String. - * - * @param str the string to search for, null returns false - * @return true if the builder starts with the string - */ - public boolean startsWith(final String str) { - if (str == null) { - return false; - } - final int len = str.length(); - if (len == 0) { - return true; - } - if (len > size) { - return false; - } - for (int i = 0; i < len; i++) { - if (buffer[i] != str.charAt(i)) { - return false; - } - } - return true; - } - - /** - * Checks whether this builder ends with the specified string. - *

    - * Note that this method handles null input quietly, unlike String. - * - * @param str the string to search for, null returns false - * @return true if the builder ends with the string - */ - public boolean endsWith(final String str) { - if (str == null) { - return false; - } - final int len = str.length(); - if (len == 0) { - return true; - } - if (len > size) { - return false; - } - int pos = size - len; - for (int i = 0; i < len; i++, pos++) { - if (buffer[pos] != str.charAt(i)) { - return false; - } - } - return true; - } - - // ----------------------------------------------------------------------- - /** - * {@inheritDoc} - * - * @since 3.0 - */ - @Override - public CharSequence subSequence(final int startIndex, final int endIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex > size) { - throw new StringIndexOutOfBoundsException(endIndex); - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException(endIndex - startIndex); - } - return substring(startIndex, endIndex); - } - - /** - * Extracts a portion of this string builder as a string. - * - * @param start the start index, inclusive, must be valid - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - public String substring(final int start) { - return substring(start, size); - } - - /** - * Extracts a portion of this string builder as a string. - *

    - * Note: This method treats an endIndex greater than the length of the builder - * as equal to the length of the builder, and continues without error, unlike - * StringBuffer or String. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - public String substring(final int startIndex, int endIndex) { - endIndex = validateRange(startIndex, endIndex); - return new String(buffer, startIndex, endIndex - startIndex); - } - - /** - * Extracts the leftmost characters from the string builder without throwing an - * exception. - *

    - * This method extracts the left {@code length} characters from the builder. If - * this many characters are not available, the whole builder is returned. Thus - * the returned string may be shorter than the length requested. - * - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String leftString(final int length) { - if (length <= 0) { - return ""; - } else if (length >= size) { - return new String(buffer, 0, size); - } else { - return new String(buffer, 0, length); - } - } - - /** - * Extracts the rightmost characters from the string builder without throwing an - * exception. - *

    - * This method extracts the right {@code length} characters from the builder. If - * this many characters are not available, the whole builder is returned. Thus - * the returned string may be shorter than the length requested. - * - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String rightString(final int length) { - if (length <= 0) { - return ""; - } else if (length >= size) { - return new String(buffer, 0, size); - } else { - return new String(buffer, size - length, length); - } - } - - /** - * Extracts some characters from the middle of the string builder without - * throwing an exception. - *

    - * This method extracts {@code length} characters from the builder at the - * specified index. If the index is negative it is treated as zero. If the index - * is greater than the builder size, it is treated as the builder size. If the - * length is negative, the empty string is returned. If insufficient characters - * are available in the builder, as much as possible is returned. Thus the - * returned string may be shorter than the length requested. - * - * @param index the index to start at, negative means zero - * @param length the number of characters to extract, negative returns empty - * string - * @return the new string - */ - public String midString(int index, final int length) { - if (index < 0) { - index = 0; - } - if (length <= 0 || index >= size) { - return ""; - } - if (size <= index + length) { - return new String(buffer, index, size - index); - } - return new String(buffer, index, length); - } - - // ----------------------------------------------------------------------- - /** - * Checks if the string builder contains the specified char. - * - * @param ch the character to find - * @return true if the builder contains the character - */ - public boolean contains(final char ch) { - final char[] thisBuf = buffer; - for (int i = 0; i < this.size; i++) { - if (thisBuf[i] == ch) { - return true; - } - } - return false; - } - - /** - * Checks if the string builder contains the specified string. - * - * @param str the string to find - * @return true if the builder contains the string - */ - public boolean contains(final String str) { - return indexOf(str, 0) >= 0; - } - - /** - * Checks if the string builder contains a string matched using the specified - * matcher. - *

    - * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to search for the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return true if the matcher finds a match in the builder - */ - public boolean contains(final StrMatcher matcher) { - return indexOf(matcher, 0) >= 0; - } - - // ----------------------------------------------------------------------- - /** - * Searches the string builder to find the first reference to the specified - * char. - * - * @param ch the character to find - * @return the first index of the character, or -1 if not found - */ - public int indexOf(final char ch) { - return indexOf(ch, 0); - } - - /** - * Searches the string builder to find the first reference to the specified - * char. - * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index of the character, or -1 if not found - */ - public int indexOf(final char ch, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (startIndex >= size) { - return -1; - } - final char[] thisBuf = buffer; - for (int i = startIndex; i < size; i++) { - if (thisBuf[i] == ch) { - return i; - } - } - return -1; - } - - /** - * Searches the string builder to find the first reference to the specified - * string. - *

    - * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @return the first index of the string, or -1 if not found - */ - public int indexOf(final String str) { - return indexOf(str, 0); - } - - /** - * Searches the string builder to find the first reference to the specified - * string starting searching from the given index. - *

    - * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index of the string, or -1 if not found - */ - public int indexOf(final String str, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (str == null || startIndex >= size) { - return -1; - } - final int strLen = str.length(); - if (strLen == 1) { - return indexOf(str.charAt(0), startIndex); - } - if (strLen == 0) { - return startIndex; - } - if (strLen > size) { - return -1; - } - final char[] thisBuf = buffer; - final int len = size - strLen + 1; - outer: for (int i = startIndex; i < len; i++) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != thisBuf[i + j]) { - continue outer; - } - } - return i; - } - return -1; - } - - /** - * Searches the string builder using the matcher to find the first match. - *

    - * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return the first index matched, or -1 if not found - */ - public int indexOf(final StrMatcher matcher) { - return indexOf(matcher, 0); - } - - /** - * Searches the string builder using the matcher to find the first match - * searching from the given index. - *

    - * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the first index matched, or -1 if not found - */ - public int indexOf(final StrMatcher matcher, int startIndex) { - startIndex = (Math.max(startIndex, 0)); - if (matcher == null || startIndex >= size) { - return -1; - } - final int len = size; - final char[] buf = buffer; - for (int i = startIndex; i < len; i++) { - if (matcher.isMatch(buf, i, startIndex, len) > 0) { - return i; - } - } - return -1; - } - - // ----------------------------------------------------------------------- - /** - * Searches the string builder to find the last reference to the specified char. - * - * @param ch the character to find - * @return the last index of the character, or -1 if not found - */ - public int lastIndexOf(final char ch) { - return lastIndexOf(ch, size - 1); - } - - /** - * Searches the string builder to find the last reference to the specified char. - * - * @param ch the character to find - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index of the character, or -1 if not found - */ - public int lastIndexOf(final char ch, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (startIndex < 0) { - return -1; - } - for (int i = startIndex; i >= 0; i--) { - if (buffer[i] == ch) { - return i; - } - } - return -1; - } - - /** - * Searches the string builder to find the last reference to the specified - * string. - *

    - * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @return the last index of the string, or -1 if not found - */ - public int lastIndexOf(final String str) { - return lastIndexOf(str, size - 1); - } - - /** - * Searches the string builder to find the last reference to the specified - * string starting searching from the given index. - *

    - * Note that a null input string will return -1, whereas the JDK throws an - * exception. - * - * @param str the string to find, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index of the string, or -1 if not found - */ - public int lastIndexOf(final String str, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (str == null || startIndex < 0) { - return -1; - } - final int strLen = str.length(); - if (strLen > 0 && strLen <= size) { - if (strLen == 1) { - return lastIndexOf(str.charAt(0), startIndex); - } - - outer: for (int i = startIndex - strLen + 1; i >= 0; i--) { - for (int j = 0; j < strLen; j++) { - if (str.charAt(j) != buffer[i + j]) { - continue outer; - } - } - return i; - } - - } else if (strLen == 0) { - return startIndex; - } - return -1; - } - - /** - * Searches the string builder using the matcher to find the last match. - *

    - * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @return the last index matched, or -1 if not found - */ - public int lastIndexOf(final StrMatcher matcher) { - return lastIndexOf(matcher, size); - } - - /** - * Searches the string builder using the matcher to find the last match - * searching from the given index. - *

    - * Matchers can be used to perform advanced searching behavior. For example you - * could write a matcher to find the character 'a' followed by a number. - * - * @param matcher the matcher to use, null returns -1 - * @param startIndex the index to start at, invalid index rounded to edge - * @return the last index matched, or -1 if not found - */ - public int lastIndexOf(final StrMatcher matcher, int startIndex) { - startIndex = (startIndex >= size ? size - 1 : startIndex); - if (matcher == null || startIndex < 0) { - return -1; - } - final char[] buf = buffer; - final int endIndex = startIndex + 1; - for (int i = startIndex; i >= 0; i--) { - if (matcher.isMatch(buf, i, 0, endIndex) > 0) { - return i; - } - } - return -1; - } - - // ----------------------------------------------------------------------- - /** - * Creates a tokenizer that can tokenize the contents of this builder. - *

    - * This method allows the contents of this builder to be tokenized. The - * tokenizer will be setup by default to tokenize on space, tab, newline and - * formfeed (as per StringTokenizer). These values can be changed on the - * tokenizer class, before retrieving the tokens. - *

    - * The returned tokenizer is linked to this builder. You may intermix calls to - * the builder and tokenizer within certain limits, however there is no - * synchronization. Once the tokenizer has been used once, it must be - * {@link StrTokenizer#reset() reset} to pickup the latest changes in the - * builder. For example: - * - *

    -	 * StrBuilder b = new StrBuilder();
    -	 * b.append("a b ");
    -	 * StrTokenizer t = b.asTokenizer();
    -	 * String[] tokens1 = t.getTokenArray(); // returns a,b
    -	 * b.append("c d ");
    -	 * String[] tokens2 = t.getTokenArray(); // returns a,b (c and d ignored)
    -	 * t.reset(); // reset causes builder changes to be picked up
    -	 * String[] tokens3 = t.getTokenArray(); // returns a,b,c,d
    -	 * 
    - * - * In addition to simply intermixing appends and tokenization, you can also call - * the set methods on the tokenizer to alter how it tokenizes. Just remember to - * call reset when you want to pickup builder changes. - *

    - * Calling {@link StrTokenizer#reset(String)} or - * {@link StrTokenizer#reset(char[])} with a non-null value will break the link - * with the builder. - * - * @return a tokenizer that is linked to this builder - */ - public StrTokenizer asTokenizer() { - return new StrBuilderTokenizer(); - } - - // ----------------------------------------------------------------------- - /** - * Gets the contents of this builder as a Reader. - *

    - * This method allows the contents of the builder to be read using any standard - * method that expects a Reader. - *

    - * To use, simply create a {@code StrBuilder}, populate it with data, call - * {@code asReader}, and then read away. - *

    - * The internal character array is shared between the builder and the reader. - * This allows you to append to the builder after creating the reader, and the - * changes will be picked up. Note however, that no synchronization occurs, so - * you must perform all operations with the builder and the reader in one - * thread. - *

    - * The returned reader supports marking, and ignores the flush method. - * - * @return a reader that reads from this builder - */ - public Reader asReader() { - return new StrBuilderReader(); - } - - // ----------------------------------------------------------------------- - /** - * Gets this builder as a Writer that can be written to. - *

    - * This method allows you to populate the contents of the builder using any - * standard method that takes a Writer. - *

    - * To use, simply create a {@code StrBuilder}, call {@code asWriter}, and - * populate away. The data is available at any time using the methods of the - * {@code StrBuilder}. - *

    - * The internal character array is shared between the builder and the writer. - * This allows you to intermix calls that append to the builder and write using - * the writer and the changes will be occur correctly. Note however, that no - * synchronization occurs, so you must perform all operations with the builder - * and the writer in one thread. - *

    - * The returned writer ignores the close and flush methods. - * - * @return a writer that populates this builder - */ - public Writer asWriter() { - return new StrBuilderWriter(); - } - - /** - * Appends current contents of this {@code StrBuilder} to the provided - * {@link Appendable}. - *

    - * This method tries to avoid doing any extra copies of contents. - * - * @param appendable the appendable to append data to - * @throws IOException if an I/O error occurs - * - * @since 3.4 - * @see #readFrom(Readable) - */ - public void appendTo(final Appendable appendable) throws IOException { - if (appendable instanceof Writer) { - ((Writer) appendable).write(buffer, 0, size); - } else if (appendable instanceof StringBuilder) { - ((StringBuilder) appendable).append(buffer, 0, size); - } else if (appendable instanceof StringBuffer) { - ((StringBuffer) appendable).append(buffer, 0, size); - } else if (appendable instanceof CharBuffer) { - ((CharBuffer) appendable).put(buffer, 0, size); - } else { - appendable.append(this); - } - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content ignoring case. - * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - public boolean equalsIgnoreCase(final StrBuilder other) { - if (this == other) { - return true; - } - if (this.size != other.size) { - return false; - } - final char[] thisBuf = this.buffer; - final char[] otherBuf = other.buffer; - for (int i = size - 1; i >= 0; i--) { - final char c1 = thisBuf[i]; - final char c2 = otherBuf[i]; - if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2)) { - return false; - } - } - return true; - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content. - * - * @param other the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - public boolean equals(final StrBuilder other) { - if (this == other) { - return true; - } - if (other == null) { - return false; - } - if (this.size != other.size) { - return false; - } - final char[] thisBuf = this.buffer; - final char[] otherBuf = other.buffer; - for (int i = size - 1; i >= 0; i--) { - if (thisBuf[i] != otherBuf[i]) { - return false; - } - } - return true; - } - - /** - * Checks the contents of this builder against another to see if they contain - * the same character content. - * - * @param obj the object to check, null returns false - * @return true if the builders contain the same characters in the same order - */ - @Override - public boolean equals(final Object obj) { - return obj instanceof StrBuilder && equals((StrBuilder) obj); - } - - /** - * Gets a suitable hash code for this builder. - * - * @return a hash code - */ - @Override - public int hashCode() { - final char[] buf = buffer; - int hash = 0; - for (int i = size - 1; i >= 0; i--) { - hash = 31 * hash + buf[i]; - } - return hash; - } - - // ----------------------------------------------------------------------- - /** - * Gets a String version of the string builder, creating a new instance each - * time the method is called. - *

    - * Note that unlike StringBuffer, the string version returned is independent of - * the string builder. - * - * @return the builder as a String - */ - @Override - public String toString() { - return new String(buffer, 0, size); - } - - /** - * Gets a StringBuffer version of the string builder, creating a new instance - * each time the method is called. - * - * @return the builder as a StringBuffer - */ - public StringBuffer toStringBuffer() { - return new StringBuffer(size).append(buffer, 0, size); - } - - /** - * Gets a StringBuilder version of the string builder, creating a new instance - * each time the method is called. - * - * @return the builder as a StringBuilder - * @since 3.2 - */ - public StringBuilder toStringBuilder() { - return new StringBuilder(size).append(buffer, 0, size); - } - - /** - * Implement the {@link Builder} interface. - * - * @return the builder as a String - * @since 3.2 - * @see #toString() - */ - public String build() { - return toString(); - } - - // ----------------------------------------------------------------------- - /** - * Validates parameters defining a range of the builder. - * - * @param startIndex the start index, inclusive, must be valid - * @param endIndex the end index, exclusive, must be valid except that if too - * large it is treated as end of string - * @return the new string - * @throws IndexOutOfBoundsException if the index is invalid - */ - protected int validateRange(final int startIndex, int endIndex) { - if (startIndex < 0) { - throw new StringIndexOutOfBoundsException(startIndex); - } - if (endIndex > size) { - endIndex = size; - } - if (startIndex > endIndex) { - throw new StringIndexOutOfBoundsException("end < start"); - } - return endIndex; - } - - /** - * Validates parameters defining a single index in the builder. - * - * @param index the index, must be valid - * @throws IndexOutOfBoundsException if the index is invalid - */ - protected void validateIndex(final int index) { - if (index < 0 || index > size) { - throw new StringIndexOutOfBoundsException(index); - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a tokenizer. - */ - class StrBuilderTokenizer extends StrTokenizer { - - /** - * Default constructor. - */ - StrBuilderTokenizer() { - } - - /** {@inheritDoc} */ - @Override - protected List tokenize(final char[] chars, final int offset, final int count) { - if (chars == null) { - return super.tokenize(StrBuilder.this.buffer, 0, StrBuilder.this.size()); - } - return super.tokenize(chars, offset, count); - } - - /** {@inheritDoc} */ - @Override - public String getContent() { - final String str = super.getContent(); - if (str == null) { - return StrBuilder.this.toString(); - } - return str; - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a reader. - */ - class StrBuilderReader extends Reader { - /** The current stream position. */ - private int pos; - /** The last mark position. */ - private int mark; - - /** - * Default constructor. - */ - StrBuilderReader() { - } - - /** {@inheritDoc} */ - @Override - public void close() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public int read() { - if (ready() == false) { - return -1; - } - return StrBuilder.this.charAt(pos++); - } - - /** {@inheritDoc} */ - @Override - public int read(final char[] b, final int off, int len) { - if (off < 0 || len < 0 || off > b.length || (off + len) > b.length || (off + len) < 0) { - throw new IndexOutOfBoundsException(); - } - if (len == 0) { - return 0; - } - if (pos >= StrBuilder.this.size()) { - return -1; - } - if (pos + len > size()) { - len = StrBuilder.this.size() - pos; - } - StrBuilder.this.getChars(pos, pos + len, b, off); - pos += len; - return len; - } - - /** {@inheritDoc} */ - @Override - public long skip(long n) { - if (pos + n > StrBuilder.this.size()) { - n = StrBuilder.this.size() - pos; - } - if (n < 0) { - return 0; - } - pos += n; - return n; - } - - /** {@inheritDoc} */ - @Override - public boolean ready() { - return pos < StrBuilder.this.size(); - } - - /** {@inheritDoc} */ - @Override - public boolean markSupported() { - return true; - } - - /** {@inheritDoc} */ - @Override - public void mark(final int readAheadLimit) { - mark = pos; - } - - /** {@inheritDoc} */ - @Override - public void reset() { - pos = mark; - } - } - - // ----------------------------------------------------------------------- - /** - * Inner class to allow StrBuilder to operate as a writer. - */ - class StrBuilderWriter extends Writer { - - /** - * Default constructor. - */ - StrBuilderWriter() { - } - - /** {@inheritDoc} */ - @Override - public void close() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public void flush() { - // do nothing - } - - /** {@inheritDoc} */ - @Override - public void write(final int c) { - StrBuilder.this.append((char) c); - } - - /** {@inheritDoc} */ - @Override - public void write(final char[] cbuf) { - StrBuilder.this.append(cbuf); - } - - /** {@inheritDoc} */ - @Override - public void write(final char[] cbuf, final int off, final int len) { - StrBuilder.this.append(cbuf, off, len); - } - - /** {@inheritDoc} */ - @Override - public void write(final String str) { - StrBuilder.this.append(str); - } - - /** {@inheritDoc} */ - @Override - public void write(final String str, final int off, final int len) { - StrBuilder.this.append(str, off, len); - } - } - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrMatcher.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrMatcher.java deleted file mode 100644 index a20457a6..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrMatcher.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.repackage.lang3; - -import java.util.Arrays; - -/** - * A matcher class that can be queried to determine if a character array portion - * matches. - *

    - * This class comes complete with various factory methods. If these do not - * suffice, you can subclass and implement your own matcher. - * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * StringMatcherFactory instead - */ -//@Deprecated -public abstract class StrMatcher { - - /** - * Matches the comma character. - */ - private static final StrMatcher COMMA_MATCHER = new CharMatcher(','); - /** - * Matches the tab character. - */ - private static final StrMatcher TAB_MATCHER = new CharMatcher('\t'); - /** - * Matches the space character. - */ - private static final StrMatcher SPACE_MATCHER = new CharMatcher(' '); - /** - * Matches the same characters as StringTokenizer, namely space, tab, newline, - * formfeed. - */ - private static final StrMatcher SPLIT_MATCHER = new CharSetMatcher(" \t\n\r\f".toCharArray()); - /** - * Matches the String trim() whitespace characters. - */ - private static final StrMatcher TRIM_MATCHER = new TrimMatcher(); - /** - * Matches the double quote character. - */ - private static final StrMatcher SINGLE_QUOTE_MATCHER = new CharMatcher('\''); - /** - * Matches the double quote character. - */ - private static final StrMatcher DOUBLE_QUOTE_MATCHER = new CharMatcher('"'); - /** - * Matches the single or double quote character. - */ - private static final StrMatcher QUOTE_MATCHER = new CharSetMatcher("'\"".toCharArray()); - /** - * Matches no characters. - */ - private static final StrMatcher NONE_MATCHER = new NoMatcher(); - - // ----------------------------------------------------------------------- - - /** - * Returns a matcher which matches the comma character. - * - * @return a matcher for a comma - */ - public static StrMatcher commaMatcher() { - return COMMA_MATCHER; - } - - /** - * Returns a matcher which matches the tab character. - * - * @return a matcher for a tab - */ - public static StrMatcher tabMatcher() { - return TAB_MATCHER; - } - - /** - * Returns a matcher which matches the space character. - * - * @return a matcher for a space - */ - public static StrMatcher spaceMatcher() { - return SPACE_MATCHER; - } - - /** - * Matches the same characters as StringTokenizer, namely space, tab, newline - * and formfeed. - * - * @return the split matcher - */ - public static StrMatcher splitMatcher() { - return SPLIT_MATCHER; - } - - /** - * Matches the String trim() whitespace characters. - * - * @return the trim matcher - */ - public static StrMatcher trimMatcher() { - return TRIM_MATCHER; - } - - /** - * Returns a matcher which matches the single quote character. - * - * @return a matcher for a single quote - */ - public static StrMatcher singleQuoteMatcher() { - return SINGLE_QUOTE_MATCHER; - } - - /** - * Returns a matcher which matches the double quote character. - * - * @return a matcher for a double quote - */ - public static StrMatcher doubleQuoteMatcher() { - return DOUBLE_QUOTE_MATCHER; - } - - /** - * Returns a matcher which matches the single or double quote character. - * - * @return a matcher for a single or double quote - */ - public static StrMatcher quoteMatcher() { - return QUOTE_MATCHER; - } - - /** - * Matches no characters. - * - * @return a matcher that matches nothing - */ - public static StrMatcher noneMatcher() { - return NONE_MATCHER; - } - - /** - * Constructor that creates a matcher from a character. - * - * @param ch the character to match, must not be null - * @return a new Matcher for the given char - */ - public static StrMatcher charMatcher(final char ch) { - return new CharMatcher(ch); - } - - /** - * Constructor that creates a matcher from a set of characters. - * - * @param chars the characters to match, null or empty matches nothing - * @return a new matcher for the given char[] - */ - public static StrMatcher charSetMatcher(final char... chars) { - if (chars == null || chars.length == 0) { - return NONE_MATCHER; - } - if (chars.length == 1) { - return new CharMatcher(chars[0]); - } - return new CharSetMatcher(chars); - } - - /** - * Constructor that creates a matcher from a string representing a set of - * characters. - * - * @param chars the characters to match, null or empty matches nothing - * @return a new Matcher for the given characters - */ - public static StrMatcher charSetMatcher(final String chars) { - if (chars == null || chars.length() == 0) { - return NONE_MATCHER; - } - if (chars.length() == 1) { - return new CharMatcher(chars.charAt(0)); - } - return new CharSetMatcher(chars.toCharArray()); - } - - /** - * Constructor that creates a matcher from a string. - * - * @param str the string to match, null or empty matches nothing - * @return a new Matcher for the given String - */ - public static StrMatcher stringMatcher(final String str) { - if (str == null || str.length() == 0) { - return NONE_MATCHER; - } - return new StringMatcher(str); - } - - // ----------------------------------------------------------------------- - /** - * Constructor. - */ - protected StrMatcher() { - } - - /** - * Returns the number of matching characters, zero for no match. - *

    - * This method is called to check for a match. The parameter {@code pos} - * represents the current position to be checked in the string {@code buffer} (a - * character array which must not be changed). The API guarantees that - * {@code pos} is a valid index for {@code buffer}. - *

    - * The character array may be larger than the active area to be matched. Only - * values in the buffer between the specified indices may be accessed. - *

    - * The matching code may check one character or many. It may check characters - * preceding {@code pos} as well as those after, so long as no checks exceed the - * bounds specified. - *

    - * It must return zero for no match, or a positive number if a match was found. - * The number indicates the number of characters that matched. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index (exclusive) of the active buffer, valid for - * buffer - * @return the number of matching characters, zero for no match - */ - public abstract int isMatch(char[] buffer, int pos, int bufferStart, int bufferEnd); - - /** - * Returns the number of matching characters, zero for no match. - *

    - * This method is called to check for a match. The parameter {@code pos} - * represents the current position to be checked in the string {@code buffer} (a - * character array which must not be changed). The API guarantees that - * {@code pos} is a valid index for {@code buffer}. - *

    - * The matching code may check one character or many. It may check characters - * preceding {@code pos} as well as those after. - *

    - * It must return zero for no match, or a positive number if a match was found. - * The number indicates the number of characters that matched. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @return the number of matching characters, zero for no match - * @since 2.4 - */ - public int isMatch(final char[] buffer, final int pos) { - return isMatch(buffer, pos, 0, buffer.length); - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a set of characters for matching purposes. - */ - static final class CharSetMatcher extends StrMatcher { - /** The set of characters to match. */ - private final char[] chars; - - /** - * Constructor that creates a matcher from a character array. - * - * @param chars the characters to match, must not be null - */ - CharSetMatcher(final char[] chars) { - this.chars = chars.clone(); - Arrays.sort(this.chars); - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return Arrays.binarySearch(chars, buffer[pos]) >= 0 ? 1 : 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a character for matching purposes. - */ - static final class CharMatcher extends StrMatcher { - /** The character to match. */ - private final char ch; - - /** - * Constructor that creates a matcher that matches a single character. - * - * @param ch the character to match - */ - CharMatcher(final char ch) { - this.ch = ch; - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return ch == buffer[pos] ? 1 : 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to define a set of characters for matching purposes. - */ - static final class StringMatcher extends StrMatcher { - /** The string to match, as a character array. */ - private final char[] chars; - - /** - * Constructor that creates a matcher from a String. - * - * @param str the string to match, must not be null - */ - StringMatcher(final String str) { - chars = str.toCharArray(); - } - - /** - * Returns whether or not the given text matches the stored string. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, int pos, final int bufferStart, final int bufferEnd) { - final int len = chars.length; - if (pos + len > bufferEnd) { - return 0; - } - for (int i = 0; i < chars.length; i++, pos++) { - if (chars[i] != buffer[pos]) { - return 0; - } - } - return len; - } - - @Override - public String toString() { - return super.toString() + ' ' + Arrays.toString(chars); - } - - } - - // ----------------------------------------------------------------------- - /** - * Class used to match no characters. - */ - static final class NoMatcher extends StrMatcher { - - /** - * Constructs a new instance of {@code NoMatcher}. - */ - NoMatcher() { - } - - /** - * Always returns {@code false}. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return 0; - } - } - - // ----------------------------------------------------------------------- - /** - * Class used to match whitespace as per trim(). - */ - static final class TrimMatcher extends StrMatcher { - - /** - * Constructs a new instance of {@code TrimMatcher}. - */ - TrimMatcher() { - } - - /** - * Returns whether or not the given character matches. - * - * @param buffer the text content to match against, do not change - * @param pos the starting position for the match, valid for buffer - * @param bufferStart the first active index in the buffer, valid for buffer - * @param bufferEnd the end index of the active buffer, valid for buffer - * @return the number of matching characters, zero for no match - */ - @Override - public int isMatch(final char[] buffer, final int pos, final int bufferStart, final int bufferEnd) { - return buffer[pos] <= 32 ? 1 : 0; - } - } - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrTokenizer.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrTokenizer.java deleted file mode 100644 index cd501532..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrTokenizer.java +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.repackage.lang3; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; -import java.util.NoSuchElementException; - -/** - * Tokenizes a string based on delimiters (separators) and supporting quoting - * and ignored character concepts. - *

    - * This class can split a String into many smaller strings. It aims to do a - * similar job to {@link java.util.StringTokenizer StringTokenizer}, however it - * offers much more control and flexibility including implementing the - * {@code ListIterator} interface. By default, it is set up like - * {@code StringTokenizer}. - *

    - * The input String is split into a number of tokens. Each token is - * separated from the next String by a delimiter. One or more delimiter - * characters must be specified. - *

    - * Each token may be surrounded by quotes. The quote matcher specifies - * the quote character(s). A quote may be escaped within a quoted section by - * duplicating itself. - *

    - * Between each token and the delimiter are potentially characters that need - * trimming. The trimmer matcher specifies these characters. One usage - * might be to trim whitespace characters. - *

    - * At any point outside the quotes there might potentially be invalid - * characters. The ignored matcher specifies these characters to be - * removed. One usage might be to remove new line characters. - *

    - * Empty tokens may be removed or returned as null. - * - *

    - * "a,b,c"         - Three tokens "a","b","c"   (comma delimiter)
    - * " a, b , c "    - Three tokens "a","b","c"   (default CSV processing trims whitespace)
    - * "a, ", b ,", c" - Three tokens "a, " , " b ", ", c" (quoted text untouched)
    - * 
    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    StrTokenizer properties and options
    PropertyTypeDefault
    delimCharSetMatcher{ \t\n\r\f}
    quoteNoneMatcher{}
    ignoreNoneMatcher{}
    emptyTokenAsNullbooleanfalse
    ignoreEmptyTokensbooleantrue
    - * - * @since 2.2 - * @!deprecated as of 3.6, use commons-text - * StringTokenizer instead - */ -//@Deprecated -public class StrTokenizer implements ListIterator, Cloneable { - - private static final StrTokenizer CSV_TOKENIZER_PROTOTYPE; - private static final StrTokenizer TSV_TOKENIZER_PROTOTYPE; - static { - CSV_TOKENIZER_PROTOTYPE = new StrTokenizer(); - CSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.commaMatcher()); - CSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher()); - CSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher()); - CSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher()); - CSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false); - CSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false); - - TSV_TOKENIZER_PROTOTYPE = new StrTokenizer(); - TSV_TOKENIZER_PROTOTYPE.setDelimiterMatcher(StrMatcher.tabMatcher()); - TSV_TOKENIZER_PROTOTYPE.setQuoteMatcher(StrMatcher.doubleQuoteMatcher()); - TSV_TOKENIZER_PROTOTYPE.setIgnoredMatcher(StrMatcher.noneMatcher()); - TSV_TOKENIZER_PROTOTYPE.setTrimmerMatcher(StrMatcher.trimMatcher()); - TSV_TOKENIZER_PROTOTYPE.setEmptyTokenAsNull(false); - TSV_TOKENIZER_PROTOTYPE.setIgnoreEmptyTokens(false); - } - - /** The text to work on. */ - private char[] chars; - /** The parsed tokens */ - private String[] tokens; - /** The current iteration position */ - private int tokenPos; - - /** The delimiter matcher */ - private StrMatcher delimMatcher = StrMatcher.splitMatcher(); - /** The quote matcher */ - private StrMatcher quoteMatcher = StrMatcher.noneMatcher(); - /** The ignored matcher */ - private StrMatcher ignoredMatcher = StrMatcher.noneMatcher(); - /** The trimmer matcher */ - private StrMatcher trimmerMatcher = StrMatcher.noneMatcher(); - - /** Whether to return empty tokens as null */ - private boolean emptyAsNull; - /** Whether to ignore empty tokens */ - private boolean ignoreEmptyTokens = true; - - // ----------------------------------------------------------------------- - - /** - * Returns a clone of {@code CSV_TOKENIZER_PROTOTYPE}. - * - * @return a clone of {@code CSV_TOKENIZER_PROTOTYPE}. - */ - private static StrTokenizer getCSVClone() { - return (StrTokenizer) CSV_TOKENIZER_PROTOTYPE.clone(); - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - *

    - * You must call a "reset" method to set the string which you want to parse. - * - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance() { - return getCSVClone(); - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance(final String input) { - final StrTokenizer tok = getCSVClone(); - tok.reset(input); - return tok; - } - - /** - * Gets a new tokenizer instance which parses Comma Separated Value strings - * initializing it with the given input. The default for CSV processing will be - * trim whitespace from both ends (which can be overridden with the setTrimmer - * method). - * - * @param input the text to parse - * @return a new tokenizer instance which parses Comma Separated Value strings - */ - public static StrTokenizer getCSVInstance(final char[] input) { - final StrTokenizer tok = getCSVClone(); - tok.reset(input); - return tok; - } - - /** - * Returns a clone of {@code TSV_TOKENIZER_PROTOTYPE}. - * - * @return a clone of {@code TSV_TOKENIZER_PROTOTYPE}. - */ - private static StrTokenizer getTSVClone() { - return (StrTokenizer) TSV_TOKENIZER_PROTOTYPE.clone(); - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - *

    - * You must call a "reset" method to set the string which you want to parse. - * - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance() { - return getTSVClone(); - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - * - * @param input the string to parse - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance(final String input) { - final StrTokenizer tok = getTSVClone(); - tok.reset(input); - return tok; - } - - /** - * Gets a new tokenizer instance which parses Tab Separated Value strings. The - * default for CSV processing will be trim whitespace from both ends (which can - * be overridden with the setTrimmer method). - * - * @param input the string to parse - * @return a new tokenizer instance which parses Tab Separated Value strings. - */ - public static StrTokenizer getTSVInstance(final char[] input) { - final StrTokenizer tok = getTSVClone(); - tok.reset(input); - return tok; - } - - // ----------------------------------------------------------------------- - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer, but with no text to tokenize. - *

    - * This constructor is normally used with {@link #reset(String)}. - */ - public StrTokenizer() { - this.chars = null; - } - - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer. - * - * @param input the string which is to be parsed - */ - public StrTokenizer(final String input) { - if (input != null) { - chars = input.toCharArray(); - } else { - chars = null; - } - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character. - * - * @param input the string which is to be parsed - * @param delim the field delimiter character - */ - public StrTokenizer(final String input, final char delim) { - this(input); - setDelimiterChar(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter string. - * - * @param input the string which is to be parsed - * @param delim the field delimiter string - */ - public StrTokenizer(final String input, final String delim) { - this(input); - setDelimiterString(delim); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher. - * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher - */ - public StrTokenizer(final String input, final StrMatcher delim) { - this(input); - setDelimiterMatcher(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character and - * handling quotes using the specified quote character. - * - * @param input the string which is to be parsed - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final String input, final char delim, final char quote) { - this(input, delim); - setQuoteChar(quote); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher and - * handling quotes using the specified quote matcher. - * - * @param input the string which is to be parsed - * @param delim the field delimiter matcher - * @param quote the field quoted string matcher - */ - public StrTokenizer(final String input, final StrMatcher delim, final StrMatcher quote) { - this(input, delim); - setQuoteMatcher(quote); - } - - /** - * Constructs a tokenizer splitting on space, tab, newline and formfeed as per - * StringTokenizer. - * - * @param input the string which is to be parsed, not cloned - */ - public StrTokenizer(final char[] input) { - this.chars = new String(input).toCharArray(); - } - - /** - * Constructs a tokenizer splitting on the specified character. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - */ - public StrTokenizer(final char[] input, final char delim) { - this(input); - setDelimiterChar(delim); - } - - /** - * Constructs a tokenizer splitting on the specified string. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter string - */ - public StrTokenizer(final char[] input, final String delim) { - this(input); - setDelimiterString(delim); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter matcher - */ - public StrTokenizer(final char[] input, final StrMatcher delim) { - this(input); - setDelimiterMatcher(delim); - } - - /** - * Constructs a tokenizer splitting on the specified delimiter character and - * handling quotes using the specified quote character. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final char[] input, final char delim, final char quote) { - this(input, delim); - setQuoteChar(quote); - } - - /** - * Constructs a tokenizer splitting using the specified delimiter matcher and - * handling quotes using the specified quote matcher. - * - * @param input the string which is to be parsed, not cloned - * @param delim the field delimiter character - * @param quote the field quoted string character - */ - public StrTokenizer(final char[] input, final StrMatcher delim, final StrMatcher quote) { - this(input, delim); - setQuoteMatcher(quote); - } - - // API - // ----------------------------------------------------------------------- - /** - * Gets the number of tokens found in the String. - * - * @return the number of matched tokens - */ - public int size() { - checkTokenized(); - return tokens.length; - } - - /** - * Gets the next token from the String. Equivalent to {@link #next()} except it - * returns null rather than throwing {@link NoSuchElementException} when no - * tokens remain. - * - * @return the next sequential token, or null when no more tokens are found - */ - public String nextToken() { - if (hasNext()) { - return tokens[tokenPos++]; - } - return null; - } - - /** - * Gets the previous token from the String. - * - * @return the previous sequential token, or null when no more tokens are found - */ - public String previousToken() { - if (hasPrevious()) { - return tokens[--tokenPos]; - } - return null; - } - - /** - * Gets a copy of the full token list as an independent modifiable array. - * - * @return the tokens as a String array - */ - public String[] getTokenArray() { - checkTokenized(); - return tokens.clone(); - } - - /** - * Gets a copy of the full token list as an independent modifiable list. - * - * @return the tokens as a String array - */ - public List getTokenList() { - checkTokenized(); - final List list = new ArrayList<>(tokens.length); - list.addAll(Arrays.asList(tokens)); - return list; - } - - /** - * Resets this tokenizer, forgetting all parsing and iteration already - * completed. - *

    - * This method allows the same tokenizer to be reused for the same String. - * - * @return this, to enable chaining - */ - public StrTokenizer reset() { - tokenPos = 0; - tokens = null; - return this; - } - - /** - * Reset this tokenizer, giving it a new input string to parse. In this manner - * you can re-use a tokenizer with the same settings on multiple input lines. - * - * @param input the new string to tokenize, null sets no text to parse - * @return this, to enable chaining - */ - public StrTokenizer reset(final String input) { - reset(); - if (input != null) { - this.chars = input.toCharArray(); - } else { - this.chars = null; - } - return this; - } - - /** - * Reset this tokenizer, giving it a new input string to parse. In this manner - * you can re-use a tokenizer with the same settings on multiple input lines. - * - * @param input the new character array to tokenize, not cloned, null sets no - * text to parse - * @return this, to enable chaining - */ - public StrTokenizer reset(final char[] input) { - reset(); - this.chars = new String(input).toCharArray(); - return this; - } - - // ListIterator - // ----------------------------------------------------------------------- - /** - * Checks whether there are any more tokens. - * - * @return true if there are more tokens - */ - @Override - public boolean hasNext() { - checkTokenized(); - return tokenPos < tokens.length; - } - - /** - * Gets the next token. - * - * @return the next String token - * @throws NoSuchElementException if there are no more elements - */ - @Override - public String next() { - if (hasNext()) { - return tokens[tokenPos++]; - } - throw new NoSuchElementException(); - } - - /** - * Gets the index of the next token to return. - * - * @return the next token index - */ - @Override - public int nextIndex() { - return tokenPos; - } - - /** - * Checks whether there are any previous tokens that can be iterated to. - * - * @return true if there are previous tokens - */ - @Override - public boolean hasPrevious() { - checkTokenized(); - return tokenPos > 0; - } - - /** - * Gets the token previous to the last returned token. - * - * @return the previous token - */ - @Override - public String previous() { - if (hasPrevious()) { - return tokens[--tokenPos]; - } - throw new NoSuchElementException(); - } - - /** - * Gets the index of the previous token. - * - * @return the previous token index - */ - @Override - public int previousIndex() { - return tokenPos - 1; - } - - /** - * Unsupported ListIterator operation. - * - * @throws UnsupportedOperationException always - */ - @Override - public void remove() { - throw new UnsupportedOperationException("remove() is unsupported"); - } - - /** - * Unsupported ListIterator operation. - * - * @param obj this parameter ignored. - * @throws UnsupportedOperationException always - */ - @Override - public void set(final String obj) { - throw new UnsupportedOperationException("set() is unsupported"); - } - - /** - * Unsupported ListIterator operation. - * - * @param obj this parameter ignored. - * @throws UnsupportedOperationException always - */ - @Override - public void add(final String obj) { - throw new UnsupportedOperationException("add() is unsupported"); - } - - // Implementation - // ----------------------------------------------------------------------- - /** - * Checks if tokenization has been done, and if not then do it. - */ - private void checkTokenized() { - if (tokens == null) { - if (chars == null) { - // still call tokenize as subclass may do some work - final List split = tokenize(null, 0, 0); - tokens = split.toArray(new String[0]); - } else { - final List split = tokenize(chars, 0, chars.length); - tokens = split.toArray(new String[0]); - } - } - } - - /** - * Internal method to performs the tokenization. - *

    - * Most users of this class do not need to call this method. This method will be - * called automatically by other (public) methods when required. - *

    - * This method exists to allow subclasses to add code before or after the - * tokenization. For example, a subclass could alter the character array, offset - * or count to be parsed, or call the tokenizer multiple times on multiple - * strings. It is also be possible to filter the results. - *

    - * {@code StrTokenizer} will always pass a zero offset and a count equal to the - * length of the array to this method, however a subclass may pass other values, - * or even an entirely different array. - * - * @param srcChars the character array being tokenized, may be null - * @param offset the start position within the character array, must be valid - * @param count the number of characters to tokenize, must be valid - * @return the modifiable list of String tokens, unmodifiable if null array or - * zero count - */ - protected List tokenize(final char[] srcChars, final int offset, final int count) { - if (srcChars == null || count == 0) { - return Collections.emptyList(); - } - final StrBuilder buf = new StrBuilder(); - final List tokenList = new ArrayList<>(); - int pos = offset; - - // loop around the entire buffer - while (pos >= 0 && pos < count) { - // find next token - pos = readNextToken(srcChars, pos, count, buf, tokenList); - - // handle case where end of string is a delimiter - if (pos >= count) { - addToken(tokenList, ""); - } - } - return tokenList; - } - - /** - * Adds a token to a list, paying attention to the parameters we've set. - * - * @param list the list to add to - * @param tok the token to add - */ - private void addToken(final List list, String tok) { - if (tok == null || tok.length() == 0) { - if (isIgnoreEmptyTokens()) { - return; - } - if (isEmptyTokenAsNull()) { - tok = null; - } - } - list.add(tok); - } - - /** - * Reads character by character through the String to get the next token. - * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @return the starting position of the next field (the character immediately - * after the delimiter), or -1 if end of string found - */ - private int readNextToken(final char[] srcChars, int start, final int len, final StrBuilder workArea, - final List tokenList) { - // skip all leading whitespace, unless it is the - // field delimiter or the quote character - while (start < len) { - final int removeLen = Math.max(getIgnoredMatcher().isMatch(srcChars, start, start, len), - getTrimmerMatcher().isMatch(srcChars, start, start, len)); - if (removeLen == 0 || getDelimiterMatcher().isMatch(srcChars, start, start, len) > 0 - || getQuoteMatcher().isMatch(srcChars, start, start, len) > 0) { - break; - } - start += removeLen; - } - - // handle reaching end - if (start >= len) { - addToken(tokenList, ""); - return -1; - } - - // handle empty token - final int delimLen = getDelimiterMatcher().isMatch(srcChars, start, start, len); - if (delimLen > 0) { - addToken(tokenList, ""); - return start + delimLen; - } - - // handle found token - final int quoteLen = getQuoteMatcher().isMatch(srcChars, start, start, len); - if (quoteLen > 0) { - return readWithQuotes(srcChars, start + quoteLen, len, workArea, tokenList, start, quoteLen); - } - return readWithQuotes(srcChars, start, len, workArea, tokenList, 0, 0); - } - - /** - * Reads a possibly quoted string token. - * - * @param srcChars the character array being tokenized - * @param start the first character of field - * @param len the length of the character array being tokenized - * @param workArea a temporary work area - * @param tokenList the list of parsed tokens - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return the starting position of the next field (the character immediately - * after the delimiter, or if end of string found, then the length of - * string - */ - private int readWithQuotes(final char[] srcChars, final int start, final int len, final StrBuilder workArea, - final List tokenList, final int quoteStart, final int quoteLen) { - // Loop until we've found the end of the quoted - // string or the end of the input - workArea.clear(); - int pos = start; - boolean quoting = quoteLen > 0; - int trimStart = 0; - - while (pos < len) { - // quoting mode can occur several times throughout a string - // we must switch between quoting and non-quoting until we - // encounter a non-quoted delimiter, or end of string - if (quoting) { - // In quoting mode - - // If we've found a quote character, see if it's - // followed by a second quote. If so, then we need - // to actually put the quote character into the token - // rather than end the token. - if (isQuote(srcChars, pos, len, quoteStart, quoteLen)) { - if (isQuote(srcChars, pos + quoteLen, len, quoteStart, quoteLen)) { - // matched pair of quotes, thus an escaped quote - workArea.append(srcChars, pos, quoteLen); - pos += quoteLen * 2; - trimStart = workArea.size(); - continue; - } - - // end of quoting - quoting = false; - pos += quoteLen; - continue; - } - - // copy regular character from inside quotes - workArea.append(srcChars[pos++]); - trimStart = workArea.size(); - - } else { - // Not in quoting mode - - // check for delimiter, and thus end of token - final int delimLen = getDelimiterMatcher().isMatch(srcChars, pos, start, len); - if (delimLen > 0) { - // return condition when end of token found - addToken(tokenList, workArea.substring(0, trimStart)); - return pos + delimLen; - } - - // check for quote, and thus back into quoting mode - if (quoteLen > 0 && isQuote(srcChars, pos, len, quoteStart, quoteLen)) { - quoting = true; - pos += quoteLen; - continue; - } - - // check for ignored (outside quotes), and ignore - final int ignoredLen = getIgnoredMatcher().isMatch(srcChars, pos, start, len); - if (ignoredLen > 0) { - pos += ignoredLen; - continue; - } - - // check for trimmed character - // don't yet know if its at the end, so copy to workArea - // use trimStart to keep track of trim at the end - final int trimmedLen = getTrimmerMatcher().isMatch(srcChars, pos, start, len); - if (trimmedLen > 0) { - workArea.append(srcChars, pos, trimmedLen); - pos += trimmedLen; - continue; - } - - // copy regular character from outside quotes - workArea.append(srcChars[pos++]); - trimStart = workArea.size(); - } - } - - // return condition when end of string found - addToken(tokenList, workArea.substring(0, trimStart)); - return -1; - } - - /** - * Checks if the characters at the index specified match the quote already - * matched in readNextToken(). - * - * @param srcChars the character array being tokenized - * @param pos the position to check for a quote - * @param len the length of the character array being tokenized - * @param quoteStart the start position of the matched quote, 0 if no quoting - * @param quoteLen the length of the matched quote, 0 if no quoting - * @return true if a quote is matched - */ - private boolean isQuote(final char[] srcChars, final int pos, final int len, final int quoteStart, - final int quoteLen) { - for (int i = 0; i < quoteLen; i++) { - if (pos + i >= len || srcChars[pos + i] != srcChars[quoteStart + i]) { - return false; - } - } - return true; - } - - // Delimiter - // ----------------------------------------------------------------------- - /** - * Gets the field delimiter matcher. - * - * @return the delimiter matcher in use - */ - public StrMatcher getDelimiterMatcher() { - return this.delimMatcher; - } - - /** - * Sets the field delimiter matcher. - *

    - * The delimiter is used to separate one token from another. - * - * @param delim the delimiter matcher to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterMatcher(final StrMatcher delim) { - if (delim == null) { - this.delimMatcher = StrMatcher.noneMatcher(); - } else { - this.delimMatcher = delim; - } - return this; - } - - /** - * Sets the field delimiter character. - * - * @param delim the delimiter character to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterChar(final char delim) { - return setDelimiterMatcher(StrMatcher.charMatcher(delim)); - } - - /** - * Sets the field delimiter string. - * - * @param delim the delimiter string to use - * @return this, to enable chaining - */ - public StrTokenizer setDelimiterString(final String delim) { - return setDelimiterMatcher(StrMatcher.stringMatcher(delim)); - } - - // Quote - // ----------------------------------------------------------------------- - /** - * Gets the quote matcher currently in use. - *

    - * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. The default value is '"' (double quote). - * - * @return the quote matcher in use - */ - public StrMatcher getQuoteMatcher() { - return quoteMatcher; - } - - /** - * Set the quote matcher to use. - *

    - * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. - * - * @param quote the quote matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setQuoteMatcher(final StrMatcher quote) { - if (quote != null) { - this.quoteMatcher = quote; - } - return this; - } - - /** - * Sets the quote character to use. - *

    - * The quote character is used to wrap data between the tokens. This enables - * delimiters to be entered as data. - * - * @param quote the quote character to use - * @return this, to enable chaining - */ - public StrTokenizer setQuoteChar(final char quote) { - return setQuoteMatcher(StrMatcher.charMatcher(quote)); - } - - // Ignored - // ----------------------------------------------------------------------- - /** - * Gets the ignored character matcher. - *

    - * These characters are ignored when parsing the String, unless they are within - * a quoted region. The default value is not to ignore anything. - * - * @return the ignored matcher in use - */ - public StrMatcher getIgnoredMatcher() { - return ignoredMatcher; - } - - /** - * Set the matcher for characters to ignore. - *

    - * These characters are ignored when parsing the String, unless they are within - * a quoted region. - * - * @param ignored the ignored matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setIgnoredMatcher(final StrMatcher ignored) { - if (ignored != null) { - this.ignoredMatcher = ignored; - } - return this; - } - - /** - * Set the character to ignore. - *

    - * This character is ignored when parsing the String, unless it is within a - * quoted region. - * - * @param ignored the ignored character to use - * @return this, to enable chaining - */ - public StrTokenizer setIgnoredChar(final char ignored) { - return setIgnoredMatcher(StrMatcher.charMatcher(ignored)); - } - - // Trimmer - // ----------------------------------------------------------------------- - /** - * Gets the trimmer character matcher. - *

    - * These characters are trimmed off on each side of the delimiter until the - * token or quote is found. The default value is not to trim anything. - * - * @return the trimmer matcher in use - */ - public StrMatcher getTrimmerMatcher() { - return trimmerMatcher; - } - - /** - * Sets the matcher for characters to trim. - *

    - * These characters are trimmed off on each side of the delimiter until the - * token or quote is found. - * - * @param trimmer the trimmer matcher to use, null ignored - * @return this, to enable chaining - */ - public StrTokenizer setTrimmerMatcher(final StrMatcher trimmer) { - if (trimmer != null) { - this.trimmerMatcher = trimmer; - } - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets whether the tokenizer currently returns empty tokens as null. The - * default for this property is false. - * - * @return true if empty tokens are returned as null - */ - public boolean isEmptyTokenAsNull() { - return this.emptyAsNull; - } - - /** - * Sets whether the tokenizer should return empty tokens as null. The default - * for this property is false. - * - * @param emptyAsNull whether empty tokens are returned as null - * @return this, to enable chaining - */ - public StrTokenizer setEmptyTokenAsNull(final boolean emptyAsNull) { - this.emptyAsNull = emptyAsNull; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets whether the tokenizer currently ignores empty tokens. The default for - * this property is true. - * - * @return true if empty tokens are not returned - */ - public boolean isIgnoreEmptyTokens() { - return ignoreEmptyTokens; - } - - /** - * Sets whether the tokenizer should ignore and not return empty tokens. The - * default for this property is true. - * - * @param ignoreEmptyTokens whether empty tokens are not returned - * @return this, to enable chaining - */ - public StrTokenizer setIgnoreEmptyTokens(final boolean ignoreEmptyTokens) { - this.ignoreEmptyTokens = ignoreEmptyTokens; - return this; - } - - // ----------------------------------------------------------------------- - /** - * Gets the String content that the tokenizer is parsing. - * - * @return the string content being parsed - */ - public String getContent() { - if (chars == null) { - return null; - } - return new String(chars); - } - - // ----------------------------------------------------------------------- - /** - * Creates a new instance of this Tokenizer. The new instance is reset so that - * it will be at the start of the token list. If a - * {@link CloneNotSupportedException} is caught, return {@code null}. - * - * @return a new instance of this Tokenizer which has been reset. - */ - @Override - public Object clone() { - try { - return cloneReset(); - } catch (final CloneNotSupportedException ex) { - return null; - } - } - - /** - * Creates a new instance of this Tokenizer. The new instance is reset so that - * it will be at the start of the token list. - * - * @return a new instance of this Tokenizer which has been reset. - * @throws CloneNotSupportedException if there is a problem cloning - */ - Object cloneReset() throws CloneNotSupportedException { - // this method exists to enable 100% test coverage - final StrTokenizer cloned = (StrTokenizer) super.clone(); - if (cloned.chars != null) { - cloned.chars = cloned.chars.clone(); - } - cloned.reset(); - return cloned; - } - - // ----------------------------------------------------------------------- - /** - * Gets the String content that the tokenizer is parsing. - * - * @return the string content being parsed - */ - @Override - public String toString() { - if (tokens == null) { - return "StrTokenizer[not tokenized yet]"; - } - return "StrTokenizer" + getTokenList(); - } - -} diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerConnectionInstance.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerConnectionInstance.java deleted file mode 100644 index f283f10a..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerConnectionInstance.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import io.netty.channel.Channel; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class EaglerConnectionInstance { - - public final Channel channel; - - public final long creationTime; - public boolean hasBeenForwarded = false; - - public long lastServerPingPacket; - public long lastClientPingPacket; - public long lastClientPongPacket; - - public boolean isWebSocket = false; - public boolean isRegularHttp = false; - - public ConnectedPlayer userConnection = null; - public EaglerPlayerData eaglerData = null; - public HttpServerQueryHandler queryHandler = null; - - public EaglerConnectionInstance(Channel channel) { - this.channel = channel; - this.creationTime = this.lastServerPingPacket = this.lastClientPingPacket = - this.lastClientPongPacket = EaglerXVelocityAPIHelper.steadyTimeMillis(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftDecoder.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftDecoder.java deleted file mode 100644 index 408ecc44..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftDecoder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -import java.util.List; - -public class EaglerMinecraftDecoder extends MessageToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List out) { - if(!ctx.channel().isActive()) { - return; - } - EaglerConnectionInstance con = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - if(frame instanceof BinaryWebSocketFrame) { - out.add(frame.content().retain()); - }else if(frame instanceof PingWebSocketFrame) { - if(millis - con.lastClientPingPacket > 500l) { - ctx.write(new PongWebSocketFrame()); - con.lastClientPingPacket = millis; - } - }else if(frame instanceof PongWebSocketFrame) { - con.lastClientPongPacket = millis; - }else { - ctx.close(); - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftEncoder.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftEncoder.java deleted file mode 100644 index a2b1b264..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerMinecraftEncoder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.util.List; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageEncoder; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; - -public class EaglerMinecraftEncoder extends MessageToMessageEncoder { - @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - out.add(new BinaryWebSocketFrame(msg.retain())); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPipeline.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPipeline.java deleted file mode 100644 index 37b0d8cc..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPipeline.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicInteger; - -import org.slf4j.Logger; - -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.scheduler.VelocityScheduler; - -import io.netty.buffer.PooledByteBufAllocator; -import io.netty.channel.Channel; -import io.netty.channel.ChannelException; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.WriteBufferWaterMark; -import io.netty.handler.codec.compression.ZlibCodecFactory; -import io.netty.handler.codec.haproxy.HAProxyMessageDecoder; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler; -import io.netty.handler.codec.http.websocketx.extensions.compression.DeflateFrameServerExtensionHandshaker; -import io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateServerExtensionHandshaker; -import io.netty.util.AttributeKey; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData.ClientCertificateHolder; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpWebServer; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUpdateCertEAG; - -public class EaglerPipeline { - - public static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1048576, 2097152); - public static final AttributeKey LISTENER = AttributeKey.valueOf("ListenerInfo"); - public static final AttributeKey LOCAL_ADDRESS = AttributeKey.valueOf("LocalAddress"); - public static final AttributeKey CONNECTION_INSTANCE = AttributeKey.valueOf("EaglerConnectionInstance"); - public static final AttributeKey REAL_ADDRESS = AttributeKey.valueOf("RealAddress"); - public static final AttributeKey HOST = AttributeKey.valueOf("Host"); - public static final AttributeKey ORIGIN = AttributeKey.valueOf("Origin"); - public static final AttributeKey USER_AGENT = AttributeKey.valueOf("UserAgent"); - - public static final Collection openChannels = new LinkedList<>(); - - public static final TimerTask closeInactive = new TimerTask() { - - @Override - public void run() { - Logger log = EaglerXVelocity.logger(); - try { - EaglerVelocityConfig conf = EaglerXVelocity.getEagler().getConfig(); - long handshakeTimeout = conf.getWebsocketHandshakeTimeout(); - long keepAliveTimeout = conf.getWebsocketKeepAliveTimeout(); - long httpTimeout = conf.getBuiltinHttpServerTimeout(); - List channelsList; - synchronized(openChannels) { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - Iterator channelIterator = openChannels.iterator(); - while(channelIterator.hasNext()) { - Channel c = channelIterator.next(); - final EaglerConnectionInstance i = c.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - long handshakeTimeoutForConnection = 500l; - if(i.isRegularHttp) handshakeTimeoutForConnection = httpTimeout; - else if(i.isWebSocket) handshakeTimeoutForConnection = handshakeTimeout; - boolean hasTimeout = !i.hasBeenForwarded; - if(i.queryHandler != null) { - long l = i.queryHandler.getMaxAge(); - hasTimeout = l != -1l; - if(hasTimeout) { - handshakeTimeoutForConnection = l; - } - } - if((hasTimeout && millis - i.creationTime > handshakeTimeoutForConnection) - || millis - i.lastClientPongPacket > keepAliveTimeout || !c.isActive()) { - if(c.isActive()) { - c.close(); - } - channelIterator.remove(); - }else { - long pingRate = 5000l; - if(pingRate + 700l > keepAliveTimeout) { - pingRate = keepAliveTimeout - 500l; - if(pingRate < 500l) { - keepAliveTimeout = 500l; - } - } - if(millis - i.lastServerPingPacket > pingRate) { - i.lastServerPingPacket = millis; - c.write(new PingWebSocketFrame()); - } - } - } - channelsList = new ArrayList<>(openChannels); - } - for(EaglerListenerConfig lst : conf.getServerListeners()) { - HttpWebServer srv = lst.getWebServer(); - if(srv != null) { - try { - srv.flushCache(); - }catch(Throwable t) { - log.error("Failed to flush web server cache for: {}", lst.getAddress()); - t.printStackTrace(); - } - } - } - final int serverInfoSendRate = Math.max(conf.getPauseMenuConf().getInfoSendRate(), 1); - boolean blockAllClientUpdates = conf.getUpdateConfig().isBlockAllClientUpdates(); - final AtomicInteger sizeTracker = blockAllClientUpdates ? null : new AtomicInteger(0); - final int rateLimitParam = conf.getUpdateConfig().getCertPacketDataRateLimit() / 4; - VelocityScheduler sched = EaglerXVelocity.proxy().getScheduler(); - EaglerXVelocity plugin = EaglerXVelocity.getEagler(); - for(Channel c : channelsList) { - final EaglerConnectionInstance conn = c.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - if(conn.userConnection == null) { - continue; - } - final EaglerPlayerData i = conn.eaglerData; - boolean certToSend = false; - if(!blockAllClientUpdates) { - synchronized(i.certificatesToSend) { - if(!i.certificatesToSend.isEmpty()) { - certToSend = true; - } - } - } - boolean serverInfoToSend = false; - synchronized(i.serverInfoSendBuffer) { - if(!i.serverInfoSendBuffer.isEmpty()) { - serverInfoToSend = true; - } - } - if(certToSend || serverInfoToSend) { - final boolean do_certToSend = certToSend; - final boolean do_serverInfoToSend = serverInfoToSend; - sched.buildTask(plugin, () -> { - if(do_certToSend) { - ClientCertificateHolder certHolder = null; - synchronized(i.certificatesToSend) { - if(i.certificatesToSend.size() > 0) { - Iterator itr = i.certificatesToSend.iterator(); - certHolder = itr.next(); - itr.remove(); - } - } - if(certHolder != null && sizeTracker.getAndAdd(certHolder.data.length) < rateLimitParam) { - int identityHash = certHolder.hashCode(); - boolean bb; - synchronized(i.certificatesSent) { - bb = i.certificatesSent.add(identityHash); - } - if(bb) { - conn.eaglerData.sendEaglerMessage(new SPacketUpdateCertEAG(certHolder.data)); - } - } - } - if(do_serverInfoToSend) { - List toSend = i.serverInfoSendBuffer; - synchronized(toSend) { - if(!toSend.isEmpty()) { - try { - if(serverInfoSendRate == 1) { - i.getEaglerMessageController().sendPacketImmediately(toSend.remove(0)); - }else { - for(int j = 0; j < serverInfoSendRate; ++j) { - if(!toSend.isEmpty()) { - i.getEaglerMessageController().sendPacketImmediately(toSend.remove(0)); - }else { - break; - } - } - } - }catch(Throwable t) { - log.error("Exception in thread \"{}\"!", Thread.currentThread().getName(), t); - } - } - } - } - }).schedule(); - } - } - }catch(Throwable t) { - log.error("Exception in thread \"{}\"!", Thread.currentThread().getName(), t); - } - } - }; - - public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() { - - @Override - protected void initChannel(Channel channel) throws Exception { - channel.config().setAllocator(PooledByteBufAllocator.DEFAULT).setWriteBufferWaterMark(SERVER_WRITE_MARK); - try { - channel.config().setOption(ChannelOption.IP_TOS, 24); - } catch (ChannelException var3) { - } - EaglerListenerConfig listener = channel.attr(LISTENER).get(); - ChannelPipeline pipeline = channel.pipeline(); - if(listener.isHAProxyProtocol()) { - pipeline.addLast("HAProxyMessageDecoder", new HAProxyMessageDecoder()); - } - pipeline.addLast("HttpServerCodec", new HttpServerCodec()); - pipeline.addLast("HttpObjectAggregator", new HttpObjectAggregator(65535)); - int compressionLevel = EaglerXVelocity.getEagler().getConfig().getHttpWebsocketCompressionLevel(); - if(compressionLevel > 0) { - if(compressionLevel > 9) { - compressionLevel = 9; - } - DeflateFrameServerExtensionHandshaker deflateExtensionHandshaker = new DeflateFrameServerExtensionHandshaker( - compressionLevel); - PerMessageDeflateServerExtensionHandshaker perMessageDeflateExtensionHandshaker = new PerMessageDeflateServerExtensionHandshaker( - compressionLevel, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), - PerMessageDeflateServerExtensionHandshaker.MAX_WINDOW_SIZE, false, false); - pipeline.addLast("HttpCompressionHandler", new WebSocketServerExtensionHandler(deflateExtensionHandshaker, - perMessageDeflateExtensionHandshaker)); - } - pipeline.addLast("HttpHandshakeHandler", new HttpHandshakeHandler(listener)); - channel.attr(CONNECTION_INSTANCE).set(new EaglerConnectionInstance(channel)); - synchronized(openChannels) { - openChannels.add(channel); - } - } - - }; - - public static void closeChannel(Channel channel) { - synchronized(openChannels) { - openChannels.remove(channel); - } - } - - public static EaglerPlayerData getEaglerHandle(Channel channel) { - EaglerConnectionInstance i = channel.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - return i == null ? null : i.eaglerData; - } - - public static EaglerPlayerData getEaglerHandle(Player player) { - if(!(player instanceof ConnectedPlayer)) return null; - return getEaglerHandle(((ConnectedPlayer)player).getConnection().getChannel()); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPlayerData.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPlayerData.java deleted file mode 100644 index c09e928f..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerPlayerData.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import com.google.common.collect.Collections2; -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.api.util.GameProfile; -import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.kyori.adventure.text.Component; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumWebViewState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.NotificationBadgeBuilder; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.BackendRPCSessionHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SimpleRateLimiter; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeHideV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsRegisterV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsReleaseV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketRedirectClientV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketSetServerCookieV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketWebViewMessageV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class EaglerPlayerData { - - public static class ClientCertificateHolder { - public final byte[] data; - public final int hash; - public ClientCertificateHolder(byte[] data, int hash) { - this.data = data; - this.hash = hash; - } - } - - protected final EaglerConnectionInstance connInstance; - protected final int clientProtocolVersion; - protected final int gameProtocolVersion; - protected final String clientBrandString; - protected final String clientVersionString; - protected final UUID clientBrandUUID; - protected final String username; - protected final UUID playerUUID; - protected final InetSocketAddress eaglerAddress; - public final SimpleRateLimiter skinLookupRateLimiter; - public final SimpleRateLimiter skinUUIDLookupRateLimiter; - public final SimpleRateLimiter skinTextureDownloadRateLimiter; - public final SimpleRateLimiter capeLookupRateLimiter; - public final SimpleRateLimiter voiceConnectRateLimiter; - public final EaglerListenerConfig listener; - public final String origin; - protected final String userAgent; - public final ClientCertificateHolder clientCertificate; - public final Set certificatesToSend; - public final Set certificatesSent; - public final AtomicBoolean currentFNAWSkinEnableStatus = new AtomicBoolean(true); - public final AtomicBoolean currentFNAWSkinForceStatus = new AtomicBoolean(false); - volatile GameProtocolMessageController messageProtocolController = null; - protected final boolean allowCookie; - protected volatile byte[] cookie; - public volatile SkinPacketVersionCache originalSkin = null; - public volatile GameMessagePacket originalCape = null; - protected final Map otherProfileDataFromHanshake; - public boolean isWebViewChannelAllowed = false; - public final AtomicBoolean webViewMessageChannelOpen = new AtomicBoolean(false); - public volatile String webViewMessageChannelName = null; - public final AtomicBoolean hasSentServerInfo = new AtomicBoolean(false); - public final List serverInfoSendBuffer = new LinkedList<>(); - protected BackendRPCSessionHandler backedRPCSessionHandler = null; - protected GameProfile gameProfile; - protected final AtomicReference lastVoiceState = new AtomicReference<>( - EaglercraftVoiceStatusChangeEvent.EnumVoiceState.SERVER_DISABLE); - - public EaglerPlayerData(EaglerConnectionInstance connInstance, EaglerListenerConfig listener, - int clientProtocolVersion, int gameProtocolVersion, String clientBrandString, String clientVersionString, - UUID clientBrandUUID, String username, UUID playerUUID, InetSocketAddress eaglerAddress, String origin, - String userAgent, ClientCertificateHolder clientCertificate, boolean allowCookie, byte[] cookie, - Map otherProfileData, GameProfile gameProfile) { - this.connInstance = connInstance; - this.listener = listener; - this.clientProtocolVersion = clientProtocolVersion; - this.gameProtocolVersion = gameProtocolVersion; - this.clientBrandString = clientBrandString; - this.clientVersionString = clientVersionString; - this.clientBrandUUID = clientBrandUUID; - this.username = username; - this.playerUUID = playerUUID; - this.eaglerAddress = eaglerAddress; - this.origin = origin; - this.userAgent = userAgent; - this.skinLookupRateLimiter = new SimpleRateLimiter(); - this.skinUUIDLookupRateLimiter = new SimpleRateLimiter(); - this.skinTextureDownloadRateLimiter = new SimpleRateLimiter(); - this.capeLookupRateLimiter = new SimpleRateLimiter(); - this.voiceConnectRateLimiter = new SimpleRateLimiter(); - this.allowCookie = allowCookie; - this.cookie = cookie; - this.otherProfileDataFromHanshake = otherProfileData; - this.clientCertificate = clientCertificate; - this.gameProfile = gameProfile; - this.certificatesToSend = new HashSet<>(); - this.certificatesSent = new HashSet<>(); - EaglerVelocityConfig conf = EaglerXVelocity.getEagler().getConfig(); - SPacketCustomizePauseMenuV4EAG pkt = conf.getPauseMenuConf().getPacket(); - this.isWebViewChannelAllowed = pkt != null - && (pkt.serverInfoEmbedPerms & SPacketCustomizePauseMenuV4EAG.SERVER_INFO_EMBED_PERMS_MESSAGE_API) != 0; - this.backedRPCSessionHandler = conf.getEnableBackendRPCAPI() - ? BackendRPCSessionHandler.createForPlayer(this) : null; - if(clientCertificate != null) { - this.certificatesSent.add(clientCertificate.hashCode()); - } - } - - public InetSocketAddress getSocketAddress() { - return eaglerAddress; - } - - public GameProtocolMessageController getEaglerMessageController() { - return messageProtocolController; - } - - public GamePluginMessageProtocol getEaglerProtocol() { - return messageProtocolController == null ? GamePluginMessageProtocol.getByVersion(clientProtocolVersion) - : messageProtocolController.protocol; - } - - public int getEaglerProtocolHandshake() { - return clientProtocolVersion; - } - - public void sendEaglerMessage(GameMessagePacket pkt) { - if(messageProtocolController != null) { - try { - messageProtocolController.sendPacket(pkt); - } catch (IOException e) { - connInstance.userConnection.disconnect(Component.text("Failed to write eaglercraft packet! (" + e.toString() + ")")); - } - }else { - throw new IllegalStateException("Race condition detected, messageProtocolController is null!"); - } - } - - public boolean getWebViewSupport() { - return getEaglerProtocol().ver >= 4; - } - - public void setWebViewChannelAllowed(boolean en) { - isWebViewChannelAllowed = en; - } - public boolean getWebViewChannelAllowed() { - return isWebViewChannelAllowed; - } - - public boolean getWebViewMessageChannelOpen() { - return webViewMessageChannelOpen.get(); - } - - public String getWebViewMessageChannelName() { - return webViewMessageChannelName; - } - - public void sendWebViewMessage(int type, byte[] bytes) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(type, bytes)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to send a webview message to player \"{}\", but the player doesn't have a webview message channel open!", - getSocketAddress(), username); - } - } - public void sendWebViewMessage(String str) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(str)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to send a webview message to player \"{}\", but the player doesn't have a webview message channel open!", - getSocketAddress(), username); - } - } - - public void sendWebViewMessage(byte[] bin) { - if(webViewMessageChannelOpen.get()) { - sendEaglerMessage(new SPacketWebViewMessageV4EAG(bin)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to send a webview message to player \"{}\", but the player doesn't have a webview message channel open!", - getSocketAddress(), username); - } - } - - public EnumWebViewState getWebViewState() { - if(!getWebViewSupport()) { - return EnumWebViewState.NOT_SUPPORTED; - } - if(isWebViewChannelAllowed) { - if(webViewMessageChannelOpen.get()) { - return EnumWebViewState.CHANNEL_OPEN; - }else { - return EnumWebViewState.CHANNEL_CLOSED; - } - }else { - return EnumWebViewState.SERVER_DISABLE; - } - } - - public boolean getCookieAllowed() { - return allowCookie; - } - - public byte[] getCookieData() { - return allowCookie ? cookie : null; - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), false, true); - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, true); - } - - public void setCookieData(byte[] data, long expiresAfter, TimeUnit timeUnit, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - setCookieData(data, timeUnit.toSeconds(expiresAfter), revokeQuerySupported, clientSaveCookieToDisk); - } - - public void setCookieData(byte[] data, long expiresAfterSec, boolean revokeQuerySupported, boolean clientSaveCookieToDisk) { - if(allowCookie) { - if(expiresAfterSec < 0l) { - expiresAfterSec = 0l; - data = null; - } - if(data == null) { - cookie = null; - sendEaglerMessage(new SPacketSetServerCookieV4EAG(null, 01, false, false)); - return; - } - if(data.length > 255) { - throw new IllegalArgumentException("Cookie cannot be longer than 255 bytes!"); - } - if(expiresAfterSec > 604800l) { - throw new IllegalArgumentException("Cookie cannot be set for longer than 7 days! (tried " + (expiresAfterSec / 604800l) + " days)"); - } - cookie = data; - sendEaglerMessage(new SPacketSetServerCookieV4EAG(data, expiresAfterSec, revokeQuerySupported, clientSaveCookieToDisk)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to set a cookie for player \"{}\", but the player has cookies disabled!", - getSocketAddress(), username); - } - } - - public void clearCookieData() { - setCookieData(null, 0, false, false); - } - - public boolean notificationSupported() { - return clientProtocolVersion >= 4; - } - - public void registerNotificationIcon(UUID uuid, PacketImageData imageData) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG( - Arrays.asList(new SPacketNotifIconsRegisterV4EAG.CreateIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), imageData)))); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to register notification icons for player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void registerNotificationIcons(Map imageDatas) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG( - new ArrayList<>(Collections2.transform(imageDatas.entrySet(), (etr) -> { - UUID key = etr.getKey(); - return new SPacketNotifIconsRegisterV4EAG.CreateIcon(key.getMostSignificantBits(), - key.getLeastSignificantBits(), etr.getValue()); - })))); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to register notification icons for player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void showNotificationBadge(NotificationBadgeBuilder badgeBuilder) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(badgeBuilder.buildPacket()); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to show notification badges to player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void showNotificationBadge(SPacketNotifBadgeShowV4EAG badgePacket) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(badgePacket); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to show notification badges to player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void hideNotificationBadge(UUID badgeUUID) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifBadgeHideV4EAG(badgeUUID.getMostSignificantBits(), badgeUUID.getLeastSignificantBits())); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to hide notification badges for player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void releaseNotificationIcon(UUID uuid) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG( - Arrays.asList(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())))); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to release notification icons for player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public void releaseNotificationIcons(Collection uuids) { - if(clientProtocolVersion >= 4) { - sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG(new ArrayList<>(Collections2.transform(uuids, - (etr) -> new SPacketNotifIconsReleaseV4EAG.DestroyIcon(etr.getMostSignificantBits(), - etr.getLeastSignificantBits()))))); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to release notification icons for player \"{}\", but the player has notifications disabled!", - getSocketAddress(), username); - } - } - - public boolean redirectToWebSocketSupported() { - return clientProtocolVersion >= 4; - } - - public void redirectPlayerToWebSocket(String serverAddress) { - if(getEaglerProtocol().ver >= 4) { - sendEaglerMessage(new SPacketRedirectClientV4EAG(serverAddress)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Some plugin tried to redirect player \"{}\" to a different websocket, but that player's client doesn't support this feature!", - getSocketAddress(), username); - } - } - - public BackendRPCSessionHandler getRPCSessionHandler() { - return backedRPCSessionHandler; - } - - public boolean getRPCEventSubscribed(EnumSubscribedEvent event) { - return backedRPCSessionHandler != null && backedRPCSessionHandler.isSubscribed(event); - } - - public void handleBackendRPCPacket(ServerConnection server, byte[] data) { - if(backedRPCSessionHandler != null) { - backedRPCSessionHandler.handleRPCPacket(server, data); - }else { - EaglerXVelocity.logger().error( - "[{}]: Server tried to send backend RPC packet to player \"{}\" but this feature is not enabled. Enable it by setting \"enable_backend_rpc_api: true\" in settings.yml", - getSocketAddress(), username); - } - } - - public void fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState state) { - EaglercraftVoiceStatusChangeEvent.EnumVoiceState oldState = lastVoiceState.getAndSet(state); - if(state != oldState) { - EaglerXVelocity.proxy().getEventManager().fireAndForget( - new EaglercraftVoiceStatusChangeEvent(getPlayerObj(), listener, this, oldState, state)); - } - } - - public String getEaglerBrandString() { - return clientBrandString; - } - - public String getEaglerVersionString() { - return clientVersionString; - } - - public UUID getClientBrandUUID() { - return clientBrandUUID; - } - - public byte[] getOtherProfileDataFromHandshake(String name) { - return otherProfileDataFromHanshake.get(name); - } - - public String getOrigin() { - return origin; - } - - public String getUserAgent() { - return userAgent; - } - - public EaglerListenerConfig getEaglerListenerConfig() { - return listener; - } - - public String getName() { - return username; - } - - public UUID getUniqueId() { - return playerUUID; - } - - public ConnectedPlayer getPlayerObj() { - return connInstance.userConnection; - } - - public VelocityServerConnection getConnectedServer() { - ConnectedPlayer conn = connInstance.userConnection; - return conn != null ? conn.getConnectedServer() : null; - } - - public boolean isOnlineMode() { - ConnectedPlayer conn = connInstance.userConnection; - return conn != null && conn.isOnlineMode(); - } - - public GameProfile getGameProfile() { - return gameProfile; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerUpdateSvc.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerUpdateSvc.java deleted file mode 100644 index 08867dc4..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/EaglerUpdateSvc.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; - -import com.velocitypowered.api.proxy.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.SHA1Digest; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerUpdateConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData.ClientCertificateHolder; - -public class EaglerUpdateSvc { - - private static final List certs = new ArrayList<>(); - private static final Map certsCache = new HashMap<>(); - - private static class CachedClientCertificate { - private final ClientCertificateHolder cert; - private final long lastModified; - public CachedClientCertificate(ClientCertificateHolder cert, long lastModified) { - this.cert = cert; - this.lastModified = lastModified; - } - } - - private static long lastDownload = 0l; - private static long lastEnumerate = 0l; - - public static void updateTick() { - Logger log = EaglerXVelocity.logger(); - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - EaglerUpdateConfig conf = EaglerXVelocity.getEagler().getConfig().getUpdateConfig(); - if(conf.isDownloadLatestCerts() && millis - lastDownload > (long)conf.getCheckForUpdatesEvery() * 1000l) { - lastDownload = millis; - lastEnumerate = 0l; - try { - downloadUpdates(); - }catch(Throwable t) { - log.error("Uncaught exception downloading certificates!"); - t.printStackTrace(); - } - millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - } - if(conf.isEnableEagcertFolder() && millis - lastEnumerate > 5000l) { - lastEnumerate = millis; - try { - enumerateEagcertDirectory(); - }catch(Throwable t) { - log.error("Uncaught exception reading eagcert directory!"); - t.printStackTrace(); - } - } - } - - private static void downloadUpdates() throws Throwable { - Logger log = EaglerXVelocity.logger(); - EaglerUpdateConfig conf = EaglerXVelocity.getEagler().getConfig().getUpdateConfig(); - File eagcert = new File(EaglerXVelocity.getEagler().getDataFolder(), "eagcert"); - if(!eagcert.isDirectory()) { - if(!eagcert.mkdirs()) { - log.error("Could not create directory: {}", eagcert.getAbsolutePath()); - return; - } - } - Set filenames = new HashSet<>(); - for(String str : conf.getDownloadCertURLs()) { - try { - URL url = new URL(str); - HttpURLConnection con = (HttpURLConnection)url.openConnection(); - con.setDoInput(true); - con.setDoOutput(false); - con.setRequestMethod("GET"); - con.setConnectTimeout(30000); - con.setReadTimeout(30000); - con.setRequestProperty("User-Agent", "Mozilla/5.0 " + EaglerXVelocityVersion.ID + "/" + EaglerXVelocityVersion.VERSION); - con.connect(); - int code = con.getResponseCode(); - if(code / 100 != 2) { - con.disconnect(); - throw new IOException("Response code was " + code); - } - ByteArrayOutputStream bao = new ByteArrayOutputStream(32767); - try(InputStream is = con.getInputStream()) { - byte[] readBuffer = new byte[1024]; - int c; - while((c = is.read(readBuffer, 0, 1024)) != -1) { - bao.write(readBuffer, 0, c); - } - } - byte[] done = bao.toByteArray(); - SHA1Digest digest = new SHA1Digest(); - digest.update(done, 0, done.length); - byte[] hash = new byte[20]; - digest.doFinal(hash, 0); - char[] hexchars = new char[40]; - for(int i = 0; i < 20; ++i) { - hexchars[i << 1] = hex[(hash[i] >> 4) & 15]; - hexchars[(i << 1) + 1] = hex[hash[i] & 15]; - } - String strr = "$dl." + new String(hexchars) + ".cert"; - filenames.add(strr); - File cacheFile = new File(eagcert, strr); - if(cacheFile.exists()) { - continue; // no change - } - try(OutputStream os = new FileOutputStream(cacheFile)) { - os.write(done); - } - log.info("Downloading new certificate: {}", str); - }catch(Throwable t) { - log.error("Failed to download certificate: {}", str); - log.error("Reason: {}", t.toString()); - } - } - long millis = System.currentTimeMillis(); - File[] dirList = eagcert.listFiles(); - for(int i = 0; i < dirList.length; ++i) { - File f = dirList[i]; - String n = f.getName(); - if(!n.startsWith("$dl.")) { - continue; - } - if(millis - f.lastModified() > 86400000l && !filenames.contains(n)) { - log.warn("Deleting stale certificate: {}", n); - if(!f.delete()) { - log.error("Failed to delete: {}", n); - } - } - } - } - - private static final char[] hex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - private static void enumerateEagcertDirectory() throws Throwable { - Logger log = EaglerXVelocity.logger(); - File eagcert = new File(EaglerXVelocity.getEagler().getDataFolder(), "eagcert"); - if(!eagcert.isDirectory()) { - if(!eagcert.mkdirs()) { - log.error("Could not create directory: {}", eagcert.getAbsolutePath()); - return; - } - } - boolean dirty = false; - File[] dirList = eagcert.listFiles(); - Set existingFiles = new HashSet<>(); - for(int i = 0; i < dirList.length; ++i) { - File f = dirList[i]; - String n = f.getName(); - long lastModified = f.lastModified(); - existingFiles.add(n); - CachedClientCertificate cc = certsCache.get(n); - if(cc != null) { - if(cc.lastModified != lastModified) { - try { - byte[] fileData = new byte[(int)f.length()]; - if(fileData.length > 0xFFFF) { - throw new IOException("File is too long! Max: 65535 bytes"); - } - try(FileInputStream fis = new FileInputStream(f)) { - for(int j = 0, k; (k = fis.read(fileData, j, fileData.length - j)) != -1 && j < fileData.length; j += k); - } - certsCache.remove(n); - ClientCertificateHolder ch = tryMakeHolder(fileData); - certsCache.put(n, new CachedClientCertificate(ch, lastModified)); - dirty = true; - sendCertificateToPlayers(ch); - log.info("Reloaded certificate: {}", f.getAbsolutePath()); - }catch(IOException ex) { - log.error("Failed to read: {}", f.getAbsolutePath()); - log.error("Reason: {}", ex.toString()); - } - } - continue; - } - try { - byte[] fileData = new byte[(int)f.length()]; - if(fileData.length > 0xFFFF) { - throw new IOException("File is too long! Max: 65535 bytes"); - } - try(FileInputStream fis = new FileInputStream(f)) { - for(int j = 0, k; j < fileData.length && (k = fis.read(fileData, j, fileData.length - j)) != -1; j += k); - } - ClientCertificateHolder ch = tryMakeHolder(fileData); - certsCache.put(n, new CachedClientCertificate(ch, lastModified)); - dirty = true; - sendCertificateToPlayers(ch); - log.info("Loaded certificate: {}", f.getAbsolutePath()); - }catch(IOException ex) { - log.error("Failed to read: {}", f.getAbsolutePath()); - log.error("Reason: {}", ex.toString()); - } - } - Iterator itr = certsCache.keySet().iterator(); - while(itr.hasNext()) { - String etr = itr.next(); - if(!existingFiles.contains(etr)) { - itr.remove(); - dirty = true; - log.warn("Certificate was deleted: {}", etr); - } - } - if(dirty) { - remakeCertsList(); - } - } - - private static void remakeCertsList() { - synchronized(certs) { - certs.clear(); - for(CachedClientCertificate cc : certsCache.values()) { - certs.add(cc.cert); - } - } - } - - public static List getCertList() { - return certs; - } - - public static ClientCertificateHolder tryMakeHolder(byte[] data) { - int hash = Arrays.hashCode(data); - ClientCertificateHolder ret = tryGetHolder(data, hash); - if(ret == null) { - ret = new ClientCertificateHolder(data, hash); - } - return ret; - } - - public static ClientCertificateHolder tryGetHolder(byte[] data, int hash) { - synchronized(certs) { - for(ClientCertificateHolder cc : certs) { - if(cc.hash == hash && Arrays.equals(cc.data, data)) { - return cc; - } - } - } - for(Player p : EaglerXVelocity.proxy().getAllPlayers()) { - EaglerPlayerData pp = EaglerPipeline.getEaglerHandle(p); - if(pp != null) { - if(pp.clientCertificate != null && pp.clientCertificate.hash == hash && Arrays.equals(pp.clientCertificate.data, data)) { - return pp.clientCertificate; - } - } - } - return null; - } - - public static void sendCertificateToPlayers(ClientCertificateHolder holder) { - for(Player p : EaglerXVelocity.proxy().getAllPlayers()) { - EaglerPlayerData pp = EaglerPipeline.getEaglerHandle(p); - if(pp != null) { - boolean bb; - synchronized(pp.certificatesSent) { - bb = pp.certificatesSent.contains(holder.hashCode()); - } - if(!bb) { - Set set = pp.certificatesToSend; - synchronized(set) { - set.add(holder); - } - } - } - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HandshakePacketTypes.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HandshakePacketTypes.java deleted file mode 100644 index 78129903..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HandshakePacketTypes.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -public class HandshakePacketTypes { - - public static final String AUTHENTICATION_REQUIRED = "Authentication Required:"; - - public static final int PROTOCOL_CLIENT_VERSION = 0x01; - public static final int PROTOCOL_SERVER_VERSION = 0x02; - public static final int PROTOCOL_VERSION_MISMATCH = 0x03; - public static final int PROTOCOL_CLIENT_REQUEST_LOGIN = 0x04; - public static final int PROTOCOL_SERVER_ALLOW_LOGIN = 0x05; - public static final int PROTOCOL_SERVER_DENY_LOGIN = 0x06; - public static final int PROTOCOL_CLIENT_PROFILE_DATA = 0x07; - public static final int PROTOCOL_CLIENT_FINISH_LOGIN = 0x08; - public static final int PROTOCOL_SERVER_FINISH_LOGIN = 0x09; - public static final int PROTOCOL_SERVER_ERROR = 0xFF; - - public static final int STATE_OPENED = 0x00; - public static final int STATE_CLIENT_VERSION = 0x01; - public static final int STATE_CLIENT_LOGIN = 0x02; - public static final int STATE_CLIENT_COMPLETE = 0x03; - public static final int STATE_STALLING = 0xFF; - - public static final int SERVER_ERROR_UNKNOWN_PACKET = 0x01; - public static final int SERVER_ERROR_INVALID_PACKET = 0x02; - public static final int SERVER_ERROR_WRONG_PACKET = 0x03; - public static final int SERVER_ERROR_EXCESSIVE_PROFILE_DATA = 0x04; - public static final int SERVER_ERROR_DUPLICATE_PROFILE_DATA = 0x05; - public static final int SERVER_ERROR_RATELIMIT_BLOCKED = 0x06; - public static final int SERVER_ERROR_RATELIMIT_LOCKED = 0x07; - public static final int SERVER_ERROR_CUSTOM_MESSAGE = 0x08; - public static final int SERVER_ERROR_AUTHENTICATION_REQUIRED = 0x09; - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpHandshakeHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpHandshakeHandler.java deleted file mode 100644 index 4ac389aa..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpHandshakeHandler.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; -import io.netty.util.ReferenceCountUtil; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftWebSocketOpenEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerRateLimiter; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.RateLimitStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpMemoryCache; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpWebServer; - -public class HttpHandshakeHandler extends ChannelInboundHandlerAdapter { - - private static final byte[] error429Bytes = "

    429 Too Many Requests
    (Try again later)

    ".getBytes(StandardCharsets.UTF_8); - - private final EaglerListenerConfig conf; - private boolean logExceptions; - private boolean healthCheck; - private InetSocketAddress haproxyRemoteAddr; - - public HttpHandshakeHandler(EaglerListenerConfig conf) { - this.conf = conf; - } - - public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if (msg instanceof HttpRequest) { - logExceptions = true; - EaglerConnectionInstance pingTracker = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - HttpRequest req = (HttpRequest) msg; - HttpHeaders headers = req.headers(); - - String rateLimitHost = null; - - SocketAddress addr; - if (conf.isForwardIp()) { - String str = headers.get(conf.getForwardIpHeader()); - if (str != null) { - rateLimitHost = str.split(",", 2)[0]; - try { - InetAddress inetAddr = InetAddress.getByName(rateLimitHost); - if(haproxyRemoteAddr != null) { - addr = new InetSocketAddress(inetAddr, haproxyRemoteAddr.getPort()); - }else { - addr = ctx.channel().remoteAddress(); - if(addr instanceof InetSocketAddress) { - addr = new InetSocketAddress(inetAddr, ((InetSocketAddress)addr).getPort()); - }else { - addr = new InetSocketAddress(inetAddr, 0); - } - } - ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).set(inetAddr); - } catch (UnknownHostException ex) { - EaglerXVelocity.logger().warn("[{}]: Connected with an invalid '{}' header, disconnecting...", ctx.channel().remoteAddress(), conf.getForwardIpHeader()); - ctx.close(); - return; - } - } else { - EaglerXVelocity.logger().warn("[{}]: Connected without a '{}' header, disconnecting...", ctx.channel().remoteAddress(), conf.getForwardIpHeader()); - ctx.close(); - return; - } - } else if(haproxyRemoteAddr != null) { - addr = haproxyRemoteAddr; - ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).set(haproxyRemoteAddr.getAddress()); - } else { - addr = ctx.channel().remoteAddress(); - if (addr instanceof InetSocketAddress) { - rateLimitHost = ((InetSocketAddress) addr).getAddress().getHostAddress(); - } - } - - EaglerRateLimiter ipRateLimiter = conf.getRatelimitIp(); - RateLimitStatus ipRateLimit = RateLimitStatus.OK; - - if (ipRateLimiter != null && rateLimitHost != null) { - ipRateLimit = ipRateLimiter.rateLimit(rateLimitHost); - } - - if (ipRateLimit == RateLimitStatus.LOCKED_OUT) { - ctx.close(); - return; - } - - if (headers.get(HttpHeaderNames.CONNECTION) != null && headers.get(HttpHeaderNames.CONNECTION).toLowerCase().contains("upgrade") && - "websocket".equalsIgnoreCase(headers.get(HttpHeaderNames.UPGRADE))) { - - String origin = headers.get(HttpHeaderNames.ORIGIN); - if (origin != null) { - ctx.channel().attr(EaglerPipeline.ORIGIN).set(origin); - } - String userAgent = headers.get(HttpHeaderNames.USER_AGENT); - if(userAgent != null) { - ctx.channel().attr(EaglerPipeline.USER_AGENT).set(userAgent); - } - - if (ipRateLimit == RateLimitStatus.OK) { - EaglercraftWebSocketOpenEvent evt = new EaglercraftWebSocketOpenEvent(ctx.channel(), conf, rateLimitHost, origin, userAgent); - try { - evt = EaglerXVelocity.proxy().getEventManager().fire(evt).join(); - }catch(Throwable t) { - ctx.close(); - return; - } - if(evt.isCancelled()) { - ctx.close(); - return; - } - ctx.channel().attr(EaglerPipeline.HOST).set(headers.get(HttpHeaderNames.HOST)); - ctx.pipeline().replace(this, "HttpWebSocketHandler", new HttpWebSocketHandler(conf)); - } - - WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( - "ws://" + headers.get(HttpHeaderNames.HOST) + req.uri(), null, true, 0xFFFFF); - WebSocketServerHandshaker hs = wsFactory.newHandshaker(req); - if (hs != null) { - pingTracker.isWebSocket = true; - ChannelFuture future = hs.handshake(ctx.channel(), req); - if (ipRateLimit != RateLimitStatus.OK) { - final RateLimitStatus rateLimitTypeFinal = ipRateLimit; - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture paramF) throws Exception { - ctx.writeAndFlush(new TextWebSocketFrame( - rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "LOCKED" : "BLOCKED")) - .addListener(ChannelFutureListener.CLOSE); - } - }); - } - } else { - WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()).addListener(ChannelFutureListener.CLOSE); - } - } else { - if (ipRateLimit != RateLimitStatus.OK) { - ByteBuf error429Buffer = ctx.alloc().buffer(error429Bytes.length, error429Bytes.length); - error429Buffer.writeBytes(error429Bytes); - DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.TOO_MANY_REQUESTS, error429Buffer); - ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); - return; - } - pingTracker.isRegularHttp = true; - HttpWebServer srv = conf.getWebServer(); - if (srv != null) { - String uri = req.uri(); - if (uri.startsWith("/")) { - uri = uri.substring(1); - } - int j = uri.indexOf('?'); - if (j != -1) { - uri = uri.substring(0, j); - } - HttpMemoryCache ch = srv.retrieveFile(uri); - if (ch != null) { - ctx.writeAndFlush(ch.createHTTPResponse()).addListener(ChannelFutureListener.CLOSE); - } else { - ctx.writeAndFlush(HttpWebServer.getWebSocket404().createHTTPResponse(HttpResponseStatus.NOT_FOUND)) - .addListener(ChannelFutureListener.CLOSE); - } - } else { - ctx.writeAndFlush(HttpWebServer.getWebSocket404().createHTTPResponse(HttpResponseStatus.NOT_FOUND)) - .addListener(ChannelFutureListener.CLOSE); - } - } - } else if (msg instanceof HAProxyMessage) { - logExceptions = true; - HAProxyMessage proxy = (HAProxyMessage) msg; - if(proxy.sourceAddress() != null) { - if(!conf.isForwardIp()) { - try { - haproxyRemoteAddr = new InetSocketAddress(proxy.sourceAddress(), proxy.sourcePort()); - }catch(IllegalArgumentException t) { - } - } - }else { - healthCheck = true; - } - } else { - ctx.close(); - } - } finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - if(logExceptions && !healthCheck) { - EaglerXVelocity.logger().warn("[Pre][{}]: Exception Caught: {}", ctx.channel().remoteAddress(), cause.toString(), cause); - } - ctx.close(); - } - } - - public void channelInactive(ChannelHandlerContext ctx) { - EaglerPipeline.closeChannel(ctx.channel()); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpServerQueryHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpServerQueryHandler.java deleted file mode 100644 index 665e4169..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpServerQueryHandler.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.util.ReferenceCountUtil; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query.QueryManager; - -public abstract class HttpServerQueryHandler extends ChannelInboundHandlerAdapter { - - public static class UnexpectedDataException extends RuntimeException { - public UnexpectedDataException() { - } - public UnexpectedDataException(String message, Throwable cause) { - super(message, cause); - } - public UnexpectedDataException(String message) { - super(message); - } - public UnexpectedDataException(Throwable cause) { - super(cause); - } - } - - private static final InetAddress localhost; - - static { - try { - localhost = InetAddress.getLocalHost(); - }catch(Throwable t) { - throw new RuntimeException("localhost doesn't exist?!", t); - } - } - - private EaglerListenerConfig conf; - private ChannelHandlerContext context; - private String accept; - private boolean acceptTextPacket = false; - private boolean acceptBinaryPacket = false; - private boolean hasClosed = false; - private boolean keepAlive = false; - private long maxAge = -1l; - - public void beginHandleQuery(EaglerListenerConfig conf, ChannelHandlerContext context, String accept) { - this.conf = conf; - this.context = context; - this.accept = accept; - begin(accept); - } - - protected void acceptText() { - acceptText(true); - } - - protected void acceptText(boolean bool) { - acceptTextPacket = bool; - } - - protected void acceptBinary() { - acceptBinary(true); - } - - protected void acceptBinary(boolean bool) { - acceptBinaryPacket = bool; - } - - public void close() { - context.close(); - hasClosed = true; - } - - public boolean isClosed() { - return hasClosed; - } - - public InetAddress getAddress() { - InetAddress addr = context.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr != null) { - return addr; - }else { - SocketAddress sockAddr = context.channel().remoteAddress(); - return sockAddr instanceof InetSocketAddress ? ((InetSocketAddress) sockAddr).getAddress() : localhost; - } - } - - public ChannelHandlerContext getContext() { - return context; - } - - public EaglerListenerConfig getListener() { - return conf; - } - - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if (msg instanceof WebSocketFrame) { - if (msg instanceof BinaryWebSocketFrame) { - handleBinary(ctx, ((BinaryWebSocketFrame) msg).content()); - } else if (msg instanceof TextWebSocketFrame) { - handleText(ctx, ((TextWebSocketFrame) msg).text()); - } else if (msg instanceof PingWebSocketFrame) { - ctx.writeAndFlush(new PongWebSocketFrame()); - } else if (msg instanceof CloseWebSocketFrame) { - ctx.close(); - } - }else if(msg instanceof HAProxyMessage) { - EaglerXVelocity.logger().warn("[{}]: Ignoring HAProxyMessage because the WebSocket connection has already been established", ctx.channel().remoteAddress()); - }else { - EaglerXVelocity.logger().error("Unexpected Packet: {}", msg.getClass().getSimpleName()); - } - } finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - EaglerXVelocity.logger().warn("[{}]: Exception Caught: {}", ctx.channel().remoteAddress(), cause.toString()); - } - } - - private void handleBinary(ChannelHandlerContext ctx, ByteBuf buffer) { - if(!acceptBinaryPacket) { - ctx.close(); - return; - } - byte[] packet = new byte[buffer.readableBytes()]; - buffer.readBytes(packet); - processBytes(packet); - } - - private void handleText(ChannelHandlerContext ctx, String str) { - if(!acceptTextPacket) { - ctx.close(); - return; - } - JsonObject obj = null; - if(str.indexOf('{') == 0) { - try { - obj = JsonParser.parseString(str).getAsJsonObject(); - }catch(JsonParseException ex) { - } - } - if(obj != null) { - processJson(obj); - }else { - processString(str); - } - } - - public void channelInactive(ChannelHandlerContext ctx) { - EaglerPipeline.closeChannel(ctx.channel()); - hasClosed = true; - closed(); - } - - public String getAccept() { - return accept; - } - - public String getOrigin() { - return context.channel().attr(EaglerPipeline.ORIGIN).get(); - } - - public String getUserAgent() { - return context.channel().attr(EaglerPipeline.USER_AGENT).get(); - } - - public void sendStringResponse(String type, String str) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createStringResponse(accept, str).toString())); - } - - public void sendStringResponseAndClose(String type, String str) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createStringResponse(accept, str).toString())).addListener(ChannelFutureListener.CLOSE); - } - - public void sendJsonResponse(String type, JsonObject obj) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createJsonObjectResponse(accept, obj).toString())); - } - - public void sendJsonResponseAndClose(String type, JsonObject obj) { - context.writeAndFlush(new TextWebSocketFrame(QueryManager.createJsonObjectResponse(accept, obj).toString())).addListener(ChannelFutureListener.CLOSE); - } - - public void sendBinaryResponse(byte[] bytes) { - context.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(bytes))); - } - - public void sendBinaryResponseAndClose(byte[] bytes) { - context.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(bytes))).addListener(ChannelFutureListener.CLOSE); - } - - public void setKeepAlive(boolean enable) { - keepAlive = enable; - } - - public boolean shouldKeepAlive() { - return keepAlive; - } - - public long getMaxAge() { - return maxAge; - } - - public void setMaxAge(long millis) { - this.maxAge = millis; - } - - protected abstract void begin(String queryType); - - protected abstract void processString(String str); - - protected abstract void processJson(JsonObject obj); - - protected abstract void processBytes(byte[] bytes); - - protected abstract void closed(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpWebSocketHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpWebSocketHandler.java deleted file mode 100644 index b33fcad4..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/HttpWebSocketHandler.java +++ /dev/null @@ -1,1643 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; - -import com.google.common.collect.Sets; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.velocitypowered.api.event.connection.*; -import com.velocitypowered.api.event.permission.PermissionsSetupEvent; -import com.velocitypowered.api.event.player.GameProfileRequestEvent; -import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent; -import com.velocitypowered.api.network.HandshakeIntent; -import com.velocitypowered.api.network.ProtocolVersion; -import com.velocitypowered.api.permission.PermissionFunction; -import com.velocitypowered.api.permission.PermissionProvider; -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.proxy.crypto.IdentifiedKey; -import com.velocitypowered.api.proxy.server.RegisteredServer; -import com.velocitypowered.api.util.GameProfile; -import com.velocitypowered.api.util.GameProfile.Property; -import com.velocitypowered.proxy.VelocityServer; -import com.velocitypowered.proxy.config.PlayerInfoForwarding; -import com.velocitypowered.proxy.connection.ConnectionTypes; -import com.velocitypowered.proxy.connection.MinecraftConnection; -import com.velocitypowered.proxy.connection.client.*; -import com.velocitypowered.proxy.network.Connections; -import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.StateRegistry; -import com.velocitypowered.proxy.protocol.netty.*; -import com.velocitypowered.proxy.protocol.packet.HandshakePacket; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.haproxy.HAProxyMessage; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import io.netty.util.ReferenceCountUtil; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import net.kyori.adventure.translation.GlobalTranslator; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.JSONLegacySerializer; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftClientBrandEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftHandleAuthCookieEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftHandleAuthPasswordEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftMOTDEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftRegisterCapeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftRegisterSkinEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent.AuthMethod; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftIsAuthRequiredEvent.AuthResponse; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.auth.DefaultAuthSystem; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.command.CommandConfirmCode; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.*; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query.MOTDQueryHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query.QueryManager; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.CapePackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinPackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.SkinService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; - -import static com.velocitypowered.proxy.network.Connections.*; - -public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { - - private static final Constructor stupidConstructor; - private static final Field remoteAddressField; - private static final Field stateField; - private static final Field protocolVersionField; - private static final Constructor stupid2Constructor; - private static final Method loginEventFiredMethod; - private static final Constructor stupid3Constructor; - private static final Constructor stupid3Constructor_new; - private static final Constructor stupid3Constructor_new_new; - private static final Method setPermissionFunctionMethod; - private static final Field defaultPermissionsField; - private static final Constructor stupid4Constructor; - static { - try { - stupidConstructor = InitialInboundConnection.class.getDeclaredConstructor(MinecraftConnection.class, String.class, HandshakePacket.class); - stupidConstructor.setAccessible(true); - remoteAddressField = MinecraftConnection.class.getDeclaredField("remoteAddress"); - remoteAddressField.setAccessible(true); - stateField = MinecraftConnection.class.getDeclaredField("state"); - stateField.setAccessible(true); - protocolVersionField = MinecraftConnection.class.getDeclaredField("protocolVersion"); - protocolVersionField.setAccessible(true); - stupid2Constructor = LoginInboundConnection.class.getDeclaredConstructor(InitialInboundConnection.class); - stupid2Constructor.setAccessible(true); - loginEventFiredMethod = LoginInboundConnection.class.getDeclaredMethod("loginEventFired", Runnable.class); - loginEventFiredMethod.setAccessible(true); - Constructor c3 = null; - Constructor c3_new = null; - Constructor c3_new_new = null; - try { - c3_new_new = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, String.class, boolean.class, HandshakeIntent.class, IdentifiedKey.class); - c3_new_new.setAccessible(true); - } catch (NoSuchMethodException e) { - try { - c3_new_new = null; - c3_new = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, String.class, boolean.class, IdentifiedKey.class); - c3_new.setAccessible(true); - } catch (NoSuchMethodException ee) { - c3_new = null; - c3 = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, boolean.class, IdentifiedKey.class); - c3.setAccessible(true); - } - } - stupid3Constructor = c3; - stupid3Constructor_new = c3_new; - stupid3Constructor_new_new = c3_new_new; - setPermissionFunctionMethod = ConnectedPlayer.class.getDeclaredMethod("setPermissionFunction", PermissionFunction.class); - setPermissionFunctionMethod.setAccessible(true); - defaultPermissionsField = ConnectedPlayer.class.getDeclaredField("DEFAULT_PERMISSIONS"); - defaultPermissionsField.setAccessible(true); - stupid4Constructor = InitialConnectSessionHandler.class.getDeclaredConstructor(ConnectedPlayer.class, VelocityServer.class); - stupid4Constructor.setAccessible(true); - } catch (NoSuchMethodException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - - private final EaglerListenerConfig conf; - - private int clientLoginState = HandshakePacketTypes.STATE_OPENED; - private int clientProtocolVersion = -1; - private boolean isProtocolExchanged = false; - private int gameProtocolVersion = -1; - private String clientBrandString; - private String clientVersionString; - private String clientUsername; - private UUID clientUUID; - private String clientRequestedServer; - private boolean clientAuth; - private byte[] clientAuthUsername; - private byte[] clientAuthPassword; - private boolean clientEnableCookie; - private byte[] clientCookieData; - private EaglercraftIsAuthRequiredEvent authRequireEvent; - private final Map profileData = new HashMap<>(); - private boolean hasFirstPacket = false; - private boolean hasBinaryConnection = false; - private boolean connectionClosed = false; - private InetAddress remoteAddress; - private String localAddrString; - private Property texturesOverrideProperty; - private boolean overrideEaglerToVanillaSkins; - - private static final Set profileDataStandard = Sets.newHashSet( - "skin_v1", "skin_v2", "cape_v1", "update_cert_v1", "brand_uuid_v1"); - - public HttpWebSocketHandler(EaglerListenerConfig conf) { - this.conf = conf; - } - - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - try { - if (msg instanceof WebSocketFrame) { - if (msg instanceof BinaryWebSocketFrame) { - handleBinary(ctx, ((BinaryWebSocketFrame) msg).content()); - } else if (msg instanceof TextWebSocketFrame) { - handleText(ctx, ((TextWebSocketFrame) msg).text()); - } else if (msg instanceof PingWebSocketFrame) { - ctx.writeAndFlush(new PongWebSocketFrame()); - } else if (msg instanceof CloseWebSocketFrame) { - ctx.close(); - } - }else if(msg instanceof HAProxyMessage) { - EaglerXVelocity.logger().warn("[{}]: Ignoring HAProxyMessage because the WebSocket connection has already been established", ctx.channel().remoteAddress()); - }else { - EaglerXVelocity.logger().error("Unexpected Packet: {}", msg.getClass().getSimpleName()); - } - } finally { - ReferenceCountUtil.release(msg); - } - } - - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (ctx.channel().isActive()) { - EaglerXVelocity.logger().warn("[Yee][{}]: Exception Caught: {}", ctx.channel().remoteAddress(), cause.toString()); - } - } - - private void handleBinary(ChannelHandlerContext ctx, ByteBuf buffer) { - if(connectionClosed) { - return; - } - if(!hasFirstPacket) { - if(buffer.readableBytes() >= 2) { - if(buffer.getByte(0) == (byte)2 && buffer.getByte(1) == (byte)69) { - handleLegacyClient(ctx, buffer); - return; - } - } - hasFirstPacket = true; - hasBinaryConnection = true; - - VelocityServer bungus = EaglerXVelocity.proxy(); - - if(conf.getMaxPlayer() > 0) { - int i = 0; - for(Player p : bungus.getAllPlayers()) { - EaglerPlayerData d = EaglerPipeline.getEaglerHandle(p); - if(d != null && d.getEaglerListenerConfig() == conf) { - ++i; - } - } - - if (i >= conf.getMaxPlayer()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full") - .addListener(ChannelFutureListener.CLOSE); - return; - } - } - - SocketAddress localSocketAddr = ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - - String limiterAddress = null; - RateLimitStatus loginRateLimit = RateLimitStatus.OK; - if(addr != null) { - remoteAddress = addr; - limiterAddress = addr.getHostAddress(); - }else { - if(localSocketAddr instanceof InetSocketAddress) { - remoteAddress = ((InetSocketAddress)localSocketAddr).getAddress(); - limiterAddress = remoteAddress.getHostAddress(); - }else { - remoteAddress = InetAddress.getLoopbackAddress(); - } - } - - EaglerRateLimiter limiter = conf.getRatelimitLogin(); - if(limiterAddress != null && limiter != null) { - loginRateLimit = limiter.rateLimit(limiterAddress); - } - - if(loginRateLimit == RateLimitStatus.LOCKED_OUT) { - connectionClosed = true; - ctx.close(); - return; - } - - if (loginRateLimit != RateLimitStatus.OK) { - sendErrorCode(ctx, - loginRateLimit == RateLimitStatus.LIMITED_NOW_LOCKED_OUT - ? HandshakePacketTypes.SERVER_ERROR_RATELIMIT_LOCKED - : HandshakePacketTypes.SERVER_ERROR_RATELIMIT_BLOCKED, - "Too many logins!").addListener(ChannelFutureListener.CLOSE); - return; - } - - localAddrString = localSocketAddr.toString(); - EaglerXVelocity.logger().info("[{}]: Connected via websocket", localAddrString); - if(addr != null) { - EaglerXVelocity.logger().info("[{}]: Real address is {}", localAddrString, addr.getHostAddress()); - } - String origin = ctx.channel().attr(EaglerPipeline.ORIGIN).get(); - if(origin != null) { - EaglerXVelocity.logger().info("[{}]: Origin header is {}", localAddrString, origin); - }else { - EaglerXVelocity.logger().info("[{}]: No origin header is present!", localAddrString); - } - }else if(!hasBinaryConnection) { - connectionClosed = true; - ctx.close(); - return; - } - int op = -1; - try { - op = buffer.readUnsignedByte(); - switch(op) { - case HandshakePacketTypes.PROTOCOL_CLIENT_VERSION: { - if(clientLoginState == HandshakePacketTypes.STATE_OPENED) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - EaglerXVelocity eaglerXBungee = EaglerXVelocity.getEagler(); - EaglerAuthConfig authConfig = eaglerXBungee.getConfig().getAuthConfig(); - - int eaglerLegacyProtocolVersion = buffer.readUnsignedByte(); - - if(eaglerLegacyProtocolVersion == 1) { - if(authConfig.isEnableAuthentication()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Please update your client to register on this server!") - .addListener(ChannelFutureListener.CLOSE); - return; - } else if (buffer.readUnsignedByte() != 47 || 47 < conf.getMinMCProtocol() - || 47 > conf.getMaxMCProtocol() || !conf.isAllowV3()) { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); - buf.writeByte(1); - buf.writeByte(1); - buf.writeByte(eaglerLegacyProtocolVersion); - String str = "Outdated Client"; - buf.writeByte(str.length()); - buf.writeCharSequence(str, StandardCharsets.US_ASCII); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(ChannelFutureListener.CLOSE); - return; - } - }else if(eaglerLegacyProtocolVersion == 2) { - //make sure to update VersionQueryHandler too - int minServerSupported = conf.isAllowV3() ? 2 : 4; - int maxServerSupported = conf.isAllowV4() ? 4 : 3; - int minAvailableProtVers = Integer.MAX_VALUE; - int maxAvailableProtVers = Integer.MIN_VALUE; - int protVers = -1; - - int cnt = buffer.readUnsignedShort(); - for(int i = 0; i < cnt; ++i) { - int j = buffer.readUnsignedShort(); - if(j > maxAvailableProtVers) { - maxAvailableProtVers = j; - } - if(j < minAvailableProtVers) { - minAvailableProtVers = j; - } - if(j >= minServerSupported && j <= maxServerSupported && j > protVers) { - protVers = j; - } - } - - int minGameVers = conf.getMinMCProtocol(); - int maxGameVers = conf.getMaxMCProtocol(); - int minAvailableGameVers = Integer.MAX_VALUE; - int maxAvailableGameVers = Integer.MIN_VALUE; - int gameVers = -1; - - cnt = buffer.readUnsignedShort(); - for(int i = 0; i < cnt; ++i) { - int j = buffer.readUnsignedShort(); - if(j > maxAvailableGameVers) { - maxAvailableGameVers = j; - } - if(j < minAvailableGameVers) { - minAvailableGameVers = j; - } - if(j >= minGameVers && j <= maxGameVers && j > gameVers) { - gameVers = j; - } - } - - if(maxAvailableProtVers == Integer.MIN_VALUE || maxAvailableGameVers == Integer.MIN_VALUE) { - throw new IOException(); - } - - boolean versMisMatch = false; - boolean isServerProbablyOutdated = false; - boolean isClientProbablyOutdated = false; - if(protVers == -1) { - clientProtocolVersion = maxAvailableProtVers < 3 ? 2 : 3; - versMisMatch = true; - isServerProbablyOutdated = minAvailableProtVers > maxServerSupported && maxAvailableProtVers > maxServerSupported; - isClientProbablyOutdated = minAvailableProtVers < minServerSupported && maxAvailableProtVers < minServerSupported; - }else { - clientProtocolVersion = protVers; - if(gameVers == -1) { - versMisMatch = true; - isServerProbablyOutdated = minAvailableGameVers > maxGameVers && maxAvailableGameVers > maxGameVers; - isClientProbablyOutdated = minAvailableGameVers < minGameVers && maxAvailableGameVers < minGameVers; - }else { - gameProtocolVersion = gameVers; - } - } - - if(versMisMatch) { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); - - buf.writeShort((conf.isAllowV3() ? 2 : 0) + (conf.isAllowV4() ? 1 : 0)); - if(conf.isAllowV3()) { - buf.writeShort(2); - buf.writeShort(3); - } - if(conf.isAllowV4()) { - buf.writeShort(4); - } - - buf.writeShort(2); - buf.writeShort(minGameVers); - buf.writeShort(maxGameVers); - - String str = isClientProbablyOutdated ? "Outdated Client" : (isServerProbablyOutdated ? "Outdated Server" : "Unsupported Client Version"); - buf.writeByte(str.length()); - buf.writeCharSequence(str, StandardCharsets.US_ASCII); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(ChannelFutureListener.CLOSE); - return; - } - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Legacy protocol version should always be '2' on post-snapshot clients") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - int strlen = buffer.readUnsignedByte(); - String eaglerBrand = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedByte(); - String eaglerVersionString = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - - if(eaglerLegacyProtocolVersion >= 2) { - clientAuth = buffer.readBoolean(); - strlen = buffer.readUnsignedByte(); - clientAuthUsername = new byte[strlen]; - buffer.readBytes(clientAuthUsername); - } - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - boolean useSnapshotFallbackProtocol = false; - if(eaglerLegacyProtocolVersion == 1 && !authConfig.isEnableAuthentication()) { - clientProtocolVersion = 2; - gameProtocolVersion = 47; - useSnapshotFallbackProtocol = true; - clientAuth = false; - clientAuthUsername = null; - } - - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr == null) { - SocketAddress remoteSocketAddr = ctx.channel().remoteAddress(); - if(remoteSocketAddr instanceof InetSocketAddress) { - addr = ((InetSocketAddress)remoteSocketAddr).getAddress(); - }else { - addr = InetAddress.getLoopbackAddress(); - } - } - - EaglercraftClientBrandEvent brandEvent = new EaglercraftClientBrandEvent(eaglerBrand, eaglerVersionString, - ctx.channel().attr(EaglerPipeline.ORIGIN).get(), clientProtocolVersion, addr); - brandEvent = eaglerXBungee.getProxy().getEventManager().fire(brandEvent).join(); - if(brandEvent.isCancelled()) { - Component kickReason = brandEvent.getMessage(); - if(kickReason == null) { - kickReason = Component.text("End of stream"); - } - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, kickReason) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final boolean final_useSnapshotFallbackProtocol = useSnapshotFallbackProtocol; - Runnable continueThread = () -> { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_VERSION; - clientBrandString = eaglerBrand; - clientVersionString = eaglerVersionString; - - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_VERSION); - - if(final_useSnapshotFallbackProtocol) { - buf.writeByte(1); - }else { - buf.writeShort(clientProtocolVersion); - buf.writeShort(gameProtocolVersion); - } - - String brandStr = EaglerXVelocityVersion.NAME; - buf.writeByte(brandStr.length()); - buf.writeCharSequence(brandStr, StandardCharsets.US_ASCII); - - String versStr = EaglerXVelocityVersion.VERSION; - buf.writeByte(versStr.length()); - buf.writeCharSequence(versStr, StandardCharsets.US_ASCII); - - if(!authConfig.isEnableAuthentication() || !clientAuth) { - buf.writeByte(0); - buf.writeShort(0); - }else { - int meth = getAuthMethodId(authRequireEvent.getUseAuthType()); - - if(meth == -1) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error("[{}]: Disconnecting, unsupported AuthMethod: {}", localAddrString, authRequireEvent.getUseAuthType()); - return; - } - - buf.writeByte(meth); - - byte[] saltingData = authRequireEvent.getSaltingData(); - if(saltingData != null) { - buf.writeShort(saltingData.length); - buf.writeBytes(saltingData); - }else { - buf.writeShort(0); - } - } - - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - isProtocolExchanged = true; - }; - - authRequireEvent = null; - if(authConfig.isEnableAuthentication()) { - String origin = ctx.channel().attr(EaglerPipeline.ORIGIN).get(); - try { - authRequireEvent = new EaglercraftIsAuthRequiredEvent(conf, remoteAddress, origin, - clientAuth, clientAuthUsername, (reqAuthEvent) -> { - if(authRequireEvent.shouldKickUser()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, authRequireEvent.getKickMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - AuthResponse resp = authRequireEvent.getAuthRequired(); - if(resp == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error("[{}]: Disconnecting, no installed authentication system handled: {}", localAddrString, authRequireEvent); - return; - } - - if(resp == AuthResponse.DENY) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, authRequireEvent.getKickMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - AuthMethod type = authRequireEvent.getUseAuthType(); - if(type == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not fully handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error("[{}]: Disconnecting, no authentication method provided by handler", localAddrString); - return; - } - - int typeId = getAuthMethodId(type); - if(typeId == -1) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error("[{}]: Disconnecting, unsupported AuthMethod: {}", localAddrString, type); - return; - } - - if(!clientAuth && resp == AuthResponse.REQUIRE) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_AUTHENTICATION_REQUIRED, - HandshakePacketTypes.AUTHENTICATION_REQUIRED + " [" + typeId + "] " + authRequireEvent.getAuthMessage()) - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().info("[{}]: Displaying authentication screen", localAddrString); - return; - }else { - if(authRequireEvent.getUseAuthType() == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not fully handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error("[{}]: Disconnecting, no authentication method provided by handler", localAddrString); - return; - } - } - continueThread.run(); - }); - - if(authConfig.isUseBuiltInAuthentication()) { - DefaultAuthSystem authSystem = eaglerXBungee.getAuthService(); - if(authSystem != null) { - authSystem.handleIsAuthRequiredEvent(authRequireEvent); - } - }else { - authRequireEvent = eaglerXBungee.getProxy().getEventManager().fire(authRequireEvent).join(); - } - - if(!authRequireEvent.isAsyncContinue()) { - authRequireEvent.doDirectContinue(); - } - }catch(Throwable t) { - throw new EventException(t); - } - }else { - continueThread.run(); - } - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_OPENED").addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_REQUEST_LOGIN: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_VERSION) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - - int strlen = buffer.readUnsignedByte(); - clientUsername = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - - if(!clientUsername.equals(clientUsername.replaceAll("[^A-Za-z0-9_]", "_"))) { - sendLoginDenied(ctx, "Invalid characters in username") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientUsername.length() < 3) { - sendLoginDenied(ctx, "Username must be at least 3 characters") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientUsername.length() > 16) { - sendLoginDenied(ctx, "Username must be under 16 characters") - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if(clientAuthUsername == null) { - clientAuthUsername = new byte[strlen]; - for(int i = 0; i < strlen; ++i) { - clientAuthUsername[i] = (byte)clientUsername.charAt(i); - } - } - - String offlinePlayerStr = "OfflinePlayer:"; - byte[] uuidHashGenerator = new byte[offlinePlayerStr.length() + clientAuthUsername.length]; - System.arraycopy(offlinePlayerStr.getBytes(StandardCharsets.US_ASCII), 0, uuidHashGenerator, 0, offlinePlayerStr.length()); - System.arraycopy(clientAuthUsername, 0, uuidHashGenerator, offlinePlayerStr.length(), clientAuthUsername.length); - clientUUID = UUID.nameUUIDFromBytes(uuidHashGenerator); - - strlen = buffer.readUnsignedByte(); - clientRequestedServer = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedByte(); - clientAuthPassword = new byte[strlen]; - buffer.readBytes(clientAuthPassword); - - if(clientProtocolVersion >= 4) { - clientEnableCookie = buffer.readBoolean(); - strlen = buffer.readUnsignedByte(); - if(clientEnableCookie && strlen > 0) { - clientCookieData = new byte[strlen]; - buffer.readBytes(clientCookieData); - }else { - if(strlen > 0) { - throw new IllegalArgumentException("Unexpected cookie"); - } - clientCookieData = null; - } - }else { - clientEnableCookie = false; - clientCookieData = null; - } - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - Runnable continueThread = () -> { - - final VelocityServer bungee = EaglerXVelocity.proxy(); - if (bungee.getPlayer(clientUsername).isPresent()) { - sendLoginDenied(ctx, LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - clientLoginState = HandshakePacketTypes.STATE_CLIENT_LOGIN; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ALLOW_LOGIN); - buf.writeByte(clientUsername.length()); - buf.writeCharSequence(clientUsername, StandardCharsets.US_ASCII); - buf.writeLong(clientUUID.getMostSignificantBits()); - buf.writeLong(clientUUID.getLeastSignificantBits()); - ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - }; - - EaglerXVelocity eaglerXBungee = EaglerXVelocity.getEagler(); - EaglerAuthConfig authConfig = eaglerXBungee.getConfig().getAuthConfig(); - - if(authConfig.isEnableAuthentication()) { - if(clientAuth && clientAuthPassword.length > 0) { - EaglercraftHandleAuthPasswordEvent handleEvent = new EaglercraftHandleAuthPasswordEvent( - conf, remoteAddress, authRequireEvent.getOriginHeader(), clientAuthUsername, - authRequireEvent.getSaltingData(), clientUsername, clientUUID, - clientAuthPassword, clientEnableCookie, clientCookieData, - authRequireEvent.getUseAuthType(), authRequireEvent.getAuthMessage(), - (Object) authRequireEvent.getAuthAttachment(), clientRequestedServer, - (handleAuthEvent) -> { - - if(handleAuthEvent.getLoginAllowed() != EaglercraftHandleAuthPasswordEvent.AuthResponse.ALLOW) { - sendLoginDenied(ctx, handleAuthEvent.getLoginDeniedMessage()).addListener(ChannelFutureListener.CLOSE); - return; - } - - clientUsername = handleAuthEvent.getProfileUsername(); - clientUUID = handleAuthEvent.getProfileUUID(); - - String texPropOverrideValue = handleAuthEvent.getApplyTexturesPropertyValue(); - if(texPropOverrideValue != null) { - String texPropOverrideSig = handleAuthEvent.getApplyTexturesPropertySignature(); - texturesOverrideProperty = new Property("textures", texPropOverrideValue, texPropOverrideSig); - } - - overrideEaglerToVanillaSkins = handleAuthEvent.isOverrideEaglerToVanillaSkins(); - - continueThread.run(); - }); - - if(authConfig.isUseBuiltInAuthentication()) { - DefaultAuthSystem authSystem = eaglerXBungee.getAuthService(); - if(authSystem != null) { - authSystem.handleAuthPasswordEvent(handleEvent); - } - }else { - eaglerXBungee.getProxy().getEventManager().fire(handleEvent).join(); - } - - if(!handleEvent.isAsyncContinue()) { - handleEvent.doDirectContinue(); - } - }else if(authRequireEvent.getEnableCookieAuth()) { - EaglercraftHandleAuthCookieEvent handleEvent = new EaglercraftHandleAuthCookieEvent( - conf, remoteAddress, authRequireEvent.getOriginHeader(), clientAuthUsername, - clientUsername, clientUUID, clientEnableCookie, clientCookieData, - authRequireEvent.getUseAuthType(), authRequireEvent.getAuthMessage(), - (Object) authRequireEvent.getAuthAttachment(), - clientRequestedServer, (handleAuthEvent) -> { - - EaglercraftHandleAuthCookieEvent.AuthResponse resp = handleAuthEvent.getLoginAllowed(); - - if(resp == null) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "EaglercraftHandleAuthCookieEvent was not handled") - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().error( - "[{}]: Disconnecting, no installed authentication system handled: {}", - localAddrString, handleAuthEvent.toString()); - return; - } - - if(resp == EaglercraftHandleAuthCookieEvent.AuthResponse.DENY) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, handleAuthEvent.getLoginDeniedMessage()) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - clientUsername = handleAuthEvent.getProfileUsername(); - clientUUID = handleAuthEvent.getProfileUUID(); - - String texPropOverrideValue = handleAuthEvent.getApplyTexturesPropertyValue(); - if(texPropOverrideValue != null) { - String texPropOverrideSig = handleAuthEvent.getApplyTexturesPropertySignature(); - texturesOverrideProperty = new Property("textures", texPropOverrideValue, texPropOverrideSig); - } - - overrideEaglerToVanillaSkins = handleAuthEvent.isOverrideEaglerToVanillaSkins(); - - if(resp == EaglercraftHandleAuthCookieEvent.AuthResponse.ALLOW) { - continueThread.run(); - return; - } - - if(!clientAuth && resp == EaglercraftHandleAuthCookieEvent.AuthResponse.REQUIRE_AUTH) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_AUTHENTICATION_REQUIRED, HandshakePacketTypes.AUTHENTICATION_REQUIRED - + " [" + getAuthMethodId(authRequireEvent.getUseAuthType()) + "] " + authRequireEvent.getAuthMessage()) - .addListener(ChannelFutureListener.CLOSE); - EaglerXVelocity.logger().info("[{}]: Displaying authentication screen", localAddrString); - return; - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Failed to handle authentication!") - .addListener(ChannelFutureListener.CLOSE); - return; - } - }); - - handleEvent = eaglerXBungee.getProxy().getEventManager().fire(handleEvent).join(); - - if(!handleEvent.isAsyncContinue()) { - handleEvent.doDirectContinue(); - } - }else { - if(authRequireEvent.getAuthRequired() != EaglercraftIsAuthRequiredEvent.AuthResponse.SKIP) { - sendLoginDenied(ctx, "Client provided no authentication code").addListener(ChannelFutureListener.CLOSE); - return; - }else { - continueThread.run(); - } - } - }else { - continueThread.run(); - } - - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_CLIENT_VERSION") - .addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_LOGIN) { - if(clientProtocolVersion <= 3) { - if(profileData.size() >= 12) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_EXCESSIVE_PROFILE_DATA, "Too many profile data packets recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - int strlen = buffer.readUnsignedByte(); - String dataType = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedShort(); - byte[] readData = new byte[strlen]; - buffer.readBytes(readData); - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - if(!profileData.containsKey(dataType)) { - profileData.put(dataType, readData); - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_DUPLICATE_PROFILE_DATA, "Multiple profile data packets of the same type recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - }else { - int count = buffer.readUnsignedByte(); - if(profileData.size() + count > 12) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_EXCESSIVE_PROFILE_DATA, "Too many profile data packets recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - for(int i = 0; i < count; ++i) { - int strlen = buffer.readUnsignedByte(); - String dataType = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - strlen = buffer.readUnsignedShort(); - byte[] readData = new byte[strlen]; - buffer.readBytes(readData); - if(!profileData.containsKey(dataType)) { - profileData.put(dataType, readData); - }else { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_DUPLICATE_PROFILE_DATA, "Multiple profile data packets of the same type recieved") - .addListener(ChannelFutureListener.CLOSE); - return; - } - } - - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - } - - }else { - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorWrong(ctx, op, "STATE_CLIENT_LOGIN").addListener(ChannelFutureListener.CLOSE); - } - } - break; - case HandshakePacketTypes.PROTOCOL_CLIENT_FINISH_LOGIN: { - if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_LOGIN) { - clientLoginState = HandshakePacketTypes.STATE_STALLING; - if(buffer.isReadable()) { - throw new IllegalArgumentException("Packet too long"); - } - - finish(ctx); - - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - }else { - sendErrorWrong(ctx, op, "STATE_CLIENT_LOGIN").addListener(ChannelFutureListener.CLOSE); - } - } - break; - default: - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_UNKNOWN_PACKET, "Unknown Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); - break; - } - }catch(Throwable ex) { - ex.printStackTrace(); - if(ex instanceof EventException) { - EaglerXVelocity.logger().error("[{}]: Hanshake packet {} caught an exception", localAddrString, op, ex.getCause()); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_INVALID_PACKET, op == -1 ? - "Invalid Packet" : "Invalid Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); - } - } - - private void finish(final ChannelHandlerContext ctx) { - final VelocityServer bungee = EaglerXVelocity.proxy(); - - if(conf.getMaxPlayer() > 0) { - int i = 0; - for(Player p : bungee.getAllPlayers()) { - EaglerPlayerData playerData = EaglerPipeline.getEaglerHandle(p); - if(playerData != null && playerData.getEaglerListenerConfig() == conf) { - ++i; - } - } - - if (i >= conf.getMaxPlayer()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full") - .addListener(ChannelFutureListener.CLOSE); - connectionClosed = true; - return; - } - } - - final String usernameStr = clientUsername.toString(); - if (bungee.getPlayer(usernameStr).isPresent()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - InetSocketAddress baseAddress = (InetSocketAddress)ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - if(addr != null) { - baseAddress = new InetSocketAddress(addr, baseAddress.getPort()); - } - final InetSocketAddress final_baseAddress = baseAddress; - - ProtocolVersion protocolVers = ProtocolVersion.getProtocolVersion(gameProtocolVersion); - if(!protocolVers.isSupported()) { - //TODO: localize somehow - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Outdated Client!").addListener(ChannelFutureListener.CLOSE); - return; - } - - InetSocketAddress localAddress = (InetSocketAddress)ctx.channel().localAddress(); - String hostName = localAddress.getHostString(); - HandshakePacket fakeHandshake = new HandshakePacket(); - fakeHandshake.setIntent(HandshakeIntent.LOGIN); - fakeHandshake.setProtocolVersion(protocolVers); - fakeHandshake.setServerAddress(hostName); - fakeHandshake.setPort(localAddress.getPort()); - - final MinecraftConnection con = new MinecraftConnection(ctx.channel(), bungee); - - try { - remoteAddressField.set(con, baseAddress); - stateField.set(con, StateRegistry.LOGIN); - protocolVersionField.set(con, protocolVers); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - - con.setType(ConnectionTypes.VANILLA); - - EaglerVelocityConfig eaglerConf = EaglerXVelocity.getEagler().getConfig(); - - EaglerUpdateConfig updateconf = eaglerConf.getUpdateConfig(); - boolean blockUpdate = updateconf.isBlockAllClientUpdates(); - EaglerPlayerData.ClientCertificateHolder mycert = null; - if(!blockUpdate && !updateconf.isDiscardLoginPacketCerts()) { - byte[] b = profileData.get("update_cert_v1"); - if(b != null && b.length < 32759) { - EaglerUpdateSvc.sendCertificateToPlayers(mycert = EaglerUpdateSvc.tryMakeHolder(b)); - } - } - final EaglerPlayerData.ClientCertificateHolder cert = mycert; - - UUID clientBrandUUID = null; - String clientBrandAsString = clientBrandString.toString(); - byte[] brandUUIDBytes = profileData.get("brand_uuid_v1"); - if(brandUUIDBytes != null) { - if(brandUUIDBytes.length == 16) { - ByteBuf buf = Unpooled.wrappedBuffer(brandUUIDBytes); - clientBrandUUID = new UUID(buf.readLong(), buf.readLong()); - if (clientBrandUUID.equals(EaglerXVelocityAPIHelper.BRAND_NULL_UUID) - || clientBrandUUID.equals(EaglerXVelocityAPIHelper.BRAND_PENDING_UUID) - || clientBrandUUID.equals(EaglerXVelocityAPIHelper.BRAND_VANILLA_UUID)) { - clientBrandUUID = null; - } - } - }else { - clientBrandUUID = EaglerXVelocityAPIHelper.makeClientBrandUUIDLegacy(clientBrandAsString); - } - final UUID final_clientBrandUUID = clientBrandUUID; - final Map otherProfileData = new HashMap<>(); - for(Entry etr2 : profileData.entrySet()) { - String str = etr2.getKey(); - if(!profileDataStandard.contains(str)) { - otherProfileData.put(str, etr2.getValue()); - } - } - InitialInboundConnection inboundCon; - try { - inboundCon = stupidConstructor.newInstance(con, cleanVhost(hostName), fakeHandshake); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - - if (!bungee.getIpAttemptLimiter().attempt(baseAddress.getAddress())) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.logging-in-too-fast", NamedTextColor.RED), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - if (bungee.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN - && protocolVers.lessThan(ProtocolVersion.MINECRAFT_1_13)) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.modern-forwarding-needs-new-client", NamedTextColor.RED), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - LoginInboundConnection lic; - try { - lic = stupid2Constructor.newInstance(inboundCon); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - bungee.getEventManager().fireAndForget(new ConnectionHandshakeEvent(inboundCon, fakeHandshake.getIntent())); - - PreLoginEvent event1 = new PreLoginEvent(lic, usernameStr, clientUUID); - bungee.getEventManager().fire(event1).thenRunAsync(() -> { - if (con.isClosed()) { - return; - } - - PreLoginEvent.PreLoginComponentResult result = event1.getResult(); - Optional disconnectReason = result.getReasonComponent(); - if (disconnectReason.isPresent()) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - GlobalTranslator.render(disconnectReason.get(), Locale.getDefault())) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - try { - loginEventFiredMethod.invoke(lic, (Runnable) () -> { - if (con.isClosed()) { - return; - } - - con.eventLoop().execute(() -> { - List daprops; - if(eaglerConf.getEnableIsEaglerPlayerProperty()) { - daprops = Arrays.asList(EaglerVelocityConfig.isEaglerProperty); - }else { - daprops = new ArrayList<>(0); - } - GameProfile profile = con.getType().addGameProfileTokensIfRequired(new GameProfile(clientUUID, usernameStr, daprops), bungee.getConfiguration().getPlayerInfoForwardingMode()); - GameProfileRequestEvent profileRequestEvent = new GameProfileRequestEvent(lic, profile, false); - bungee.getEventManager().fire(profileRequestEvent).thenComposeAsync((Function>) (profileEvent) -> { - if (con.isClosed()) { - return CompletableFuture.completedFuture(null); - } else { - GameProfile gp = profileRequestEvent.getGameProfile(); - if(eaglerConf.getEnableIsEaglerPlayerProperty()) { - gp = gp.addProperty(EaglerVelocityConfig.isEaglerProperty); - } - - ConnectedPlayer player; - if(stupid3Constructor_new_new != null) { - try { - player = stupid3Constructor_new_new.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), lic.getRawVirtualHost().orElse(null), false, HandshakeIntent.LOGIN, lic.getIdentifiedKey()); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - }else if(stupid3Constructor_new != null) { - try { - player = stupid3Constructor_new.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), lic.getRawVirtualHost().orElse(null), false, lic.getIdentifiedKey()); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - }else { - try { - player = stupid3Constructor.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), false, lic.getIdentifiedKey()); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - con.setAssociation(player); - - if (!bungee.canRegisterConnection(player)) { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return CompletableFuture.completedFuture(null); - } else { - boolean doRegisterSkins = true; - boolean doForceSkins = false; - - EaglercraftRegisterSkinEvent registerSkinEvent = bungee.getEventManager() - .fire(new EaglercraftRegisterSkinEvent(usernameStr, clientUUID, - authRequireEvent != null ? authRequireEvent.getAuthAttachment() : null)).join(); - - Property prop = registerSkinEvent.getForceUseMojangProfileProperty(); - boolean useExistingProp = registerSkinEvent.getForceUseLoginResultObjectTextures(); - if(prop != null) { - texturesOverrideProperty = prop; - overrideEaglerToVanillaSkins = true; - if(clientProtocolVersion >= 4 && (EaglerXVelocity.getEagler().getSkinService() instanceof SkinService)) { - doForceSkins = true; - } - }else { - if(useExistingProp) { - overrideEaglerToVanillaSkins = true; - }else { - byte[] custom = registerSkinEvent.getForceSetUseCustomPacket(); - if(custom != null) { - profileData.remove("skin_v2"); - profileData.put("skin_v1", custom); - overrideEaglerToVanillaSkins = false; - if(clientProtocolVersion >= 4) { - doForceSkins = true; - } - } - } - } - - if(texturesOverrideProperty != null) { - gp = gp.addProperties(Arrays.asList(texturesOverrideProperty, EaglerVelocityConfig.isEaglerProperty)); - player.setGameProfileProperties(gp.getProperties()); - }else { - if(!useExistingProp) { - String vanillaSkin = eaglerConf.getEaglerPlayersVanillaSkin(); - if(vanillaSkin != null) { - gp = gp.addProperties(Arrays.asList(eaglerConf.getEaglerPlayersVanillaSkinProperties())); - player.setGameProfileProperties(gp.getProperties()); - } - } - } - - if(overrideEaglerToVanillaSkins) { - List props = gp.getProperties(); - if(props != null) { - for(int i = 0; i < props.size(); ++i) { - if("textures".equals(props.get(i).getName())) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.getDecoder().decode(props.get(i).getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = SkinService.sanitizeTextureURL(url.getAsString()); - EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(urlStr, gp.getId()); - } - } - doRegisterSkins = false; - if(clientProtocolVersion >= 4) { - doForceSkins = true; - } - }catch(Throwable t) { - } - break; - } - } - } - } - - if(doRegisterSkins) { - if(clientProtocolVersion >= 4 && profileData.containsKey("skin_v2")) { - try { - SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v2"), - EaglerXVelocity.getEagler().getSkinService(), 4); - } catch (Throwable ex) { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService()); - EaglerXVelocity.logger().info("[{}]: Invalid skin packet: {}", ctx.channel().remoteAddress(), ex.toString()); - } - }else if(profileData.containsKey("skin_v1")) { - try { - SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v1"), - EaglerXVelocity.getEagler().getSkinService(), 3); - } catch (Throwable ex) { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService()); - EaglerXVelocity.logger().info("[{}]: Invalid skin packet: {}", ctx.channel().remoteAddress(), ex.toString()); - } - }else { - SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService()); - } - } - - EaglercraftRegisterCapeEvent registerCapeEvent = bungee.getEventManager().fire(new EaglercraftRegisterCapeEvent(usernameStr, - clientUUID, authRequireEvent != null ? authRequireEvent.getAuthAttachment() : null)).join(); - - byte[] forceCape = registerCapeEvent.getForceSetUseCustomPacket(); - if(forceCape != null) { - profileData.put("cape_v1", forceCape); - } - - if(profileData.containsKey("cape_v1")) { - try { - CapePackets.registerEaglerPlayer(clientUUID, profileData.get("cape_v1"), - EaglerXVelocity.getEagler().getCapeService()); - } catch (Throwable ex) { - CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService()); - EaglerXVelocity.logger().info("[{}]: Invalid cape packet: {}", ctx.channel().remoteAddress(), ex.toString()); - } - }else { - CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService()); - } - - EaglerConnectionInstance connInstance = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - EaglerPlayerData epd = connInstance.eaglerData = new EaglerPlayerData(connInstance, - conf, clientProtocolVersion, gameProtocolVersion, clientBrandString, - clientVersionString, final_clientBrandUUID, clientUsername, clientUUID, - final_baseAddress, ctx.channel().attr(EaglerPipeline.ORIGIN).get(), - ctx.channel().attr(EaglerPipeline.USER_AGENT).get(), cert, - clientEnableCookie, clientCookieData, otherProfileData, player.getGameProfile()); - - epd.messageProtocolController = new GameProtocolMessageController(player, - GamePluginMessageProtocol.getByVersion(clientProtocolVersion), - GameProtocolMessageController.createServerHandler(clientProtocolVersion, player, - epd, EaglerXVelocity.getEagler()), conf.getDefragSendDelay()); - - if(doForceSkins) { - EaglerXVelocity.getEagler().getSkinService().processForceSkin(clientUUID, epd); - } - if(forceCape != null && clientProtocolVersion >= 4) { - EaglerXVelocity.getEagler().getCapeService().processForceCape(clientUUID, epd); - } - - EaglerXVelocity.logger().info("{} has connected", player); - if(conf.getEnableVoiceChat()) { - EaglerXVelocity.getEagler().getVoiceService().handlePlayerLoggedIn(epd); - } - - if(clientProtocolVersion >= 4) { - SPacketCustomizePauseMenuV4EAG pauseMenuPkt = EaglerXVelocity.getEagler().getConfig().getPauseMenuConf().getPacket(); - if(pauseMenuPkt != null) { - epd.sendEaglerMessage(pauseMenuPkt); - } - } - - if(!blockUpdate) { - List set = EaglerUpdateSvc.getCertList(); - synchronized(set) { - epd.certificatesToSend.addAll(set); - } - for (Player p : bungee.getAllPlayers()) { - EaglerPlayerData ppp = EaglerPipeline.getEaglerHandle(p); - if(ppp != null && ppp.clientCertificate != null && ppp.clientCertificate != cert) { - epd.certificatesToSend.add(ppp.clientCertificate); - } - } - } - - PermissionProvider prov; - try { - prov = (PermissionProvider) defaultPermissionsField.get(null); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - return bungee.getEventManager().fire(new PermissionsSetupEvent(player, prov)).thenAcceptAsync((event) -> { - if (!con.isClosed()) { - PermissionFunction function = event.createFunction(player); - if (function == null) { - EaglerXVelocity.logger().error("A plugin permission provider {} provided an invalid permission function for player {}. This is a bug in the plugin, not in Velocity. Falling back to the default permission function.", event.getProvider().getClass().getName(), player.getUsername()); - } else { - try { - setPermissionFunctionMethod.invoke(player, function); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - bungee.getEventManager().fire(new LoginEvent(player)).thenAcceptAsync(event3 -> { - if (con.isClosed()) { - // The player was disconnected - bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CANCELLED_BY_USER_BEFORE_COMPLETE)); - return; - } - - Optional reason = event3.getResult().getReasonComponent(); - if (reason.isPresent()) { - bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CANCELLED_BY_PROXY)); - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - GlobalTranslator.render(reason.get(), Locale.getDefault())) - .addListener(ChannelFutureListener.CLOSE); - return; - } else { - if (!bungee.registerConnection(player)) { - bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CONFLICTING_LOGIN)); - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - ByteBuf buf = Unpooled.buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_FINISH_LOGIN); - ctx.channel().writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(future -> { - ChannelPipeline pp = ctx.channel().pipeline(); - - pp.remove(HttpWebSocketHandler.this); - - pp.addLast("EaglerMinecraftByteBufDecoder", new EaglerMinecraftDecoder()) - .addLast(READ_TIMEOUT, - new ReadTimeoutHandler(bungee.getConfiguration().getReadTimeout(), - TimeUnit.MILLISECONDS)) - .addLast("EaglerMinecraftByteBufEncoder", new EaglerMinecraftEncoder()) - .addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolUtils.Direction.SERVERBOUND)) - .addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolUtils.Direction.CLIENTBOUND)); - - pp.addLast(Connections.HANDLER, con); - - con.setProtocolVersion(protocolVers); - con.setState(StateRegistry.PLAY); - con.setActiveSessionHandler(StateRegistry.PLAY, stupid4Constructor.newInstance(player, bungee)); - - bungee.getEventManager().fire(new PostLoginEvent(player)).thenCompose((ignored) -> { - EaglerConnectionInstance conInstance = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - conInstance.userConnection = player; - conInstance.hasBeenForwarded = true; - Optional initialFromConfig = player.getNextServerToTry(); - PlayerChooseInitialServerEvent event2 = new PlayerChooseInitialServerEvent(player, initialFromConfig.orElse(null)); - return bungee.getEventManager().fire(event2).thenRunAsync(() -> { - Optional toTry = event2.getInitialServer(); - if (toTry.isEmpty()) { - player.disconnect0(Component.translatable("velocity.error.no-available-servers", NamedTextColor.RED), true); - } else { - player.createConnectionRequest(toTry.get()).fireAndForget(); - } - }, con.eventLoop()); - }).exceptionally((ex) -> { - EaglerXVelocity.logger().error("Exception while connecting {} to initial server", player, ex); - return null; - }); - }); - } - }, con.eventLoop()).exceptionally((ex) -> { - EaglerXVelocity.logger().error("Exception while completing login initialisation phase for {}", player, ex); - return null; - }); - } - - }, con.eventLoop()); - } - } - }, con.eventLoop()).exceptionally((ex) -> { - EaglerXVelocity.logger().error("Exception during connection of {}", profile, ex); - return null; - }); - }); - }); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - }, con.eventLoop()).exceptionally((ex) -> { - EaglerXVelocity.logger().error("Exception in pre-login stage", ex); - return null; - }); - - } - - private static String cleanVhost(String hostname) { - String cleaned = hostname; - int zeroIdx = hostname.indexOf(0); - if (zeroIdx > -1) { - cleaned = hostname.substring(0, zeroIdx); - } - - if (!cleaned.isEmpty() && cleaned.charAt(cleaned.length() - 1) == '.') { - cleaned = cleaned.substring(0, cleaned.length() - 1); - } - - return cleaned; - } - - private static class EventException extends RuntimeException { - public EventException(Throwable t) { - super(t.toString(), t); - } - } - - private void handleText(ChannelHandlerContext ctx, String str) { - if(connectionClosed) { - return; - } - if (!hasFirstPacket && (conf.isAllowMOTD() || conf.isAllowQuery()) && str.length() < 128 - && (str = str.toLowerCase()).startsWith("accept:")) { - str = str.substring(7).trim(); - hasFirstPacket = true; - hasBinaryConnection = false; - - if(CommandConfirmCode.confirmHash != null && str.equalsIgnoreCase(CommandConfirmCode.confirmHash)) { - connectionClosed = true; - ctx.writeAndFlush(new TextWebSocketFrame("OK")).addListener(ChannelFutureListener.CLOSE); - CommandConfirmCode.confirmHash = null; - return; - } - - boolean isMOTD = str.startsWith("motd"); - - SocketAddress localSocketAddr = ctx.channel().remoteAddress(); - InetAddress addr = ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).get(); - - String limiterAddress = null; - RateLimitStatus queryRateLimit = RateLimitStatus.OK; - if(addr != null) { - limiterAddress = addr.getHostAddress(); - }else { - if(localSocketAddr instanceof InetSocketAddress) { - limiterAddress = ((InetSocketAddress)localSocketAddr).getAddress().getHostAddress(); - } - } - - EaglerRateLimiter limiter = isMOTD ? conf.getRatelimitMOTD() : conf.getRatelimitQuery(); - if(limiterAddress != null && limiter != null) { - queryRateLimit = limiter.rateLimit(limiterAddress); - } - - if(queryRateLimit == RateLimitStatus.LOCKED_OUT) { - connectionClosed = true; - ctx.close(); - return; - } - - if(queryRateLimit != RateLimitStatus.OK) { - connectionClosed = true; - final RateLimitStatus rateLimitTypeFinal = queryRateLimit; - ctx.writeAndFlush(new TextWebSocketFrame( - rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "{\"type\":\"locked\"}" : "{\"type\":\"blocked\"}")) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - HttpServerQueryHandler handler = null; - if(isMOTD) { - if(conf.isAllowMOTD()) { - handler = new MOTDQueryHandler(); - } - }else if(conf.isAllowQuery()) { - handler = QueryManager.createQueryHandler(str); - } - if(handler != null) { - ctx.pipeline().replace(HttpWebSocketHandler.this, "HttpServerQueryHandler", handler); - ctx.pipeline().addBefore("HttpServerQueryHandler", "WriteTimeoutHandler", new WriteTimeoutHandler(5l, TimeUnit.SECONDS)); - ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().hasBeenForwarded = true; - handler.beginHandleQuery(conf, ctx, str); - if(handler instanceof MOTDQueryHandler) { - EaglercraftMOTDEvent evt = new EaglercraftMOTDEvent((MOTDQueryHandler)handler); - final HttpServerQueryHandler handlerF = handler; - EaglerXVelocity.proxy().getEventManager().fire(evt).thenAccept(evt2 -> { - if(!handlerF.isClosed()) { - ((MOTDQueryHandler)handlerF).sendToUser(); - if(!handlerF.isClosed() && !handlerF.shouldKeepAlive()) { - handlerF.close(); - } - } - }).exceptionally((excep) -> { - EaglerXVelocity.logger().error("Failed to handle EaglercraftMOTDEvent!", excep); - if(!handlerF.isClosed()) { - handlerF.close(); - } - return null; - }); - }else if(!handler.isClosed() && !handler.shouldKeepAlive()) { - handler.close(); - } - }else { - connectionClosed = true; - ctx.close(); - } - }else { - connectionClosed = true; - ctx.close(); - return; - } - } - - private int getAuthMethodId(AuthMethod meth) { - switch(meth) { - case PLAINTEXT: - return 255; // plaintext authentication - case EAGLER_SHA256: - return 1; // eagler_sha256 authentication - case AUTHME_SHA256: - return 2; // authme_sha256 authentication - default: - return -1; - } - } - - private ChannelFuture sendLoginDenied(ChannelHandlerContext ctx, String reason) { - if((!isProtocolExchanged || clientProtocolVersion == 2) && reason.length() > 255) { - reason = reason.substring(0, 255); - }else if(reason.length() > 65535) { - reason = reason.substring(0, 65535); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_DENY_LOGIN); - byte[] msg = reason.getBytes(StandardCharsets.UTF_8); - if(!isProtocolExchanged || clientProtocolVersion == 2) { - buf.writeByte(msg.length); - }else { - buf.writeShort(msg.length); - } - buf.writeBytes(msg); - return ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - } - - private ChannelFuture sendErrorWrong(ChannelHandlerContext ctx, int op, String state) { - return sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_WRONG_PACKET, "Wrong Packet #" + op + " in state '" + state + "'"); - } - - private ChannelFuture sendErrorCode(ChannelHandlerContext ctx, int code, String str) { - if((!isProtocolExchanged || clientProtocolVersion == 2) && str.length() > 255) { - str = str.substring(0, 255); - }else if(str.length() > 65535) { - str = str.substring(0, 65535); - } - clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; - connectionClosed = true; - ByteBuf buf = ctx.alloc().buffer(); - buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ERROR); - buf.writeByte(code); - byte[] msg = str.getBytes(StandardCharsets.UTF_8); - if(!isProtocolExchanged || clientProtocolVersion == 2) { - buf.writeByte(msg.length); - }else { - buf.writeShort(msg.length); - } - buf.writeBytes(msg); - return ctx.writeAndFlush(new BinaryWebSocketFrame(buf)); - } - - private ChannelFuture sendErrorCode(ChannelHandlerContext ctx, int code, Component comp) { - if((!isProtocolExchanged || clientProtocolVersion == 2)) { - return sendErrorCode(ctx, code, LegacyComponentSerializer.legacySection().serialize(comp)); - }else { - return sendErrorCode(ctx, code, JSONLegacySerializer.instance.serialize(comp)); - } - } - - public void channelInactive(ChannelHandlerContext ctx) { - connectionClosed = true; - EaglerPipeline.closeChannel(ctx.channel()); - } - - private void handleLegacyClient(ChannelHandlerContext ctx, ByteBuf buffer) { - connectionClosed = true; - ByteBuf kickMsg = ctx.alloc().buffer(); - final String redir = conf.redirectLegacyClientsTo(); - if(redir != null) { - writeLegacyRedirect(kickMsg, redir); - }else { - writeLegacyKick(kickMsg, "This is an EaglercraftX 1.8 server, it is not compatible with 1.5.2!"); - } - ctx.writeAndFlush(new BinaryWebSocketFrame(kickMsg)).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture var1) throws Exception { - ctx.channel().eventLoop().schedule(new Runnable() { - @Override - public void run() { - ctx.close(); - } - }, redir != null ? 100l : 500l, TimeUnit.MILLISECONDS); - } - }); - } - - public static void writeLegacyKick(ByteBuf buffer, String message) { - buffer.writeByte(0xFF); - buffer.writeShort(message.length()); - for(int i = 0, l = message.length(), j; i < l; ++i) { - j = message.charAt(i); - buffer.writeByte((j >>> 8) & 0xFF); - buffer.writeByte(j & 0xFF); - } - } - - public static void writeLegacyRedirect(ByteBuf buffer, String redirect) { - buffer.writeBytes(legacyRedirectHeader); - byte[] redirect_ = redirect.getBytes(StandardCharsets.UTF_8); - buffer.writeByte((redirect_.length >>> 8) & 0xFF); - buffer.writeByte(redirect_.length & 0xFF); - buffer.writeBytes(redirect_); - } - - private static final byte[] legacyRedirectHeader; - - static { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bao); - try { - // Packet1Login - dos.writeByte(0x01); - dos.writeInt(0); - dos.writeShort(0); - dos.writeByte(0); - dos.writeByte(0); - dos.writeByte(0xFF); - dos.writeByte(0); - dos.writeByte(0); - // Packet250CustomPayload - dos.writeByte(0xFA); - String channel = "EAG|Reconnect"; - int cl = channel.length(); - dos.writeShort(cl); - for(int i = 0; i < cl; ++i) { - dos.writeChar(channel.charAt(i)); - } - }catch(IOException ex) { - throw new ExceptionInInitializerError(ex); - } - legacyRedirectHeader = bao.toByteArray(); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/BackendRPCSessionHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/BackendRPCSessionHandler.java deleted file mode 100644 index 0909b652..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/BackendRPCSessionHandler.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; - -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.proxy.connection.MinecraftConnection; -import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; - -import io.netty.buffer.Unpooled; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.EaglerBackendRPCProtocol; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.WrongRPCPacketException; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCEnabled; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCSubscribeEvents; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledFailure; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEnabledSuccess; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewOpenClose; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayInputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayOutputStream; - -public class BackendRPCSessionHandler { - - public static BackendRPCSessionHandler createForPlayer(EaglerPlayerData eaglerHandler) { - return new BackendRPCSessionHandler(eaglerHandler); - } - - protected final EaglerPlayerData eaglerHandler; - private ServerConnection currentServer = null; - private String channelName = null; - private EaglerBackendRPCProtocol currentProtocol = null; - private EaglerBackendRPCHandler currentHandler = null; - private int subscribedEvents = 0; - private final AtomicInteger currentVoiceState = new AtomicInteger(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - private final ReentrantLock inputStreamLock = new ReentrantLock(); - private final ReentrantLock outputStreamLock = new ReentrantLock(); - private final ReusableByteArrayInputStream reusableInputStream = new ReusableByteArrayInputStream(); - private final ReusableByteArrayOutputStream reusableOutputStream = new ReusableByteArrayOutputStream(); - private final DataInputStream dataInputStream = new DataInputStream(reusableInputStream); - private final DataOutputStream dataOutputStream = new DataOutputStream(reusableOutputStream); - - private BackendRPCSessionHandler(EaglerPlayerData eaglerHandler) { - this.eaglerHandler = eaglerHandler; - } - - public void handleRPCPacket(ServerConnection server, byte[] data) { - synchronized(this) { - if(currentServer != null) { - if(currentServer != server) { - return; - } - }else { - handleCreateContext(server, data); - return; - } - } - EaglerBackendRPCPacket packet; - try { - packet = decodeRPCPacket(currentProtocol, data); - } catch (IOException e) { - EaglerXVelocity.logger().error("[{}]: Recieved invalid backend RPC protocol packet for user \"{}\"", - eaglerHandler.getSocketAddress(), eaglerHandler.getName(), e); - return; - } - packet.handlePacket(currentHandler); - } - - protected EaglerBackendRPCPacket decodeRPCPacket(EaglerBackendRPCProtocol protocol, byte[] data) throws IOException { - EaglerBackendRPCPacket ret; - if(inputStreamLock.tryLock()) { - try { - reusableInputStream.feedBuffer(data); - ret = protocol.readPacket(dataInputStream, EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - }finally { - inputStreamLock.unlock(); - } - }else { - ReusableByteArrayInputStream bai = new ReusableByteArrayInputStream(); - bai.feedBuffer(data); - ret = protocol.readPacket(new DataInputStream(bai), EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - } - return ret; - } - - public void sendRPCPacket(EaglerBackendRPCPacket packet) { - if(currentServer != null) { - sendRPCPacket(currentProtocol, currentServer, packet); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Failed to write backend RPC protocol version for user \"{}\", the RPC connection is not initialized!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - protected void sendRPCPacket(EaglerBackendRPCProtocol protocol, ServerConnection server, EaglerBackendRPCPacket packet) { - byte[] ret; - int len = packet.length() + 1; - if(outputStreamLock.tryLock()) { - try { - reusableOutputStream.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(dataOutputStream, EaglerBackendRPCProtocol.SERVER_TO_CLIENT, packet); - }catch(IOException ex) { - throw new IllegalStateException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = reusableOutputStream.returnBuffer(); - }finally { - outputStreamLock.unlock(); - } - }else { - ReusableByteArrayOutputStream bao = new ReusableByteArrayOutputStream(); - bao.feedBuffer(new byte[len > 0 ? len : 64]); - try { - protocol.writePacket(new DataOutputStream(bao), EaglerBackendRPCProtocol.SERVER_TO_CLIENT, packet); - }catch(IOException ex) { - throw new IllegalStateException("Failed to serialize packet: " + packet.getClass().getSimpleName(), ex); - } - ret = bao.returnBuffer(); - } - if(len > 0 && len != ret.length) { - EaglerXVelocity.logger().warn( - "[{}]: Backend RPC packet type {} was the wrong length for user \"{}\" after serialization: {} != {}", - eaglerHandler.getSocketAddress(), packet.getClass().getSimpleName(), eaglerHandler.getName(), - ret.length, len); - } - sendPluginMessage(server, channelName, ret); - } - - public void handleConnectionLost() { - if(currentServer != null) { - handleDestroyContext(); - } - } - - private void handleDestroyContext() { - currentServer = null; - channelName = null; - currentProtocol = null; - currentHandler = null; - subscribedEvents = 0; - } - - private void handleCreateContext(ServerConnection server, byte[] data) { - EaglerBackendRPCPacket packet; - try { - packet = decodeRPCPacket(EaglerBackendRPCProtocol.INIT, data); - } catch (IOException e) { - EaglerXVelocity.logger().error("[{}]: Recieved invalid backend RPC protocol handshake for user \"{}\"", - eaglerHandler.getSocketAddress(), eaglerHandler.getName(), e); - return; - } - if(!(packet instanceof CPacketRPCEnabled)) { - throw new WrongRPCPacketException(); - } - channelName = getChNameFor((VelocityServerConnection)server); - if(!containsProtocol(((CPacketRPCEnabled)packet).supportedProtocols, EaglerBackendRPCProtocol.V1.vers)) { - EaglerXVelocity.logger().error("[{}]: Unsupported backend RPC protocol version for user \"{}\"", eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - sendRPCPacket(EaglerBackendRPCProtocol.INIT, server, new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_SERVER)); - return; - } - sendRPCPacket(EaglerBackendRPCProtocol.INIT, server, new SPacketRPCEnabledSuccess(EaglerBackendRPCProtocol.V1.vers, eaglerHandler.getEaglerProtocolHandshake())); - currentServer = server; - currentProtocol = EaglerBackendRPCProtocol.V1; - currentHandler = new ServerV1RPCProtocolHandler(this, server, eaglerHandler); - } - - private static boolean containsProtocol(int[] supportedProtocols, int vers) { - for(int i = 0; i < supportedProtocols.length; ++i) { - if(supportedProtocols[i] == vers) { - return true; - } - } - return false; - } - - public static void handlePacketOnVanilla(ServerConnection server, ConnectedPlayer player, byte[] data) { - EaglerBackendRPCPacket packet; - try { - packet = EaglerBackendRPCProtocol.INIT.readPacket(new DataInputStream(new ByteArrayInputStream(data)), EaglerBackendRPCProtocol.CLIENT_TO_SERVER); - } catch (IOException e) { - EaglerXVelocity.logger().error("[{}]: Recieved invalid backend RPC protocol handshake for user \"{}\"", player.getRemoteAddress(), player.getUsername(), e); - EaglerXVelocity.logger().error("(Note: this player is not using Eaglercraft!)"); - return; - } - if(!(packet instanceof CPacketRPCEnabled)) { - throw new WrongRPCPacketException(); - } - if(!containsProtocol(((CPacketRPCEnabled)packet).supportedProtocols, EaglerBackendRPCProtocol.V1.vers)) { - EaglerXVelocity.logger().error("[{}]: Unsupported backend RPC protocol version for user \"{}\"", player.getRemoteAddress(), player.getUsername()); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - EaglerBackendRPCProtocol.INIT.writePacket(new DataOutputStream(bao), - EaglerBackendRPCProtocol.SERVER_TO_CLIENT, - new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_OUTDATED_SERVER)); - }catch(IOException ex) { - EaglerXVelocity.logger().error("[{}]: Failed to write backend RPC protocol version for user \"{}\"", player.getRemoteAddress(), player.getUsername(), ex); - EaglerXVelocity.logger().error("(Note: this player is not using Eaglercraft!)"); - return; - } - sendPluginMessage(server, getChNameFor((VelocityServerConnection)server), bao.toByteArray()); - return; - } - EaglerXVelocity.logger().warn("[{}]: Tried to open backend RPC protocol connection for non-eagler player \"{}\"", player.getRemoteAddress(), player.getUsername()); - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - EaglerBackendRPCProtocol.INIT.writePacket(new DataOutputStream(bao), - EaglerBackendRPCProtocol.SERVER_TO_CLIENT, - new SPacketRPCEnabledFailure(SPacketRPCEnabledFailure.FAILURE_CODE_NOT_EAGLER_PLAYER)); - }catch(IOException ex) { - EaglerXVelocity.logger().error("[{}]: Failed to write backend RPC protocol version for user \"{}\"", player.getRemoteAddress(), player.getUsername(), ex); - return; - } - sendPluginMessage(server, getChNameFor((VelocityServerConnection)server), bao.toByteArray()); - } - - public void setSubscribedEvents(int eventsToEnable) { - int oldSubscribedEvents = subscribedEvents; - subscribedEvents = eventsToEnable; - if ((oldSubscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) == 0 - && (eventsToEnable & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0) { - currentVoiceState.set(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - VoiceService svc = EaglerXVelocity.getEagler().getVoiceService(); - if(svc != null && eaglerHandler.getEaglerListenerConfig().getEnableVoiceChat()) { - EnumVoiceState state = svc.getPlayerVoiceState(eaglerHandler.getUniqueId(), currentServer.getServerInfo()); - if(state == EnumVoiceState.DISABLED) { - handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - }else if(state == EnumVoiceState.ENABLED) { - handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_ENABLED); - } - } - } - if ((oldSubscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) == 0 - && (eventsToEnable & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) != 0) { - if(eaglerHandler.webViewMessageChannelOpen.get()) { - sendRPCPacket(new SPacketRPCEventWebViewOpenClose(true, eaglerHandler.webViewMessageChannelName)); - } - } - if ((eventsToEnable & ~(CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE - | CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_MESSAGE - | CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE)) != 0) { - EaglerXVelocity.logger().error( - "[{}]: Unsupported events were subscribed to for \"{}\" via backend RPC protocol, bitfield: {}", - eaglerHandler.getSocketAddress(), eaglerHandler.getName(), subscribedEvents); - } - } - - public boolean isSubscribed(EnumSubscribedEvent eventType) { - switch(eventType) { - case WEBVIEW_OPEN_CLOSE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE) != 0; - case WEBVIEW_MESSAGE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_WEBVIEW_MESSAGE) != 0; - case TOGGLE_VOICE: - return (subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0; - default: - return false; - } - } - - public void handleDisabled() { - handleDestroyContext(); - } - - public void handleVoiceStateTransition(int voiceState) { - if((subscribedEvents & CPacketRPCSubscribeEvents.SUBSCRIBE_EVENT_TOGGLE_VOICE) != 0) { - int oldState = currentVoiceState.getAndSet(voiceState); - if(oldState != voiceState) { - sendRPCPacket(new SPacketRPCEventToggledVoice(oldState, voiceState)); - } - } - } - - public static void sendPluginMessage(ServerConnection conn, String channel, byte[] data) { - // Velocity channel registry can go fuck itself - MinecraftConnection mc = ((VelocityServerConnection)conn).getConnection(); - if(mc != null) { - mc.write(new PluginMessagePacket(channel, Unpooled.wrappedBuffer(data))); - } - } - - private static int getVerSafe(VelocityServerConnection server) { - try { - return server.getConnection().getProtocolVersion().getProtocol(); - }catch(Throwable t) { - return -1; - } - } - - public static String getChNameFor(VelocityServerConnection server) { - return (EaglerXVelocity.getEagler().getConfig().getUseModernizedChannelNames() || getVerSafe(server) >= 393) - ? EaglerBackendRPCProtocol.CHANNEL_NAME_MODERN - : EaglerBackendRPCProtocol.CHANNEL_NAME; - } - - public static String getReadyChNameFor(VelocityServerConnection server) { - return (EaglerXVelocity.getEagler().getConfig().getUseModernizedChannelNames() || getVerSafe(server) >= 393) - ? EaglerBackendRPCProtocol.CHANNEL_NAME_READY_MODERN - : EaglerBackendRPCProtocol.CHANNEL_NAME_READY; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/EnumSubscribedEvent.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/EnumSubscribedEvent.java deleted file mode 100644 index b546b799..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/EnumSubscribedEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol; - -public enum EnumSubscribedEvent { - WEBVIEW_OPEN_CLOSE, - WEBVIEW_MESSAGE, - TOGGLE_VOICE; -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java deleted file mode 100644 index c7959644..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.RandomAccess; -import java.util.UUID; - -import com.velocitypowered.api.proxy.ServerConnection; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumWebViewState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerPauseMenuConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol.GameProtocolMessageController; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketCustomizePauseMenuV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeHideV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifBadgeShowV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsRegisterV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketNotifIconsReleaseV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class ServerV1RPCProtocolHandler implements EaglerBackendRPCHandler { - - protected final BackendRPCSessionHandler sessionHandler; - protected final ServerConnection server; - protected final EaglerPlayerData eaglerHandler; - - public ServerV1RPCProtocolHandler(BackendRPCSessionHandler sessionHandler, ServerConnection server, EaglerPlayerData eaglerHandler) { - this.sessionHandler = sessionHandler; - this.server = server; - this.eaglerHandler = eaglerHandler; - } - - public void handleClient(CPacketRPCRequestPlayerInfo packet) { - switch(packet.requestType) { - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_UUID: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeUUID(packet.requestID, eaglerHandler.getUniqueId())); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_REAL_IP: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, ((InetSocketAddress)eaglerHandler.getSocketAddress()).getAddress().getHostAddress())); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_ORIGIN: { - String origin = eaglerHandler.getOrigin(); - if(origin != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, origin)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_USER_AGENT: { - String userAgent = eaglerHandler.getUserAgent(); - if(userAgent != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, userAgent)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_SKIN_DATA: { - SkinPacketVersionCache skinData = EaglerXVelocity.getEagler().getSkinService().getSkin(eaglerHandler.getUniqueId()); - if(skinData != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeBytes(packet.requestID, skinData.getV3HandshakeData())); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CAPE_DATA: { - byte[] capeData = EaglerXVelocity.getEagler().getCapeService().getCapeHandshakeData(eaglerHandler.getUniqueId()); - if(capeData != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeBytes(packet.requestID, capeData)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_COOKIE: { - boolean cookieEnabled = eaglerHandler.getCookieAllowed(); - byte[] cookieData = cookieEnabled ? eaglerHandler.getCookieData() : null; - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeCookie(packet.requestID, cookieEnabled, cookieData)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_STR: { - String clientBrandStr = eaglerHandler.getEaglerBrandString(); - if(clientBrandStr != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, clientBrandStr)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VERSION_STR: { - String clientVersionStr = eaglerHandler.getEaglerVersionString(); - if(clientVersionStr != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, clientVersionStr)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_VERSION_STR: { - String clientBrandStr = eaglerHandler.getEaglerBrandString(); - String clientVersionStr = eaglerHandler.getEaglerVersionString(); - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeString(packet.requestID, "" + clientBrandStr + " " + clientVersionStr)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_BRAND_UUID: { - UUID brandUUID = eaglerHandler.getClientBrandUUID(); - if(brandUUID != null) { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeUUID(packet.requestID, brandUUID)); - }else { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeNull(packet.requestID)); - } - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_VOICE_STATUS: { - int voiceState; - VoiceService svc = EaglerXVelocity.getEagler().getVoiceService(); - if(svc != null && eaglerHandler.getEaglerListenerConfig().getEnableVoiceChat()) { - EnumVoiceState enumVoiceState = svc.getPlayerVoiceState(eaglerHandler.getUniqueId(), server.getServerInfo()); - switch(enumVoiceState) { - case SERVER_DISABLE: - default: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_SERVER_DISABLE; - break; - case DISABLED: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_DISABLED; - break; - case ENABLED: - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_ENABLED; - break; - } - }else { - voiceState = SPacketRPCResponseTypeVoiceStatus.VOICE_STATE_SERVER_DISABLE; - } - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeVoiceStatus(packet.requestID, voiceState)); - } - break; - case CPacketRPCRequestPlayerInfo.REQUEST_PLAYER_CLIENT_WEBVIEW_STATUS: { - EnumWebViewState enumWebViewState = eaglerHandler.getWebViewState(); - int webViewStatus; - String webViewChannel; - switch(enumWebViewState) { - case NOT_SUPPORTED: - default: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_NOT_SUPPORTED; - webViewChannel = null; - break; - case SERVER_DISABLE: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_SERVER_DISABLE; - webViewChannel = null; - break; - case CHANNEL_CLOSED: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_CLOSED; - webViewChannel = null; - break; - case CHANNEL_OPEN: - webViewStatus = SPacketRPCResponseTypeWebViewStatus.WEBVIEW_STATE_CHANNEL_OPEN; - webViewChannel = eaglerHandler.getWebViewMessageChannelName(); - break; - } - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeWebViewStatus(packet.requestID, webViewStatus, webViewChannel)); - } - break; - default: { - sessionHandler.sendRPCPacket(new SPacketRPCResponseTypeError(packet.requestID, "Unknown request type: " + packet.requestType)); - } - break; - } - } - - public void handleClient(CPacketRPCSubscribeEvents packet) { - sessionHandler.setSubscribedEvents(packet.eventsToEnable); - } - - public void handleClient(CPacketRPCSetPlayerSkin packet) { - try { - byte[] bs = packet.skinPacket; - if(bs.length < 5) { - throw new IOException(); - } - if(bs[0] == (byte)1) { - if(bs.length != 5) { - throw new IOException(); - } - EaglerXVelocityAPIHelper.changePlayerSkinPreset(EaglerXVelocityAPIHelper.getPlayer(eaglerHandler), - (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF), packet.notifyOthers); - }else if(bs[0] == (byte)2) { - if(bs.length < 2) { - throw new IOException(); - } - byte[] cust = new byte[bs.length - 2]; - System.arraycopy(bs, 2, cust, 0, cust.length); - EaglerXVelocityAPIHelper.changePlayerSkinCustom(EaglerXVelocityAPIHelper.getPlayer(eaglerHandler), - bs[1] & 0xFF, cust, packet.notifyOthers); - }else { - throw new IOException(); - } - }catch(IOException ex) { - EaglerXVelocity.logger().error( - "[{}]: Invalid CPacketRPCSetPlayerSkin packet recieved for player \"{}\" from backend RPC protocol!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - return; - } - } - - public void handleClient(CPacketRPCSetPlayerCape packet) { - try { - byte[] bs = packet.capePacket; - if(bs.length < 5) { - throw new IOException(); - } - if(bs[0] == (byte)1) { - if(bs.length != 5) { - throw new IOException(); - } - EaglerXVelocityAPIHelper.changePlayerCapePreset(EaglerXVelocityAPIHelper.getPlayer(eaglerHandler), - (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF), packet.notifyOthers); - }else if(bs[0] == (byte)2) { - if(bs.length != 1174) { - throw new IOException(); - } - byte[] cust = new byte[bs.length - 1]; - System.arraycopy(bs, 1, cust, 0, cust.length); - EaglerXVelocityAPIHelper.changePlayerCapeCustom(EaglerXVelocityAPIHelper.getPlayer(eaglerHandler), - cust, true, packet.notifyOthers); - }else { - throw new IOException(); - } - }catch(IOException ex) { - EaglerXVelocity.logger().error( - "[{}]: Invalid CPacketRPCSetPlayerCape packet recieved for player \"{}\" from backend RPC protocol!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - return; - } - } - - public void handleClient(CPacketRPCSetPlayerCookie packet) { - eaglerHandler.setCookieData(packet.cookieData, packet.expires, packet.revokeQuerySupported, packet.saveToDisk); - } - - public void handleClient(CPacketRPCSetPlayerFNAWEn packet) { - EaglerXVelocityAPIHelper.setEnableForceFNAWSkins(eaglerHandler, packet.enable, packet.force); - } - - public void handleClient(CPacketRPCRedirectPlayer packet) { - eaglerHandler.redirectPlayerToWebSocket(packet.redirectURI); - } - - public void handleClient(CPacketRPCResetPlayerMulti packet) { - EaglerXVelocityAPIHelper.resetPlayerMulti(EaglerXVelocityAPIHelper.getPlayer(eaglerHandler), packet.resetSkin, - packet.resetCape, packet.resetFNAWForce, packet.notifyOtherPlayers); - } - - public void handleClient(CPacketRPCSendWebViewMessage packet) { - eaglerHandler.sendWebViewMessage(packet.messageType, packet.messageContent); - } - - public void handleClient(CPacketRPCSetPauseMenuCustom packet) { - if(eaglerHandler.getEaglerProtocol().ver >= 4) { - EaglerPauseMenuConfig defaultConf = EaglerXVelocity.getEagler().getConfig().getPauseMenuConf(); - SPacketCustomizePauseMenuV4EAG defaultPacket = defaultConf.getPacket(); - int serverInfoMode = packet.serverInfoMode; - String serverInfoButtonText; - String serverInfoURL; - byte[] serverInfoHash; - int serverInfoEmbedPerms; - String serverInfoEmbedTitle; - if(serverInfoMode == CPacketRPCSetPauseMenuCustom.SERVER_INFO_MODE_INHERIT_DEFAULT) { - serverInfoMode = defaultPacket.serverInfoMode; - serverInfoButtonText = defaultPacket.serverInfoButtonText; - serverInfoURL = defaultPacket.serverInfoURL; - serverInfoHash = defaultPacket.serverInfoHash; - serverInfoEmbedPerms = defaultPacket.serverInfoEmbedPerms; - serverInfoEmbedTitle = defaultPacket.serverInfoEmbedTitle; - }else { - serverInfoButtonText = packet.serverInfoButtonText; - serverInfoURL = packet.serverInfoURL; - serverInfoHash = packet.serverInfoHash; - serverInfoEmbedPerms = packet.serverInfoEmbedPerms; - serverInfoEmbedTitle = packet.serverInfoEmbedTitle; - } - int discordButtonMode = packet.discordButtonMode; - String discordButtonText; - String discordInviteURL; - if(discordButtonMode == CPacketRPCSetPauseMenuCustom.DISCORD_MODE_INHERIT_DEFAULT) { - discordButtonMode = defaultPacket.discordButtonMode; - discordButtonText = defaultPacket.discordButtonText; - discordInviteURL = defaultPacket.discordInviteURL; - }else { - discordButtonText = packet.discordButtonText; - discordInviteURL = packet.discordInviteURL; - } - Map imageMappings = packet.imageMappings; - List imageData = packet.imageData; - List imageDataConv = imageData != null - ? new ArrayList<>(imageData.size()) : null; - if(imageDataConv != null) { - for(int i = 0, l = imageData.size(); i < l; ++i) { - PacketImageData etr = imageData.get(i); - imageDataConv.add(new net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData - (etr.width, etr.height, etr.rgba)); - } - } - eaglerHandler.sendEaglerMessage(new SPacketCustomizePauseMenuV4EAG(serverInfoMode, serverInfoButtonText, - serverInfoURL, serverInfoHash, serverInfoEmbedPerms, serverInfoEmbedTitle, discordButtonMode, - discordButtonText, discordInviteURL, imageMappings, imageDataConv)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Recieved packet CPacketRPCSetPauseMenuCustom for player \"{}\" from backend RPC protocol, but their client does not support pause menu customization!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - public void handleClient(CPacketRPCNotifIconRegister packet) { - if(eaglerHandler.notificationSupported()) { - List createIconsConv = new ArrayList<>(packet.notifIcons.size()); - for(Entry etr : packet.notifIcons.entrySet()) { - UUID uuid = etr.getKey(); - PacketImageData imgData = etr.getValue(); - createIconsConv.add(new SPacketNotifIconsRegisterV4EAG.CreateIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), new net.lax1dude.eaglercraft.v1_8.socket.protocol.util.PacketImageData - (imgData.width, imgData.height, imgData.rgba))); - } - eaglerHandler.sendEaglerMessage(new SPacketNotifIconsRegisterV4EAG(createIconsConv)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Recieved packet CPacketRPCNotifIconRegister for player \"{}\" from backend RPC protocol, but their client does not support notifications!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - public void handleClient(CPacketRPCNotifIconRelease packet) { - if(eaglerHandler.notificationSupported()) { - List destroyIconsConv = new ArrayList<>(packet.iconsToRelease.size()); - if(packet.iconsToRelease instanceof RandomAccess) { - List lst = (List)packet.iconsToRelease; - for(int i = 0, l = lst.size(); i < l; ++i) { - UUID uuid = lst.get(i); - destroyIconsConv.add(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())); - } - }else { - for(UUID uuid : packet.iconsToRelease) { - destroyIconsConv.add(new SPacketNotifIconsReleaseV4EAG.DestroyIcon(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits())); - } - } - eaglerHandler.sendEaglerMessage(new SPacketNotifIconsReleaseV4EAG(destroyIconsConv)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Recieved packet CPacketRPCNotifIconRelease for player \"{}\" from backend RPC protocol, but their client does not support notifications!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - public void handleClient(CPacketRPCNotifBadgeShow packet) { - if(eaglerHandler.notificationSupported()) { - SPacketNotifBadgeShowV4EAG.EnumBadgePriority translatedEnum; - switch(packet.priority) { - case LOW: - default: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.LOW; - break; - case NORMAL: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.NORMAL; - break; - case HIGHER: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.HIGHER; - break; - case HIGHEST: - translatedEnum = SPacketNotifBadgeShowV4EAG.EnumBadgePriority.HIGHEST; - break; - } - eaglerHandler.sendEaglerMessage(new SPacketNotifBadgeShowV4EAG(packet.badgeUUID.getMostSignificantBits(), - packet.badgeUUID.getLeastSignificantBits(), packet.bodyComponent, packet.titleComponent, - packet.sourceComponent, packet.originalTimestampSec, packet.silent, translatedEnum, - (packet.mainIconUUID != null ? packet.mainIconUUID.getMostSignificantBits() : 0l), - (packet.mainIconUUID != null ? packet.mainIconUUID.getLeastSignificantBits() : 0l), - (packet.titleIconUUID != null ? packet.titleIconUUID.getMostSignificantBits() : 0l), - (packet.titleIconUUID != null ? packet.titleIconUUID.getLeastSignificantBits() : 0l), - packet.hideAfterSec, packet.expireAfterSec, packet.backgroundColor, packet.bodyTxtColor, - packet.titleTxtColor, packet.sourceTxtColor)); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Recieved packet CPacketRPCNotifBadgeShow for player \"{}\" from backend RPC protocol, but their client does not support notifications!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - public void handleClient(CPacketRPCNotifBadgeHide packet) { - if(eaglerHandler.notificationSupported()) { - eaglerHandler.sendEaglerMessage(new SPacketNotifBadgeHideV4EAG(packet.badgeUUID.getMostSignificantBits(), - packet.badgeUUID.getLeastSignificantBits())); - }else { - EaglerXVelocity.logger().warn( - "[{}]: Recieved packet CPacketRPCNotifBadgeHide for player \"{}\" from backend RPC protocol, but their client does not support notifications!", - eaglerHandler.getSocketAddress(), eaglerHandler.getName()); - } - } - - public void handleClient(CPacketRPCDisabled packet) { - sessionHandler.handleDisabled(); - } - - public void handleClient(CPacketRPCSendRawMessage packet) { - GameProtocolMessageController.sendPluginMessage(eaglerHandler.getEaglerMessageController().getUserConnection(), packet.messageChannel, packet.messageData); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/GameProtocolMessageController.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/GameProtocolMessageController.java deleted file mode 100644 index 05814bcf..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/GameProtocolMessageController.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol; - -import java.io.IOException; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -import com.velocitypowered.proxy.connection.MinecraftConnection; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.util.concurrent.ScheduledFuture; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePacketOutputBuffer; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayInputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.ReusableByteArrayOutputStream; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleInputBufferImpl; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SimpleOutputBufferImpl; - -public class GameProtocolMessageController { - - public final GamePluginMessageProtocol protocol; - public final GameMessageHandler handler; - private final ReusableByteArrayInputStream byteInputStreamSingleton = new ReusableByteArrayInputStream(); - private final ReusableByteArrayOutputStream byteOutputStreamSingleton = new ReusableByteArrayOutputStream(); - private final SimpleInputBufferImpl inputStreamSingleton = new SimpleInputBufferImpl(byteInputStreamSingleton); - private final SimpleOutputBufferImpl outputStreamSingleton = new SimpleOutputBufferImpl(byteOutputStreamSingleton); - private final ReentrantLock inputStreamLock = new ReentrantLock(); - private final ReentrantLock outputStreamLock = new ReentrantLock(); - private final ConnectedPlayer owner; - private int defagSendDelay; - - private final List sendQueueV4 = new LinkedList<>(); - private volatile int sendQueueByteLengthV4 = 0; - private volatile Callable futureSendCallableV4 = null; - private volatile ScheduledFuture futureSendTaskV4 = null; - - public GameProtocolMessageController(ConnectedPlayer owner, GamePluginMessageProtocol protocol, - GameMessageHandler handler, int defagSendDelay) { - this.owner = owner; - this.protocol = protocol; - this.handler = handler; - this.defagSendDelay = defagSendDelay; - } - - public boolean handlePacket(String channel, byte[] data) throws IOException { - GameMessagePacket pkt; - if(inputStreamLock.tryLock()) { - try { - byteInputStreamSingleton.feedBuffer(data); - if(protocol.ver >= 4 && data.length > 0 && data[0] == (byte)0xFF && channel.equals(GamePluginMessageConstants.V4_CHANNEL)) { - inputStreamSingleton.readByte(); - int count = inputStreamSingleton.readVarInt(); - for(int i = 0, j, k; i < count; ++i) { - j = inputStreamSingleton.readVarInt(); - k = byteInputStreamSingleton.getReaderIndex() + j; - if(j > inputStreamSingleton.available()) { - throw new IOException("Packet fragment is too long: " + j + " > " + inputStreamSingleton.available()); - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputStreamSingleton); - if(pkt != null) { - pkt.handlePacket(handler); - }else { - throw new IOException("Unknown packet type in fragment!"); - } - if(byteInputStreamSingleton.getReaderIndex() != k) { - throw new IOException("Packet fragment was the wrong length: " + (j + byteInputStreamSingleton.getReaderIndex() - k) + " != " + j); - } - } - if(inputStreamSingleton.available() > 0) { - throw new IOException("Leftover data after reading multi-packet! (" + inputStreamSingleton.available() + " bytes)"); - } - return true; - } - inputStreamSingleton.setToByteArrayReturns(data); - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputStreamSingleton); - if(pkt != null && byteInputStreamSingleton.available() != 0) { - throw new IOException("Packet was the wrong length: " + pkt.getClass().getSimpleName()); - } - }finally { - byteInputStreamSingleton.feedBuffer(null); - inputStreamSingleton.setToByteArrayReturns(null); - inputStreamLock.unlock(); - } - }else { - // slow version that makes multiple new objects - ReusableByteArrayInputStream inputStream = new ReusableByteArrayInputStream(); - inputStream.feedBuffer(data); - SimpleInputBufferImpl inputBuffer = new SimpleInputBufferImpl(inputStream, data); - if(protocol.ver >= 4 && channel.equals(GamePluginMessageConstants.V4_CHANNEL)) { - inputBuffer.setToByteArrayReturns(null); - inputBuffer.readByte(); - int count = inputBuffer.readVarInt(); - for(int i = 0, j, k; i < count; ++i) { - j = inputBuffer.readVarInt(); - k = inputStream.getReaderIndex() + j; - if(j > inputBuffer.available()) { - throw new IOException("Packet fragment is too long: " + j + " > " + inputBuffer.available()); - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputBuffer); - if(pkt != null) { - pkt.handlePacket(handler); - }else { - throw new IOException("Unknown packet type in fragment!"); - } - if(inputStream.getReaderIndex() != k) { - throw new IOException("Packet fragment was the wrong length: " + (j + inputStream.getReaderIndex() - k) + " != " + j); - } - } - if(inputBuffer.available() > 0) { - throw new IOException("Leftover data after reading multi-packet! (" + inputBuffer.available() + " bytes)"); - } - return true; - } - pkt = protocol.readPacket(channel, GamePluginMessageConstants.CLIENT_TO_SERVER, inputBuffer); - if(pkt != null && inputStream.available() != 0) { - throw new IOException("Packet was the wrong length: " + pkt.getClass().getSimpleName()); - } - } - if(pkt != null) { - pkt.handlePacket(handler); - return true; - }else { - return false; - } - } - - public void sendPacketImmediately(GameMessagePacket packet) throws IOException { - sendPacket(packet, true); - } - - public void sendPacket(GameMessagePacket packet) throws IOException { - sendPacket(packet, false); - } - - protected void sendPacket(GameMessagePacket packet, boolean immediately) throws IOException { - int len = packet.length() + 1; - String chan; - byte[] data; - if(outputStreamLock.tryLock()) { - try { - byteOutputStreamSingleton.feedBuffer(new byte[len == 0 ? 64 : len]); - chan = protocol.writePacket(GamePluginMessageConstants.SERVER_TO_CLIENT, outputStreamSingleton, packet); - data = byteOutputStreamSingleton.returnBuffer(); - }finally { - byteOutputStreamSingleton.feedBuffer(null); - outputStreamLock.unlock(); - } - }else { - // slow version that makes multiple new objects - ReusableByteArrayOutputStream bao = new ReusableByteArrayOutputStream(); - bao.feedBuffer(new byte[len == 0 ? 64 : len]); - SimpleOutputBufferImpl outputStream = new SimpleOutputBufferImpl(bao); - chan = protocol.writePacket(GamePluginMessageConstants.SERVER_TO_CLIENT, outputStream, packet); - data = bao.returnBuffer(); - } - if(len != 0 && data.length != len && data.length + 1 != len) { - EaglerXVelocity.logger().warn("Packet {} was the wrong length after serialization, {} != {}", - packet.getClass().getSimpleName(), data.length, len); - } - if(defagSendDelay > 0 && protocol.ver >= 4 && chan.equals(GamePluginMessageConstants.V4_CHANNEL)) { - synchronized(sendQueueV4) { - int varIntLen = GamePacketOutputBuffer.getVarIntSize(data.length); - if(immediately || sendQueueByteLengthV4 + data.length + varIntLen > 32760) { - if(futureSendTaskV4 != null && !futureSendTaskV4.isDone()) { - futureSendTaskV4.cancel(false); - futureSendTaskV4 = null; - futureSendCallableV4 = null; - } - if(!sendQueueV4.isEmpty()) { - flushQueue(); - } - } - if(immediately) { - sendPluginMessage(owner, chan, data); - }else { - sendQueueV4.add(data); - if(futureSendTaskV4 == null || futureSendTaskV4.isDone()) { - futureSendTaskV4 = owner.getConnection().getChannel() - .eventLoop().schedule(futureSendCallableV4 = new Callable() { - @Override - public Void call() throws Exception { - synchronized (sendQueueV4) { - if (futureSendCallableV4 != this) { - return null; - } - futureSendTaskV4 = null; - futureSendCallableV4 = null; - if(!sendQueueV4.isEmpty()) { - flushQueue(); - } - } - return null; - } - }, defagSendDelay, TimeUnit.MILLISECONDS); - } - } - } - }else { - sendPluginMessage(owner, chan, data); - } - } - - private void flushQueue() { - if(!owner.isActive()) { - sendQueueV4.clear(); - return; - } - byte[] pkt; - if(sendQueueV4.size() == 1) { - pkt = sendQueueV4.remove(0); - sendPluginMessage(owner, GamePluginMessageConstants.V4_CHANNEL, pkt); - }else { - int i, j, sendCount, totalLen, lastLen; - while(!sendQueueV4.isEmpty()) { - sendCount = 0; - totalLen = 0; - Iterator itr = sendQueueV4.iterator(); - do { - i = itr.next().length; - lastLen = GamePacketOutputBuffer.getVarIntSize(i) + i; - totalLen += lastLen; - ++sendCount; - }while(totalLen < 32760 && itr.hasNext()); - if(totalLen >= 32760) { - --sendCount; - totalLen -= lastLen; - } - if(sendCount <= 1) { - pkt = sendQueueV4.remove(0); - sendPluginMessage(owner, GamePluginMessageConstants.V4_CHANNEL, pkt); - continue; - } - byte[] toSend = new byte[1 + totalLen + GamePacketOutputBuffer.getVarIntSize(sendCount)]; - ByteBuf sendBuffer = Unpooled.wrappedBuffer(toSend); - sendBuffer.writerIndex(0); - sendBuffer.writeByte(0xFF); - ProtocolUtils.writeVarInt(sendBuffer, sendCount); - for(j = 0; j < sendCount; ++j) { - pkt = sendQueueV4.remove(0); - ProtocolUtils.writeVarInt(sendBuffer, pkt.length); - sendBuffer.writeBytes(pkt); - } - sendPluginMessage(owner, GamePluginMessageConstants.V4_CHANNEL, toSend); - } - } - } - - public static GameMessageHandler createServerHandler(int protocolVersion, ConnectedPlayer conn, EaglerPlayerData playerData, EaglerXVelocity plugin) { - switch(protocolVersion) { - case 2: - case 3: - return new ServerV3MessageHandler(playerData, plugin); - case 4: - return new ServerV4MessageHandler(conn, playerData, plugin); - default: - throw new IllegalArgumentException("Unknown protocol verison: " + protocolVersion); - } - } - - public static void sendHelper(ConnectedPlayer conn, GameMessagePacket packet) { - EaglerPlayerData p = EaglerPipeline.getEaglerHandle(conn); - if(p != null) { - p.sendEaglerMessage(packet); - }else { - throw new UnsupportedOperationException("Tried to send eagler packet on a non-eagler connection!"); - } - } - - public static void sendPluginMessage(ConnectedPlayer conn, String channel, byte[] data) { - // Velocity channel registry can go fuck itself - MinecraftConnection mc = conn.getConnection(); - if(mc != null) { - mc.write(new PluginMessagePacket(channel, Unpooled.wrappedBuffer(data))); - } - } - - public ConnectedPlayer getUserConnection() { - return owner; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV3MessageHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV3MessageHandler.java deleted file mode 100644 index b58573e1..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV3MessageHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.*; - -public class ServerV3MessageHandler implements GameMessageHandler { - - private final EaglerPlayerData eaglerHandle; - private final EaglerXVelocity plugin; - - public ServerV3MessageHandler(EaglerPlayerData eaglerHandle, EaglerXVelocity plugin) { - this.eaglerHandle = eaglerHandle; - this.plugin = plugin; - } - - public void handleClient(CPacketGetOtherCapeEAG packet) { - plugin.getCapeService().processGetOtherCape(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - - public void handleClient(CPacketGetOtherSkinEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - - public void handleClient(CPacketGetSkinByURLEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), packet.url, eaglerHandle); - } - - public void handleClient(CPacketVoiceSignalConnectEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeConnect(eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalDescEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDesc(new UUID(packet.uuidMost, packet.uuidLeast), packet.desc, eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectV3EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - if(packet.isPeerType) { - svc.handleVoiceSignalPacketTypeDisconnectPeer(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - }else { - svc.handleVoiceSignalPacketTypeDisconnect(eaglerHandle); - } - } - } - - public void handleClient(CPacketVoiceSignalICEEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeICE(new UUID(packet.uuidMost, packet.uuidLeast), packet.ice, eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalRequestEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeRequest(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV4MessageHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV4MessageHandler.java deleted file mode 100644 index 84f8d222..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV4MessageHandler.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol; - -import java.util.Arrays; -import java.util.Optional; -import java.util.UUID; - -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.kyori.adventure.text.Component; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewMessage; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventWebViewOpenClose; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftWebViewChannelEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftWebViewMessageEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerPauseMenuConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessageHandler; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.*; - -public class ServerV4MessageHandler implements GameMessageHandler { - - private final ConnectedPlayer conn; - private final EaglerPlayerData eaglerHandle; - private final EaglerXVelocity plugin; - - public ServerV4MessageHandler(ConnectedPlayer conn, EaglerPlayerData eaglerHandle, EaglerXVelocity plugin) { - this.conn = conn; - this.eaglerHandle = eaglerHandle; - this.plugin = plugin; - } - - public void handleClient(CPacketGetOtherCapeEAG packet) { - plugin.getCapeService().processGetOtherCape(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - - public void handleClient(CPacketGetOtherSkinEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - - public void handleClient(CPacketGetSkinByURLEAG packet) { - plugin.getSkinService().processGetOtherSkin(new UUID(packet.uuidMost, packet.uuidLeast), packet.url, eaglerHandle); - } - - public void handleClient(CPacketVoiceSignalConnectEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeConnect(eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalDescEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDesc(new UUID(packet.uuidMost, packet.uuidLeast), packet.desc, eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectV4EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDisconnect(eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalDisconnectPeerV4EAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeDisconnectPeer(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalICEEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeICE(new UUID(packet.uuidMost, packet.uuidLeast), packet.ice, eaglerHandle); - } - } - - public void handleClient(CPacketVoiceSignalRequestEAG packet) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eaglerHandle.getEaglerListenerConfig().getEnableVoiceChat()) { - svc.handleVoiceSignalPacketTypeRequest(new UUID(packet.uuidMost, packet.uuidLeast), eaglerHandle); - } - } - - public void handleClient(CPacketGetOtherClientUUIDV4EAG packet) { - Optional player = plugin.getProxy().getPlayer(new UUID(packet.playerUUIDMost, packet.playerUUIDLeast)); - if(player.isPresent()) { - EaglerPlayerData conn2 = EaglerPipeline.getEaglerHandle(player.get()); - if(conn2 != null) { - UUID uuid = conn2.getClientBrandUUID(); - if (uuid != null) { - eaglerHandle.sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, - uuid.getMostSignificantBits(), uuid.getLeastSignificantBits())); - return; - } - }else { - eaglerHandle.sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, - EaglerXVelocityAPIHelper.BRAND_VANILLA_UUID.getMostSignificantBits(), - EaglerXVelocityAPIHelper.BRAND_VANILLA_UUID.getLeastSignificantBits())); - return; - } - } - eaglerHandle.sendEaglerMessage(new SPacketOtherPlayerClientUUIDV4EAG(packet.requestId, 0l, 0l)); - } - - public void handleClient(CPacketRequestServerInfoV4EAG packet) { - EaglerPauseMenuConfig conf = plugin.getConfig().getPauseMenuConf(); - if (conf != null && conf.getEnabled() - && conf.getPacket().serverInfoMode == SPacketCustomizePauseMenuV4EAG.SERVER_INFO_MODE_SHOW_EMBED_OVER_WS - && Arrays.equals(conf.getServerInfoHash(), packet.requestHash)) { - synchronized(eaglerHandle.serverInfoSendBuffer) { - if(eaglerHandle.hasSentServerInfo.getAndSet(true)) { - eaglerHandle.getPlayerObj().disconnect(Component.text("Duplicate server info request")); - return; - } - eaglerHandle.serverInfoSendBuffer.clear(); - eaglerHandle.serverInfoSendBuffer.addAll(conf.getServerInfo()); - } - }else { - eaglerHandle.getPlayerObj().disconnect(Component.text("Invalid server info request")); - } - } - - public void handleClient(CPacketWebViewMessageV4EAG packet) { - if(eaglerHandle.isWebViewChannelAllowed) { - if(eaglerHandle.webViewMessageChannelOpen.get()) { - if(eaglerHandle.getRPCEventSubscribed(EnumSubscribedEvent.WEBVIEW_MESSAGE)) { - eaglerHandle.getRPCSessionHandler().sendRPCPacket(new SPacketRPCEventWebViewMessage( - eaglerHandle.webViewMessageChannelName, packet.type, packet.data)); - } - plugin.getProxy().getEventManager().fire(new EaglercraftWebViewMessageEvent(conn, - eaglerHandle.getEaglerListenerConfig(), eaglerHandle.webViewMessageChannelName, packet)); - } - }else { - eaglerHandle.getPlayerObj().disconnect(Component.text("Webview channel permissions have not been enabled!")); - } - } - - public void handleClient(CPacketWebViewMessageEnV4EAG packet) { - if(eaglerHandle.isWebViewChannelAllowed) { - eaglerHandle.webViewMessageChannelOpen.set(packet.messageChannelOpen); - String oldChannelName = eaglerHandle.webViewMessageChannelName; - eaglerHandle.webViewMessageChannelName = packet.messageChannelOpen ? packet.channelName : null; - if(eaglerHandle.getRPCEventSubscribed(EnumSubscribedEvent.WEBVIEW_OPEN_CLOSE)) { - eaglerHandle.getRPCSessionHandler().sendRPCPacket(new SPacketRPCEventWebViewOpenClose( - packet.messageChannelOpen, packet.messageChannelOpen ? packet.channelName : oldChannelName)); - } - plugin.getProxy().getEventManager() - .fire(new EaglercraftWebViewChannelEvent(conn, eaglerHandle.getEaglerListenerConfig(), - packet.messageChannelOpen ? eaglerHandle.webViewMessageChannelName : oldChannelName, - packet.messageChannelOpen ? EaglercraftWebViewChannelEvent.EventType.CHANNEL_OPEN - : EaglercraftWebViewChannelEvent.EventType.CHANNEL_CLOSE)); - }else { - eaglerHandle.getPlayerObj().disconnect(Component.text("Webview channel permissions have not been enabled!")); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/MOTDQueryHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/MOTDQueryHandler.java deleted file mode 100644 index e1f545c1..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/MOTDQueryHandler.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.velocitypowered.api.proxy.Player; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query.EaglerQuerySimpleHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query.MOTDConnection; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.MOTDCacheConfiguration; - -public class MOTDQueryHandler extends EaglerQuerySimpleHandler implements MOTDConnection { - - private long creationTime = 0l; - - private String line1; - private String line2; - private List players; - private int[] bitmap; - private int onlinePlayers; - private int maxPlayers; - private boolean hasIcon; - private boolean iconDirty; - private String subType; - private String returnType; - - @Override - protected void begin(String queryType) { - creationTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); - subType = queryType; - returnType = "MOTD"; - EaglerListenerConfig listener = getListener(); - List lns = listener.getServerMOTD(); - if(lns.size() >= 1) { - line1 = lns.get(0); - } - if(lns.size() >= 2) { - line2 = lns.get(1); - } - maxPlayers = listener.getMaxPlayer(); - onlinePlayers = EaglerXVelocity.proxy().getPlayerCount(); - players = new ArrayList<>(); - for(Player pp : EaglerXVelocity.proxy().getAllPlayers()) { - players.add(pp.getUsername()); - if(players.size() >= 9) { - players.add("\u00A77\u00A7o(" + (onlinePlayers - players.size()) + " more)"); - break; - } - } - bitmap = new int[4096]; - int i = queryType.indexOf('.'); - if(i > 0) { - subType = queryType.substring(i + 1); - if(subType.length() == 0) { - subType = "motd"; - } - }else { - subType = "motd"; - } - if(!subType.startsWith("noicon") && !subType.startsWith("cache.noicon")) { - int[] maybeIcon = listener.getServerIconPixels(); - iconDirty = hasIcon = maybeIcon != null; - if(hasIcon) { - System.arraycopy(maybeIcon, 0, bitmap, 0, 4096); - } - } - } - - @Override - public long getConnectionTimestamp() { - return creationTime; - } - - @Override - public void sendToUser() { - if(!isClosed()) { - JsonObject obj = new JsonObject(); - if(subType.startsWith("cache.anim")) { - obj.addProperty("unsupported", true); - sendJsonResponseAndClose(returnType, obj); - return; - }else if(subType.startsWith("cache")) { - JsonArray cacheControl = new JsonArray(); - MOTDCacheConfiguration cc = getListener().getMOTDCacheConfig(); - if(cc.cacheServerListAnimation) { - cacheControl.add("animation"); - } - if(cc.cacheServerListResults) { - cacheControl.add("results"); - } - if(cc.cacheServerListTrending) { - cacheControl.add("trending"); - } - if(cc.cacheServerListPortfolios) { - cacheControl.add("portfolio"); - } - obj.add("cache", cacheControl); - obj.addProperty("ttl", cc.cacheTTL); - }else { - MOTDCacheConfiguration cc = getListener().getMOTDCacheConfig();; - obj.addProperty("cache", cc.cacheServerListAnimation || cc.cacheServerListResults || - cc.cacheServerListTrending || cc.cacheServerListPortfolios); - } - boolean noIcon = subType.startsWith("noicon") || subType.startsWith("cache.noicon"); - JsonArray motd = new JsonArray(); - if(line1 != null && line1.length() > 0) motd.add(line1); - if(line2 != null && line2.length() > 0) motd.add(line2); - obj.add("motd", motd); - obj.addProperty("icon", hasIcon && !noIcon); - obj.addProperty("online", onlinePlayers); - obj.addProperty("max", maxPlayers); - JsonArray playerz = new JsonArray(); - for(String s : players) { - playerz.add(s); - } - obj.add("players", playerz); - sendJsonResponse(returnType, obj); - if(hasIcon && !noIcon && iconDirty && bitmap != null) { - byte[] iconPixels = new byte[16384]; - for(int i = 0, j; i < 4096; ++i) { - j = i << 2; - iconPixels[j] = (byte)(bitmap[i] >>> 16); - iconPixels[j + 1] = (byte)(bitmap[i] >>> 8); - iconPixels[j + 2] = (byte)(bitmap[i] & 0xFF); - iconPixels[j + 3] = (byte)(bitmap[i] >>> 24); - } - sendBinaryResponse(iconPixels); - iconDirty = false; - } - if(subType.startsWith("cache")) { - close(); - } - } - } - - @Override - public String getLine1() { - return line1; - } - - @Override - public String getLine2() { - return line2; - } - - @Override - public List getPlayerList() { - return players; - } - - @Override - public int[] getBitmap() { - return bitmap; - } - - @Override - public int getOnlinePlayers() { - return onlinePlayers; - } - - @Override - public int getMaxPlayers() { - return maxPlayers; - } - - @Override - public String getSubType() { - return subType; - } - - @Override - public void setLine1(String p) { - line1 = p; - } - - @Override - public void setLine2(String p) { - line2 = p; - } - - @Override - public void setPlayerList(List p) { - players = p; - } - - @Override - public void setPlayerList(String... p) { - players = Arrays.asList(p); - } - - @Override - public void setBitmap(int[] p) { - iconDirty = hasIcon = true; - bitmap = p; - } - - @Override - public void setOnlinePlayers(int i) { - onlinePlayers = i; - } - - @Override - public void setMaxPlayers(int i) { - maxPlayers = i; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/QueryManager.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/QueryManager.java deleted file mode 100644 index f1dd5d70..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/QueryManager.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query; - -import java.util.HashMap; -import java.util.Map; - -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.HttpServerQueryHandler; - -public class QueryManager { - - private static final Map> queryTypes = new HashMap<>(); - - static { - queryTypes.put("motd", MOTDQueryHandler.class); - queryTypes.put("motd.cache", MOTDQueryHandler.class); - queryTypes.put("version", VersionQueryHandler.class); - queryTypes.put("revoke_session_token", RevokeSessionQueryHandler.class); - } - - public static HttpServerQueryHandler createQueryHandler(String type) { - Class clazz; - synchronized(queryTypes) { - clazz = queryTypes.get(type); - } - if(clazz != null) { - HttpServerQueryHandler obj = null; - try { - obj = clazz.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - EaglerXVelocity.logger().error("Exception creating query handler for '" + type + "'!", e); - } - if(obj != null) { - return obj; - } - } - return null; - } - - public static void registerQueryType(String name, Class clazz) { - synchronized(queryTypes) { - if(queryTypes.put(name, clazz) != null) { - EaglerXVelocity.logger().warn("Query type '" + name + "' was registered twice, probably by two different plugins!"); - Thread.dumpStack(); - } - } - } - - public static void unregisterQueryType(String name) { - synchronized(queryTypes) { - queryTypes.remove(name); - } - } - - private static JsonObject createBaseResponse() { - EaglerXVelocity plugin = EaglerXVelocity.getEagler(); - EaglerVelocityConfig conf = plugin.getConfig(); - JsonObject json = new JsonObject(); - json.addProperty("name", conf.getServerName()); - json.addProperty("brand", "lax1dude"); - json.addProperty("vers", EaglerXVelocityVersion.ID + "/" + EaglerXVelocityVersion.VERSION); - json.addProperty("cracked", conf.isCracked()); - json.addProperty("time", EaglerXVelocityAPIHelper.steadyTimeMillis()); - json.addProperty("uuid", conf.getServerUUID().toString()); - return json; - } - - public static JsonObject createStringResponse(String type, String str) { - JsonObject ret = createBaseResponse(); - ret.addProperty("type", type); - ret.addProperty("data", str); - return ret; - } - - public static JsonObject createJsonObjectResponse(String type, JsonObject json) { - JsonObject ret = createBaseResponse(); - ret.addProperty("type", type); - ret.add("data", json); - return ret; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/RevokeSessionQueryHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/RevokeSessionQueryHandler.java deleted file mode 100644 index dcbae3fa..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/RevokeSessionQueryHandler.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query; - -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftRevokeSessionQueryEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftRevokeSessionQueryEvent.EnumSessionRevokeStatus; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query.EaglerQueryHandler; - -public class RevokeSessionQueryHandler extends EaglerQueryHandler { - - @Override - protected void begin(String queryType) { - this.setKeepAlive(true); - this.acceptBinary(); - this.setMaxAge(5000l); - this.sendStringResponse("revoke_session_token", "ready"); - } - - @Override - protected void processString(String str) { - this.close(); - } - - @Override - protected void processJson(JsonObject obj) { - this.close(); - } - - @Override - protected void processBytes(byte[] bytes) { - if(bytes.length > 255) { - JsonObject response = new JsonObject(); - response.addProperty("status", "error"); - response.addProperty("code", 3); - response.addProperty("delete", false); - sendJsonResponseAndClose("revoke_session_token", response); - return; - } - this.setMaxAge(30000l); - EaglercraftRevokeSessionQueryEvent evt = new EaglercraftRevokeSessionQueryEvent(this.getAddress(), this.getOrigin(), bytes, this); - evt = EaglerXVelocity.proxy().getEventManager().fire(evt).join(); - JsonObject response = new JsonObject(); - EnumSessionRevokeStatus stat = evt.getResultStatus(); - response.addProperty("status", stat.status); - if(stat.code != -1) { - response.addProperty("code", stat.code); - } - if(stat != EnumSessionRevokeStatus.SUCCESS) { - response.addProperty("delete", evt.getShouldDeleteCookie()); - } - sendJsonResponseAndClose("revoke_session_token", response); - } - - @Override - protected void closed() { - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/VersionQueryHandler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/VersionQueryHandler.java deleted file mode 100644 index 79d0dc04..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/VersionQueryHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.query; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.query.EaglerQuerySimpleHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; - -public class VersionQueryHandler extends EaglerQuerySimpleHandler { - - @Override - protected void begin(String queryType) { - JsonObject responseObj = new JsonObject(); - JsonArray handshakeVersions = new JsonArray(); - EaglerListenerConfig cfg = this.getListener(); - if(cfg.isAllowV3()) { - handshakeVersions.add(2); - handshakeVersions.add(3); - } - if(cfg.isAllowV4()) { - handshakeVersions.add(4); - } - responseObj.add("handshakeVersions", handshakeVersions); - JsonObject protocolVersions = new JsonObject(); - protocolVersions.addProperty("min", cfg.getMinMCProtocol()); - protocolVersions.addProperty("max", cfg.getMaxMCProtocol()); - responseObj.add("protocolVersions", protocolVersions); - JsonObject proxyInfo = new JsonObject(); - proxyInfo.addProperty("brand", EaglerXVelocity.proxy().getVersion().getName()); - proxyInfo.addProperty("vers", EaglerXVelocity.proxy().getVersion().getVersion()); - responseObj.add("proxyVersions", proxyInfo); - sendJsonResponseAndClose("version", responseObj); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpContentType.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpContentType.java deleted file mode 100644 index 5040c40d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpContentType.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web; - -import java.util.HashSet; -import java.util.Set; - -public class HttpContentType { - - public final Set extensions; - public final String mimeType; - public final String charset; - public final String httpHeader; - public final String cacheControlHeader; - public final long fileBrowserCacheTTL; - - public static final HttpContentType defaultType = new HttpContentType(new HashSet<>(), "application/octet-stream", null, 14400000l); - - public HttpContentType(Set extensions, String mimeType, String charset, long fileBrowserCacheTTL) { - this.extensions = extensions; - this.mimeType = mimeType; - this.charset = charset; - this.fileBrowserCacheTTL = fileBrowserCacheTTL; - if(charset == null) { - this.httpHeader = mimeType; - }else { - this.httpHeader = mimeType + "; charset=" + charset; - } - if(fileBrowserCacheTTL > 0l) { - this.cacheControlHeader = "max-age=" + (fileBrowserCacheTTL / 1000l); - }else { - this.cacheControlHeader = "no-cache"; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpMemoryCache.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpMemoryCache.java deleted file mode 100644 index 5f9c29c0..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpMemoryCache.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.SimpleTimeZone; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; - -public class HttpMemoryCache { - - public File fileObject; - public String filePath; - public ByteBuf fileData; - public HttpContentType contentType; - public long lastCacheHit; - public long lastDiskReload; - public long lastDiskModified; - private final String server; - - private static final SimpleDateFormat gmt; - - static { - gmt = new SimpleDateFormat(); - gmt.setTimeZone(new SimpleTimeZone(0, "GMT")); - gmt.applyPattern("dd MMM yyyy HH:mm:ss z"); - } - - public HttpMemoryCache(File fileObject, String filePath, ByteBuf fileData, HttpContentType contentType, - long lastCacheHit, long lastDiskReload, long lastDiskModified) { - this.fileObject = fileObject; - this.filePath = filePath; - this.fileData = fileData; - this.contentType = contentType; - this.lastCacheHit = lastCacheHit; - this.lastDiskReload = lastDiskReload; - this.lastDiskModified = lastDiskModified; - this.server = EaglerXVelocityVersion.ID + "/" + EaglerXVelocityVersion.VERSION; - } - - public DefaultFullHttpResponse createHTTPResponse() { - return createHTTPResponse(HttpResponseStatus.OK); - } - - public DefaultFullHttpResponse createHTTPResponse(HttpResponseStatus code) { - DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, code, Unpooled.wrappedBuffer(fileData.retain())); - HttpHeaders responseHeaders = response.headers(); - Date d = new Date(); - responseHeaders.add(HttpHeaderNames.CONTENT_TYPE, contentType.httpHeader); - responseHeaders.add(HttpHeaderNames.CONTENT_LENGTH, fileData.readableBytes()); - responseHeaders.add(HttpHeaderNames.CACHE_CONTROL, contentType.cacheControlHeader); - responseHeaders.add(HttpHeaderNames.DATE, gmt.format(d)); - long l = contentType.fileBrowserCacheTTL; - if(l > 0l && l != Long.MAX_VALUE) { - d.setTime(d.getTime() + l); - responseHeaders.add(HttpHeaderNames.EXPIRES, gmt.format(d)); - } - d.setTime(lastDiskModified); - responseHeaders.add(HttpHeaderNames.LAST_MODIFIED, gmt.format(d)); - responseHeaders.add(HttpHeaderNames.SERVER, server); - return response; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpWebServer.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpWebServer.java deleted file mode 100644 index 5d1f3038..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/web/HttpWebServer.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web; - -import java.io.File; -import java.io.FileInputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import com.google.common.collect.Sets; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class HttpWebServer { - - public final File directory; - public final Map contentTypes; - private final Map filesCache; - private final List index; - private final String page404; - private static HttpMemoryCache default404Page; - private static HttpMemoryCache default404UpgradePage; - - public HttpWebServer(File directory, Map contentTypes, List index, String page404) { - this.directory = directory; - this.contentTypes = contentTypes; - this.filesCache = new HashMap<>(); - this.index = index; - this.page404 = page404; - } - - public void flushCache() { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - synchronized(filesCache) { - Iterator itr = filesCache.values().iterator(); - while(itr.hasNext()) { - HttpMemoryCache i = itr.next(); - if(i.contentType.fileBrowserCacheTTL != Long.MAX_VALUE && millis - i.lastCacheHit > 900000l) { - i.fileData.release(); - itr.remove(); - } - } - } - } - - public HttpMemoryCache retrieveFile(String path) { - try { - String[] pathSplit = path.split("(\\\\|\\/)+"); - - List pathList = pathSplit.length == 0 ? null : new ArrayList<>(); - for(int i = 0; i < pathSplit.length; ++i) { - pathSplit[i] = pathSplit[i].trim(); - if(pathSplit[i].length() > 0) { - if(!pathSplit[i].equals(".") && !pathSplit[i].startsWith("..")) { - pathList.add(pathSplit[i]); - } - } - } - - HttpMemoryCache cached; - - if(pathList == null || pathList.size() == 0) { - for(int i = 0, l = index.size(); i < l; ++i) { - cached = retrieveFile(index.get(i)); - if(cached != null) { - return cached; - } - } - return null; - } - - String joinedPath = String.join("/", pathList); - - //TODO: Rewrite this to cause less lock contention - synchronized(filesCache) { - cached = filesCache.get(joinedPath); - - if(cached != null) { - cached = validateCache(cached); - if(cached != null) { - return cached; - }else { - filesCache.remove(joinedPath); - } - } - - File f = new File(directory, joinedPath); - - if(!f.exists()) { - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - - if(f.isDirectory()) { - for(int i = 0, l = index.size(); i < l; ++i) { - String p = joinedPath + "/" + index.get(i); - cached = filesCache.get(p); - if(cached != null) { - cached = validateCache(cached); - if(cached != null) { - filesCache.put(joinedPath, cached); - }else { - filesCache.remove(p); - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - return cached; - } - } - for(int i = 0, l = index.size(); i < l; ++i) { - String p = joinedPath + "/" + index.get(i); - File ff = new File(directory, p); - if(ff.isFile()) { - HttpMemoryCache memCache = retrieveFile(ff, p); - if(memCache != null) { - filesCache.put(joinedPath, memCache); - return memCache; - } - } - } - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - }else { - HttpMemoryCache memCache = retrieveFile(f, joinedPath); - if(memCache != null) { - filesCache.put(joinedPath, memCache); - return memCache; - }else { - if(page404 == null || path.equals(page404)) { - return default404Page; - }else { - return retrieveFile(page404); - } - } - } - } - }catch(Throwable t) { - return default404Page; - } - } - - private HttpMemoryCache retrieveFile(File path, String requestCachePath) { - int fileSize = (int)path.length(); - try(FileInputStream is = new FileInputStream(path)) { - ByteBuf file = Unpooled.buffer(fileSize, fileSize); - file.writeBytes(is, fileSize); - String ext = path.getName(); - HttpContentType ct = null; - int i = ext.lastIndexOf('.'); - if(i != -1) { - ct = contentTypes.get(ext.substring(i + 1)); - } - if(ct == null) { - ct = HttpContentType.defaultType; - } - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(path, requestCachePath, file, ct, millis, millis, path.lastModified()); - }catch(Throwable t) { - return null; - } - } - - private HttpMemoryCache validateCache(HttpMemoryCache file) { - if(file.fileObject == null) { - return file; - } - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - file.lastCacheHit = millis; - if(millis - file.lastDiskReload > 4000l) { - File f = file.fileObject; - if(!f.isFile()) { - return null; - }else { - long lastMod = f.lastModified(); - if(lastMod != file.lastDiskModified) { - int fileSize = (int)f.length(); - try(FileInputStream is = new FileInputStream(f)) { - file.fileData.release(); - file.fileData = Unpooled.buffer(fileSize, fileSize); - file.fileData.writeBytes(is, fileSize); - file.lastDiskReload = millis; - file.lastDiskModified = lastMod; - return file; - }catch(Throwable t) { - return null; - } - }else { - return file; - } - } - }else { - return file; - } - } - - public static void regenerate404Pages() { - if(default404Page != null) { - default404Page.fileData.release(); - } - default404Page = regenerateDefault404(); - if(default404UpgradePage != null) { - default404UpgradePage.fileData.release(); - } - default404UpgradePage = regenerateDefaultUpgrade404(); - } - - public static HttpMemoryCache getHTTP404() { - return default404Page; - } - - public static HttpMemoryCache getWebSocket404() { - return default404UpgradePage; - } - - private static HttpMemoryCache regenerateDefault404() { - EaglerXVelocity plugin = EaglerXVelocity.getEagler(); - byte[] src = ("" + htmlEntities(plugin.getConfig().getServerName()) + "" - + "

    404 Not Found


    " - + "The requested resource " - + " could not be found on this server!

    " + htmlEntities(EaglerXVelocityVersion.NAME) + "/" - + htmlEntities(EaglerXVelocityVersion.VERSION) + "

    ").getBytes(StandardCharsets.UTF_8); - HttpContentType htmlContentType = new HttpContentType(Sets.newHashSet("html"), "text/html", "utf-8", 120000l); - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(null, "~404", Unpooled.wrappedBuffer(src), htmlContentType, millis, millis, millis); - } - - private static HttpMemoryCache regenerateDefaultUpgrade404() { - EaglerXVelocity plugin = EaglerXVelocity.getEagler(); - String name = htmlEntities(plugin.getConfig().getServerName()); - byte[] src = ("" + name + - "

    " - + "404 'Websocket Upgrade Failure' (rip)

    The URL you have requested is the physical WebSocket address of '" + name + "'

    To correctly join this server, load the latest EaglercraftX 1.8 client, click the 'Direct Connect' button
    on the 'Multiplayer' screen, " - + "and enter this URL as the server address

    ").getBytes(StandardCharsets.UTF_8); - HttpContentType htmlContentType = new HttpContentType(Sets.newHashSet("html"), "text/html", "utf-8", 14400000l); - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - return new HttpMemoryCache(null, "~404", Unpooled.wrappedBuffer(src), htmlContentType, millis, millis, millis); - } - - public static String htmlEntities(String input) { - return input.replace("<", "<").replace(">", ">"); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/CompatWarning.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/CompatWarning.java deleted file mode 100644 index 7ea80c4c..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/CompatWarning.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.shit; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; - -public class CompatWarning { - - public static void displayCompatWarning() { - String stfu = System.getProperty("eaglerxvelocity.stfu"); - if("true".equalsIgnoreCase(stfu)) { - return; - } - String[] compatWarnings = new String[] { - ":>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>", - ":> ", - ":> EAGLERCRAFTXVELOCITY WARNING:", - ":> ", - ":> This plugin wasn\'t tested to be \'working\'", - ":> with ANY version of Velocity (and forks)", - ":> apart from the versions listed below:", - ":> ", - ":> - Velocity: " + EaglerXVelocityVersion.NATIVE_VELOCITY_BUILD, - ":> - " + EaglerXVelocityVersion.NATIVE_VELOCITY_BUILD_DL, - ":> ", - ":> This is not a Bukkit/Spigot plugin!", - ":> ", - ":> Use \"-Deaglerxvelocity.stfu=true\" to hide", - ":> ", - ":>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>:>" - }; - for(int i = 0; i < compatWarnings.length; ++i) { - System.err.println(compatWarnings[i]); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/MainClass.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/MainClass.java deleted file mode 100644 index 5dec3202..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/shit/MainClass.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.shit; - -import java.awt.GraphicsEnvironment; - -import javax.swing.JOptionPane; - -public class MainClass { - - public static void main(String[] args) { - System.err.println(); - System.err.println("ERROR: The EaglerXVelocity 1.8 jar file is a PLUGIN intended to be used with Velocity!"); - System.err.println("Place this file in the \"plugins\" directory of your Velocity installation"); - System.err.println(); - try { - tryShowPopup(); - }catch(Throwable t) { - } - System.exit(0); - } - - private static void tryShowPopup() throws Throwable { - if(!GraphicsEnvironment.isHeadless()) { - JOptionPane.showMessageDialog(null, "ERROR: The EaglerXVelocity 1.8 jar file is a PLUGIN intended to be used with Velocity!\nPlace this file in the \"plugins\" directory of your Velocity installation", "EaglerXVelocity", JOptionPane.ERROR_MESSAGE); - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/AsyncSkinProvider.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/AsyncSkinProvider.java deleted file mode 100644 index fb2bc06b..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/AsyncSkinProvider.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.function.Consumer; - -import javax.imageio.ImageIO; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.BinaryHttpClient.Response; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.ICacheProvider.CacheLoadedProfile; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.ICacheProvider.CacheLoadedSkin; - -public class AsyncSkinProvider { - - private static class SkinConsumerImpl implements Consumer { - - protected final Consumer responseConsumer; - - protected SkinConsumerImpl(Consumer consumer) { - this.responseConsumer = consumer; - } - - protected void doAccept(byte[] v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown caching new skin!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - BufferedImage image; - try { - image = ImageIO.read(new ByteArrayInputStream(response.data)); - }catch(IOException ex) { - doAccept(null); - return; - } - try { - int srcWidth = image.getWidth(); - int srcHeight = image.getHeight(); - if(srcWidth < 64 || srcWidth > 512 || srcHeight < 32 || srcHeight > 512) { - doAccept(null); - return; - } - if(srcWidth != 64 || srcHeight != 64) { - if(srcWidth % 64 == 0) { - if(srcWidth == srcHeight * 2) { - BufferedImage scaled = new BufferedImage(64, 32, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = scaled.createGraphics(); - graphics.drawImage(image, 0, 0, 64, 32, 0, 0, srcWidth, srcHeight, null); - graphics.dispose(); - image = scaled; - srcWidth = 64; - srcHeight = 32; - }else if(srcWidth == srcHeight) { - BufferedImage scaled = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = scaled.createGraphics(); - graphics.drawImage(image, 0, 0, 64, 64, 0, 0, srcWidth, srcHeight, null); - graphics.dispose(); - image = scaled; - srcWidth = 64; - srcHeight = 64; - }else { - doAccept(null); - return; - } - }else { - doAccept(null); - return; - } - } - if(srcWidth == 64 && srcHeight == 64) { - int[] tmp = new int[4096]; - byte[] loadedPixels = new byte[16384]; - image.getRGB(0, 0, 64, 64, tmp, 0, 64); - SkinRescaler.convertToBytes(tmp, loadedPixels); - SkinPackets.setAlphaForChestV3(loadedPixels); - doAccept(loadedPixels); - return; - }else if(srcWidth == 64 && srcHeight == 32) { - int[] tmp1 = new int[2048]; - byte[] loadedPixels = new byte[16384]; - image.getRGB(0, 0, 64, 32, tmp1, 0, 64); - SkinRescaler.convert64x32To64x64(tmp1, loadedPixels); - SkinPackets.setAlphaForChestV3(loadedPixels); - doAccept(loadedPixels); - return; - }else { - doAccept(null); - return; - } - }catch(Throwable t) { - - } - } - } - - } - - private static class SkinCachingConsumer implements Consumer { - - protected final UUID skinUUID; - protected final String skinTexture; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected SkinCachingConsumer(UUID skinUUID, String skinTexture, ICacheProvider cacheProvider, - Consumer responseConsumer) { - this.skinUUID = skinUUID; - this.skinTexture = skinTexture; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - @Override - public void accept(byte[] skin) { - if(skin != null) { - try { - cacheProvider.cacheSkinByUUID(skinUUID, skinTexture, skin); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown writing new skin to database!", t); - } - responseConsumer.accept(skin); - }else { - responseConsumer.accept(null); - } - } - - } - - public static class CacheFetchedProfile { - - public final UUID uuid; - public final String username; - public final String texture; - public final UUID textureUUID; - public final String model; - - protected CacheFetchedProfile(UUID uuid, String username, String texture, String model) { - this.uuid = uuid; - this.username = username; - this.texture = texture; - this.textureUUID = SkinPackets.createEaglerURLSkinUUID(texture); - this.model = model; - } - - protected CacheFetchedProfile(CacheLoadedProfile profile) { - this.uuid = profile.uuid; - this.username = profile.username; - this.texture = profile.texture; - this.textureUUID = SkinPackets.createEaglerURLSkinUUID(profile.texture); - this.model = profile.model; - } - - } - - private static class ProfileConsumerImpl implements Consumer { - - protected final UUID uuid; - protected final Consumer responseConsumer; - - protected ProfileConsumerImpl(UUID uuid, Consumer responseConsumer) { - this.uuid = uuid; - this.responseConsumer = responseConsumer; - } - - protected void doAccept(CacheFetchedProfile v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown caching new profile!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String username = json.get("name").getAsString().toLowerCase(); - String texture = null; - String model = null; - JsonElement propsElement = json.get("properties"); - if(propsElement != null) { - try { - JsonArray properties = propsElement.getAsJsonArray(); - if(properties.size() > 0) { - for(int i = 0, l = properties.size(); i < l; ++i) { - JsonElement prop = properties.get(i); - if(prop.isJsonObject()) { - JsonObject propObj = prop.getAsJsonObject(); - if(propObj.get("name").getAsString().equals("textures")) { - String value = new String(Base64.decodeBase64(propObj.get("value").getAsString()), StandardCharsets.UTF_8); - JsonObject texturesJson = JsonParser.parseString(value).getAsJsonObject(); - if(texturesJson != null && texturesJson.has("textures")) { - texturesJson = texturesJson.getAsJsonObject("textures"); - JsonElement skin = texturesJson.get("SKIN"); - if(skin != null) { - model = "default"; - JsonObject skinObj = skin.getAsJsonObject(); - JsonElement urlElement = skinObj.get("url"); - if(urlElement != null && !urlElement.isJsonNull()) { - texture = urlElement.getAsString(); - } - JsonElement metaElement = skinObj.get("metadata"); - if(metaElement != null) { - JsonObject metaObj = metaElement.getAsJsonObject(); - JsonElement modelElement = metaObj.get("model"); - if(modelElement != null) { - model = modelElement.getAsString(); - } - } - } - } - break; - } - } - } - } - }catch(Throwable t2) { - } - } - if(texture == null && model == null) { - model = SkinService.isAlex(uuid) ? "slim" : "default"; - } - doAccept(new CacheFetchedProfile(uuid, username, texture, model)); - }catch(Throwable ex) { - doAccept(null); - } - } - } - - } - - private static class ProfileCachingConsumer implements Consumer { - - protected final UUID uuid; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected ProfileCachingConsumer(UUID uuid, ICacheProvider cacheProvider, Consumer responseConsumer) { - this.uuid = uuid; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - @Override - public void accept(CacheFetchedProfile profile) { - if(profile != null) { - try { - cacheProvider.cacheProfileByUUID(uuid, profile.username, profile.texture, profile.model); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown writing new profile to database!", t); - } - responseConsumer.accept(profile); - }else { - responseConsumer.accept(null); - } - } - - } - - private static class UsernameToUUIDConsumerImpl implements Consumer { - - protected final String username; - protected final ICacheProvider cacheProvider; - protected final Consumer responseConsumer; - - protected UsernameToUUIDConsumerImpl(String username, ICacheProvider cacheProvider, Consumer responseConsumer) { - this.username = username; - this.cacheProvider = cacheProvider; - this.responseConsumer = responseConsumer; - } - - protected void doAccept(CacheFetchedProfile v) { - try { - responseConsumer.accept(v); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown caching new profile!", t); - } - } - - @Override - public void accept(Response response) { - if(response == null || response.exception != null || response.code != 200 || response.data == null) { - doAccept(null); - }else { - try { - JsonObject json = JsonParser.parseString(new String(response.data, StandardCharsets.UTF_8)).getAsJsonObject(); - String loadUsername = json.get("name").getAsString().toLowerCase(); - if(!username.equals(loadUsername)) { - doAccept(null); - } - UUID mojangUUID = SkinService.parseMojangUUID(json.get("id").getAsString()); - lookupProfileByUUID(mojangUUID, cacheProvider, responseConsumer, false); - }catch(Throwable t) { - doAccept(null); - } - } - } - - } - - private static final SimpleRateLimiter rateLimitDownload = new SimpleRateLimiter(); - private static final SimpleRateLimiter rateLimitLookup = new SimpleRateLimiter(); - - public static void downloadSkin(String skinTexture, ICacheProvider cacheProvider, Consumer responseConsumer) { - downloadSkin(SkinPackets.createEaglerURLSkinUUID(skinTexture), skinTexture, cacheProvider, responseConsumer); - } - - public static void downloadSkin(UUID skinUUID, String skinTexture, ICacheProvider cacheProvider, Consumer responseConsumer) { - CacheLoadedSkin loadedSkin = cacheProvider.loadSkinByUUID(skinUUID); - if(loadedSkin == null) { - URI uri; - try { - uri = URI.create(skinTexture); - }catch(IllegalArgumentException ex) { - try { - responseConsumer.accept(null); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown handling invalid skin!", t); - } - throw new CancelException(); - } - int globalRatelimit = EaglerXVelocity.getEagler().getConfig().getSkinRateLimitGlobal(); - boolean isRateLimit; - synchronized(rateLimitDownload) { - isRateLimit = !rateLimitDownload.rateLimit(globalRatelimit); - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", uri, new SkinConsumerImpl( - new SkinCachingConsumer(skinUUID, skinTexture, cacheProvider, responseConsumer))); - }else { - EaglerXVelocity.logger().warn("skin system reached the global texture download ratelimit of {} while downloading up \"{}\"", globalRatelimit, skinTexture); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(loadedSkin.texture); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown processing cached skin!", t); - } - throw new CancelException(); - } - } - - public static void lookupProfileByUUID(UUID playerUUID, ICacheProvider cacheProvider, Consumer responseConsumer) { - lookupProfileByUUID(playerUUID, cacheProvider, responseConsumer, true); - } - - private static void lookupProfileByUUID(UUID playerUUID, ICacheProvider cacheProvider, Consumer responseConsumer, boolean rateLimit) { - CacheLoadedProfile profile = cacheProvider.loadProfileByUUID(playerUUID); - if(profile == null) { - URI requestURI = URI.create("https://sessionserver.mojang.com/session/minecraft/profile/" + SkinService.getMojangUUID(playerUUID)); - int globalRatelimit = EaglerXVelocity.getEagler().getConfig().getUuidRateLimitGlobal(); - boolean isRateLimit; - if(rateLimit) { - synchronized(rateLimitLookup) { - isRateLimit = !rateLimitLookup.rateLimit(globalRatelimit); - } - }else { - isRateLimit = false; - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", requestURI, new ProfileConsumerImpl(playerUUID, - new ProfileCachingConsumer(playerUUID, cacheProvider, responseConsumer))); - }else { - EaglerXVelocity.logger().warn("skin system reached the global UUID lookup ratelimit of {} while looking up \"{}\"", globalRatelimit, playerUUID); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(new CacheFetchedProfile(profile)); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown processing cached profile!", t); - } - throw new CancelException(); - } - } - - public static void lookupProfileByUsername(String playerUsername, ICacheProvider cacheProvider, Consumer responseConsumer) { - String playerUsernameLower = playerUsername.toLowerCase(); - CacheLoadedProfile profile = cacheProvider.loadProfileByUsername(playerUsernameLower); - if(profile == null) { - if(!playerUsernameLower.equals(playerUsernameLower.replaceAll("[^a-z0-9_]", "_").trim())) { - try { - responseConsumer.accept(null); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown processing invalid profile!", t); - } - throw new CancelException(); - } - URI requestURI = URI.create("https://api.mojang.com/users/profiles/minecraft/" + playerUsername); - int globalRatelimit = EaglerXVelocity.getEagler().getConfig().getUuidRateLimitGlobal(); - boolean isRateLimit; - synchronized(rateLimitLookup) { - isRateLimit = !rateLimitLookup.rateLimit(globalRatelimit); - } - if(!isRateLimit) { - BinaryHttpClient.asyncRequest("GET", requestURI, new UsernameToUUIDConsumerImpl(playerUsername, cacheProvider, responseConsumer)); - }else { - EaglerXVelocity.logger().warn("skin system reached the global UUID lookup ratelimit of {} while looking up \"{}\"", globalRatelimit, playerUsername); - throw new CancelException(); - } - }else { - try { - responseConsumer.accept(new CacheFetchedProfile(profile)); - }catch(Throwable t) { - EaglerXVelocity.logger().error("Exception thrown processing cached profile!", t); - } - throw new CancelException(); - } - } - - public static class CancelException extends RuntimeException { - - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/Base64.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/Base64.java deleted file mode 100644 index bf140b22..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/Base64.java +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.math.BigInteger; -import java.nio.charset.Charset; - -/** - * Provides Base64 encoding and decoding as defined by - * RFC 2045. - * - *

    - * This class implements section 6.8. Base64 - * Content-Transfer-Encoding from RFC 2045 Multipurpose Internet - * Mail Extensions (MIME) Part One: Format of Internet Message Bodies by - * Freed and Borenstein. - *

    - *

    - * The class can be parameterized in the following manner with various - * constructors: - *

    - *
      - *
    • URL-safe mode: Default off.
    • - *
    • Line length: Default 76. Line length that aren't multiples of 4 will - * still essentially end up being multiples of 4 in the encoded data. - *
    • Line separator: Default is CRLF ("\r\n")
    • - *
    - *

    - * The URL-safe parameter is only applied to encode operations. Decoding - * seamlessly handles both modes. - *

    - *

    - * Since this class operates directly on byte streams, and not character - * streams, it is hard-coded to only encode/decode character encodings which are - * compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, - * etc). - *

    - *

    - * This class is thread-safe. - *

    - * - * @see RFC 2045 - * @since 1.0 - */ -public class Base64 extends BaseNCodec { - - /** - * BASE32 characters are 6 bits in length. They are formed by taking a block of - * 3 octets to form a 24-bit string, which is converted into 4 BASE64 - * characters. - */ - private static final int BITS_PER_ENCODED_BYTE = 6; - private static final int BYTES_PER_UNENCODED_BLOCK = 3; - private static final int BYTES_PER_ENCODED_BLOCK = 4; - - /** - * This array is a lookup table that translates 6-bit positive integer index - * values into their "Base64 Alphabet" equivalents as specified in Table 1 of - * RFC 2045. - * - * Thanks to "commons" project in ws.apache.org for this code. - * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ - */ - private static final byte[] STANDARD_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; - - /** - * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / changed - * to - and _ to make the encoded Base64 results more URL-SAFE. This table is - * only used when the Base64's mode is set to URL-SAFE. - */ - private static final byte[] URL_SAFE_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', - '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' }; - - /** - * This array is a lookup table that translates Unicode characters drawn from - * the "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into their 6-bit - * positive integer equivalents. Characters that are not in the Base64 alphabet - * but fall within the bounds of the array are translated to -1. - * - * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This - * means decoder seamlessly handles both URL_SAFE and STANDARD base64. (The - * encoder, on the other hand, needs to know ahead of time what to emit). - * - * Thanks to "commons" project in ws.apache.org for this code. - * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ - */ - private static final byte[] DECODE_TABLE = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, // 20-2f + - / - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9 - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-O - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 70-7a p-z - }; - - /** - * Base64 uses 6-bit fields. - */ - /** Mask used to extract 6 bits, used when encoding */ - private static final int MASK_6BITS = 0x3f; - /** Mask used to extract 4 bits, used when decoding final trailing character. */ - private static final int MASK_4BITS = 0xf; - /** Mask used to extract 2 bits, used when decoding final trailing character. */ - private static final int MASK_2BITS = 0x3; - - // The static final fields above are used for the original static byte[] methods - // on Base64. - // The private member fields below are used with the new streaming approach, - // which requires - // some state be preserved between calls of encode() and decode(). - - /** - * Decodes Base64 data into octets. - *

    - * Note: this method seamlessly handles data encoded in URL-safe or - * normal mode. - *

    - * - * @param base64Data Byte array containing Base64 data - * @return Array containing decoded data. - */ - public static byte[] decodeBase64(final byte[] base64Data) { - return new Base64().decode(base64Data); - } - - /** - * Decodes a Base64 String into octets. - *

    - * Note: this method seamlessly handles data encoded in URL-safe or - * normal mode. - *

    - * - * @param base64String String containing Base64 data - * @return Array containing decoded data. - * @since 1.4 - */ - public static byte[] decodeBase64(final String base64String) { - return new Base64().decode(base64String); - } - - // Implementation of integer encoding used for crypto - /** - * Decodes a byte64-encoded integer according to crypto standards such as W3C's - * XML-Signature. - * - * @param pArray a byte array containing base64 character data - * @return A BigInteger - * @since 1.4 - */ - public static BigInteger decodeInteger(final byte[] pArray) { - return new BigInteger(1, decodeBase64(pArray)); - } - - /** - * Encodes binary data using the base64 algorithm but does not chunk the output. - * - * @param binaryData binary data to encode - * @return byte[] containing Base64 characters in their UTF-8 representation. - */ - public static byte[] encodeBase64(final byte[] binaryData) { - return encodeBase64(binaryData, false); - } - - /** - * Encodes binary data using the base64 algorithm, optionally chunking the - * output into 76 character blocks. - * - * @param binaryData Array containing binary data to encode. - * @param isChunked if {@code true} this encoder will chunk the base64 output - * into 76 character blocks - * @return Base64-encoded data. - * @throws IllegalArgumentException Thrown when the input array needs an output - * array bigger than {@link Integer#MAX_VALUE} - */ - public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) { - return encodeBase64(binaryData, isChunked, false); - } - - /** - * Encodes binary data using the base64 algorithm, optionally chunking the - * output into 76 character blocks. - * - * @param binaryData Array containing binary data to encode. - * @param isChunked if {@code true} this encoder will chunk the base64 output - * into 76 character blocks - * @param urlSafe if {@code true} this encoder will emit - and _ instead of - * the usual + and / characters. Note: no padding is added - * when encoding using the URL-safe alphabet. - * @return Base64-encoded data. - * @throws IllegalArgumentException Thrown when the input array needs an output - * array bigger than {@link Integer#MAX_VALUE} - * @since 1.4 - */ - public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) { - return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE); - } - - /** - * Encodes binary data using the base64 algorithm, optionally chunking the - * output into 76 character blocks. - * - * @param binaryData Array containing binary data to encode. - * @param isChunked if {@code true} this encoder will chunk the base64 - * output into 76 character blocks - * @param urlSafe if {@code true} this encoder will emit - and _ instead - * of the usual + and / characters. Note: no padding is - * added when encoding using the URL-safe alphabet. - * @param maxResultSize The maximum result size to accept. - * @return Base64-encoded data. - * @throws IllegalArgumentException Thrown when the input array needs an output - * array bigger than maxResultSize - * @since 1.4 - */ - public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe, - final int maxResultSize) { - if (binaryData == null || binaryData.length == 0) { - return binaryData; - } - - // Create this so can use the super-class method - // Also ensures that the same roundings are performed by the ctor and the code - final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe); - final long len = b64.getEncodedLength(binaryData); - if (len > maxResultSize) { - throw new IllegalArgumentException("Input array too big, the output array would be bigger (" + len - + ") than the specified maximum size of " + maxResultSize); - } - - return b64.encode(binaryData); - } - - /** - * Encodes binary data using the base64 algorithm and chunks the encoded output - * into 76 character blocks - * - * @param binaryData binary data to encode - * @return Base64 characters chunked in 76 character blocks - */ - public static byte[] encodeBase64Chunked(final byte[] binaryData) { - return encodeBase64(binaryData, true); - } - - /** - * Encodes binary data using the base64 algorithm but does not chunk the output. - * - * NOTE: We changed the behavior of this method from multi-line chunking - * (commons-codec-1.4) to single-line non-chunking (commons-codec-1.5). - * - * @param binaryData binary data to encode - * @return String containing Base64 characters. - * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not). - */ - public static String encodeBase64String(final byte[] binaryData) { - return new String(encodeBase64(binaryData, false), Charset.forName("UTF-8")); - } - - /** - * Encodes binary data using a URL-safe variation of the base64 algorithm but - * does not chunk the output. The url-safe variation emits - and _ instead of + - * and / characters. Note: no padding is added. - * - * @param binaryData binary data to encode - * @return byte[] containing Base64 characters in their UTF-8 representation. - * @since 1.4 - */ - public static byte[] encodeBase64URLSafe(final byte[] binaryData) { - return encodeBase64(binaryData, false, true); - } - - /** - * Encodes binary data using a URL-safe variation of the base64 algorithm but - * does not chunk the output. The url-safe variation emits - and _ instead of + - * and / characters. Note: no padding is added. - * - * @param binaryData binary data to encode - * @return String containing Base64 characters - * @since 1.4 - */ - public static String encodeBase64URLSafeString(final byte[] binaryData) { - return new String(encodeBase64(binaryData, false, true), Charset.forName("UTF-8")); - } - - /** - * Encodes to a byte64-encoded integer according to crypto standards such as - * W3C's XML-Signature. - * - * @param bigInteger a BigInteger - * @return A byte array containing base64 character data - * @throws NullPointerException if null is passed in - * @since 1.4 - */ - public static byte[] encodeInteger(final BigInteger bigInteger) { - return encodeBase64(toIntegerBytes(bigInteger), false); - } - - /** - * Tests a given byte array to see if it contains only valid characters within - * the Base64 alphabet. Currently the method treats whitespace as valid. - * - * @param arrayOctet byte array to test - * @return {@code true} if all bytes are valid characters in the Base64 alphabet - * or if the byte array is empty; {@code false}, otherwise - * @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0. - */ - @Deprecated - public static boolean isArrayByteBase64(final byte[] arrayOctet) { - return isBase64(arrayOctet); - } - - /** - * Returns whether or not the {@code octet} is in the base 64 alphabet. - * - * @param octet The value to test - * @return {@code true} if the value is defined in the the base 64 alphabet, - * {@code false} otherwise. - * @since 1.4 - */ - public static boolean isBase64(final byte octet) { - return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1); - } - - /** - * Tests a given byte array to see if it contains only valid characters within - * the Base64 alphabet. Currently the method treats whitespace as valid. - * - * @param arrayOctet byte array to test - * @return {@code true} if all bytes are valid characters in the Base64 alphabet - * or if the byte array is empty; {@code false}, otherwise - * @since 1.5 - */ - public static boolean isBase64(final byte[] arrayOctet) { - for (int i = 0; i < arrayOctet.length; i++) { - if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) { - return false; - } - } - return true; - } - - /** - * Tests a given String to see if it contains only valid characters within the - * Base64 alphabet. Currently the method treats whitespace as valid. - * - * @param base64 String to test - * @return {@code true} if all characters in the String are valid characters in - * the Base64 alphabet or if the String is empty; {@code false}, - * otherwise - * @since 1.5 - */ - public static boolean isBase64(final String base64) { - return isBase64(base64.getBytes(Charset.forName("UTF-8"))); - } - - /** - * Returns a byte-array representation of a {@code BigInteger} without sign bit. - * - * @param bigInt {@code BigInteger} to be converted - * @return a byte array representation of the BigInteger parameter - */ - static byte[] toIntegerBytes(final BigInteger bigInt) { - int bitlen = bigInt.bitLength(); - // round bitlen - bitlen = ((bitlen + 7) >> 3) << 3; - final byte[] bigBytes = bigInt.toByteArray(); - - if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) { - return bigBytes; - } - // set up params for copying everything but sign bit - int startSrc = 0; - int len = bigBytes.length; - - // if bigInt is exactly byte-aligned, just skip signbit in copy - if ((bigInt.bitLength() % 8) == 0) { - startSrc = 1; - len--; - } - final int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec - final byte[] resizedBytes = new byte[bitlen / 8]; - System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len); - return resizedBytes; - } - - /** - * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE - * above remains static because it is able to decode both STANDARD and URL_SAFE - * streams, but the encodeTable must be a member variable so we can switch - * between the two modes. - */ - private final byte[] encodeTable; - - // Only one decode table currently; keep for consistency with Base32 code - private final byte[] decodeTable = DECODE_TABLE; - - /** - * Line separator for encoding. Not used when decoding. Only used if lineLength - * > 0. - */ - private final byte[] lineSeparator; - - /** - * Convenience variable to help us determine when our buffer is going to run out - * of room and needs resizing. {@code decodeSize = 3 + lineSeparator.length;} - */ - private final int decodeSize; - - /** - * Convenience variable to help us determine when our buffer is going to run out - * of room and needs resizing. {@code encodeSize = 4 + lineSeparator.length;} - */ - private final int encodeSize; - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in - * URL-unsafe mode. - *

    - * When encoding the line length is 0 (no chunking), and the encoding table is - * STANDARD_ENCODE_TABLE. - *

    - * - *

    - * When decoding all variants are supported. - *

    - */ - public Base64() { - this(0); - } - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in the - * given URL-safe mode. - *

    - * When encoding the line length is 76, the line separator is CRLF, and the - * encoding table is STANDARD_ENCODE_TABLE. - *

    - * - *

    - * When decoding all variants are supported. - *

    - * - * @param urlSafe if {@code true}, URL-safe encoding is used. In most cases this - * should be set to {@code false}. - * @since 1.4 - */ - public Base64(final boolean urlSafe) { - this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe); - } - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in - * URL-unsafe mode. - *

    - * When encoding the line length is given in the constructor, the line separator - * is CRLF, and the encoding table is STANDARD_ENCODE_TABLE. - *

    - *

    - * Line lengths that aren't multiples of 4 will still essentially end up being - * multiples of 4 in the encoded data. - *

    - *

    - * When decoding all variants are supported. - *

    - * - * @param lineLength Each line of encoded data will be at most of the given - * length (rounded down to nearest multiple of 4). If - * lineLength <= 0, then the output will not be divided - * into lines (chunks). Ignored when decoding. - * @since 1.4 - */ - public Base64(final int lineLength) { - this(lineLength, CHUNK_SEPARATOR); - } - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in - * URL-unsafe mode. - *

    - * When encoding the line length and line separator are given in the - * constructor, and the encoding table is STANDARD_ENCODE_TABLE. - *

    - *

    - * Line lengths that aren't multiples of 4 will still essentially end up being - * multiples of 4 in the encoded data. - *

    - *

    - * When decoding all variants are supported. - *

    - * - * @param lineLength Each line of encoded data will be at most of the given - * length (rounded down to nearest multiple of 4). If - * lineLength <= 0, then the output will not be divided - * into lines (chunks). Ignored when decoding. - * @param lineSeparator Each line of encoded data will end with this sequence of - * bytes. - * @throws IllegalArgumentException Thrown when the provided lineSeparator - * included some base64 characters. - * @since 1.4 - */ - public Base64(final int lineLength, final byte[] lineSeparator) { - this(lineLength, lineSeparator, false); - } - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in - * URL-unsafe mode. - *

    - * When encoding the line length and line separator are given in the - * constructor, and the encoding table is STANDARD_ENCODE_TABLE. - *

    - *

    - * Line lengths that aren't multiples of 4 will still essentially end up being - * multiples of 4 in the encoded data. - *

    - *

    - * When decoding all variants are supported. - *

    - * - * @param lineLength Each line of encoded data will be at most of the given - * length (rounded down to nearest multiple of 4). If - * lineLength <= 0, then the output will not be divided - * into lines (chunks). Ignored when decoding. - * @param lineSeparator Each line of encoded data will end with this sequence of - * bytes. - * @param urlSafe Instead of emitting '+' and '/' we emit '-' and '_' - * respectively. urlSafe is only applied to encode - * operations. Decoding seamlessly handles both modes. - * Note: no padding is added when using the URL-safe - * alphabet. - * @throws IllegalArgumentException Thrown when the {@code lineSeparator} - * contains Base64 characters. - * @since 1.4 - */ - public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) { - this(lineLength, lineSeparator, urlSafe, CodecPolicy.LENIANT); - } - - /** - * Creates a Base64 codec used for decoding (all modes) and encoding in - * URL-unsafe mode. - *

    - * When encoding the line length and line separator are given in the - * constructor, and the encoding table is STANDARD_ENCODE_TABLE. - *

    - *

    - * Line lengths that aren't multiples of 4 will still essentially end up being - * multiples of 4 in the encoded data. - *

    - *

    - * When decoding all variants are supported. - *

    - * - * @param lineLength Each line of encoded data will be at most of the given - * length (rounded down to nearest multiple of 4). If - * lineLength <= 0, then the output will not be divided - * into lines (chunks). Ignored when decoding. - * @param lineSeparator Each line of encoded data will end with this sequence - * of bytes. - * @param urlSafe Instead of emitting '+' and '/' we emit '-' and '_' - * respectively. urlSafe is only applied to encode - * operations. Decoding seamlessly handles both modes. - * Note: no padding is added when using the URL-safe - * alphabet. - * @param decodingPolicy The decoding policy. - * @throws IllegalArgumentException Thrown when the {@code lineSeparator} - * contains Base64 characters. - * @since 1.15 - */ - public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe, - final CodecPolicy decodingPolicy) { - super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, - lineSeparator == null ? 0 : lineSeparator.length, PAD_DEFAULT, decodingPolicy); - // TODO could be simplified if there is no requirement to reject invalid line - // sep when length <=0 - // @see test case Base64Test.testConstructors() - if (lineSeparator != null) { - if (containsAlphabetOrPad(lineSeparator)) { - final String sep = new String(lineSeparator, Charset.forName("UTF-8")); - throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]"); - } - if (lineLength > 0) { // null line-sep forces no chunking rather than throwing IAE - this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length; - this.lineSeparator = new byte[lineSeparator.length]; - System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length); - } else { - this.encodeSize = BYTES_PER_ENCODED_BLOCK; - this.lineSeparator = null; - } - } else { - this.encodeSize = BYTES_PER_ENCODED_BLOCK; - this.lineSeparator = null; - } - this.decodeSize = this.encodeSize - 1; - this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE; - } - - // Implementation of the Encoder Interface - - /** - *

    - * Decodes all of the provided data, starting at inPos, for inAvail bytes. - * Should be called at least twice: once with the data to decode, and once with - * inAvail set to "-1" to alert decoder that EOF has been reached. The "-1" call - * is not necessary when decoding, but it doesn't hurt, either. - *

    - *

    - * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) - * data is handled, since CR and LF are silently ignored, but has implications - * for other bytes, too. This method subscribes to the garbage-in, garbage-out - * philosophy: it will not check the provided data for validity. - *

    - *

    - * Thanks to "commons" project in ws.apache.org for the bitwise operations, and - * general approach. - * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ - *

    - * - * @param in byte[] array of ascii data to base64 decode. - * @param inPos Position to start reading data from. - * @param inAvail Amount of bytes available from input for decoding. - * @param context the context to be used - */ - @Override - void decode(final byte[] in, int inPos, final int inAvail, final Context context) { - if (context.eof) { - return; - } - if (inAvail < 0) { - context.eof = true; - } - for (int i = 0; i < inAvail; i++) { - final byte[] buffer = ensureBufferSize(decodeSize, context); - final byte b = in[inPos++]; - if (b == pad) { - // We're done. - context.eof = true; - break; - } - if (b >= 0 && b < DECODE_TABLE.length) { - final int result = DECODE_TABLE[b]; - if (result >= 0) { - context.modulus = (context.modulus + 1) % BYTES_PER_ENCODED_BLOCK; - context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result; - if (context.modulus == 0) { - buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 16) & MASK_8BITS); - buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS); - buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS); - } - } - } - } - - // Two forms of EOF as far as base64 decoder is concerned: actual - // EOF (-1) and first time '=' character is encountered in stream. - // This approach makes the '=' padding characters completely optional. - if (context.eof && context.modulus != 0) { - final byte[] buffer = ensureBufferSize(decodeSize, context); - - // We have some spare bits remaining - // Output all whole multiples of 8 bits and ignore the rest - switch (context.modulus) { -// case 0 : // impossible, as excluded above - case 1: // 6 bits - either ignore entirely, or raise an exception - validateTrailingCharacter(); - break; - case 2: // 12 bits = 8 + 4 - validateCharacter(MASK_4BITS, context); - context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits - buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS); - break; - case 3: // 18 bits = 8 + 8 + 2 - validateCharacter(MASK_2BITS, context); - context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits - buffer[context.pos++] = (byte) ((context.ibitWorkArea >> 8) & MASK_8BITS); - buffer[context.pos++] = (byte) ((context.ibitWorkArea) & MASK_8BITS); - break; - default: - throw new IllegalStateException("Impossible modulus " + context.modulus); - } - } - } - - /** - *

    - * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must - * be called at least twice: once with the data to encode, and once with inAvail - * set to "-1" to alert encoder that EOF has been reached, to flush last - * remaining bytes (if not multiple of 3). - *

    - *

    - * Note: no padding is added when encoding using the URL-safe alphabet. - *

    - *

    - * Thanks to "commons" project in ws.apache.org for the bitwise operations, and - * general approach. - * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ - *

    - * - * @param in byte[] array of binary data to base64 encode. - * @param inPos Position to start reading data from. - * @param inAvail Amount of bytes available from input for encoding. - * @param context the context to be used - */ - @Override - void encode(final byte[] in, int inPos, final int inAvail, final Context context) { - if (context.eof) { - return; - } - // inAvail < 0 is how we're informed of EOF in the underlying data we're - // encoding. - if (inAvail < 0) { - context.eof = true; - if (0 == context.modulus && lineLength == 0) { - return; // no leftovers to process and not using chunking - } - final byte[] buffer = ensureBufferSize(encodeSize, context); - final int savedPos = context.pos; - switch (context.modulus) { // 0-2 - case 0: // nothing to do here - break; - case 1: // 8 bits = 6 + 2 - // top 6 bits: - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 2) & MASK_6BITS]; - // remaining 2: - buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 4) & MASK_6BITS]; - // URL-SAFE skips the padding to further reduce size. - if (encodeTable == STANDARD_ENCODE_TABLE) { - buffer[context.pos++] = pad; - buffer[context.pos++] = pad; - } - break; - - case 2: // 16 bits = 6 + 6 + 4 - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 10) & MASK_6BITS]; - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 4) & MASK_6BITS]; - buffer[context.pos++] = encodeTable[(context.ibitWorkArea << 2) & MASK_6BITS]; - // URL-SAFE skips the padding to further reduce size. - if (encodeTable == STANDARD_ENCODE_TABLE) { - buffer[context.pos++] = pad; - } - break; - default: - throw new IllegalStateException("Impossible modulus " + context.modulus); - } - context.currentLinePos += context.pos - savedPos; // keep track of current line position - // if currentPos == 0 we are at the start of a line, so don't add CRLF - if (lineLength > 0 && context.currentLinePos > 0) { - System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); - context.pos += lineSeparator.length; - } - } else { - for (int i = 0; i < inAvail; i++) { - final byte[] buffer = ensureBufferSize(encodeSize, context); - context.modulus = (context.modulus + 1) % BYTES_PER_UNENCODED_BLOCK; - int b = in[inPos++]; - if (b < 0) { - b += 256; - } - context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE - if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 18) & MASK_6BITS]; - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 12) & MASK_6BITS]; - buffer[context.pos++] = encodeTable[(context.ibitWorkArea >> 6) & MASK_6BITS]; - buffer[context.pos++] = encodeTable[context.ibitWorkArea & MASK_6BITS]; - context.currentLinePos += BYTES_PER_ENCODED_BLOCK; - if (lineLength > 0 && lineLength <= context.currentLinePos) { - System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length); - context.pos += lineSeparator.length; - context.currentLinePos = 0; - } - } - } - } - } - - /** - * Returns whether or not the {@code octet} is in the Base64 alphabet. - * - * @param octet The value to test - * @return {@code true} if the value is defined in the the Base64 alphabet - * {@code false} otherwise. - */ - @Override - protected boolean isInAlphabet(final byte octet) { - return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1; - } - - /** - * Returns our current encode mode. True if we're URL-SAFE, false otherwise. - * - * @return true if we're in URL-SAFE mode, false otherwise. - * @since 1.4 - */ - public boolean isUrlSafe() { - return this.encodeTable == URL_SAFE_ENCODE_TABLE; - } - - /** - * Validates whether decoding the final trailing character is possible in the - * context of the set of possible base 64 values. - * - *

    - * The character is valid if the lower bits within the provided mask are zero. - * This is used to test the final trailing base-64 digit is zero in the bits - * that will be discarded. - * - * @param emptyBitsMask The mask of the lower bits that should be empty - * @param context the context to be used - * - * @throws IllegalArgumentException if the bits being checked contain any - * non-zero value - */ - private void validateCharacter(final int emptyBitsMask, final Context context) { - if (isStrictDecoding() && (context.ibitWorkArea & emptyBitsMask) != 0) { - throw new IllegalArgumentException( - "Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " - + "Expected the discarded bits from the character to be zero."); - } - } - - /** - * Validates whether decoding allows an entire final trailing character that - * cannot be used for a complete byte. - * - * @throws IllegalArgumentException if strict decoding is enabled - */ - private void validateTrailingCharacter() { - if (isStrictDecoding()) { - throw new IllegalArgumentException( - "Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " - + "Decoding requires at least two trailing 6-bit characters to create bytes."); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BaseNCodec.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BaseNCodec.java deleted file mode 100644 index f7f1da7c..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BaseNCodec.java +++ /dev/null @@ -1,694 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.nio.charset.Charset; -import java.util.Arrays; - -public abstract class BaseNCodec { - - static enum CodecPolicy { - STRICT, LENIANT; - } - - /** - * Holds thread context so classes can be thread-safe. - * - * This class is not itself thread-safe; each thread must allocate its own copy. - * - * @since 1.7 - */ - static class Context { - - /** - * Place holder for the bytes we're dealing with for our based logic. Bitwise - * operations store and extract the encoding or decoding from this variable. - */ - int ibitWorkArea; - - /** - * Place holder for the bytes we're dealing with for our based logic. Bitwise - * operations store and extract the encoding or decoding from this variable. - */ - long lbitWorkArea; - - /** - * Buffer for streaming. - */ - byte[] buffer; - - /** - * Position where next character should be written in the buffer. - */ - int pos; - - /** - * Position where next character should be read from the buffer. - */ - int readPos; - - /** - * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, - * this object becomes useless, and must be thrown away. - */ - boolean eof; - - /** - * Variable tracks how many characters have been written to the current line. - * Only used when encoding. We use it to make sure each encoded line never goes - * beyond lineLength (if lineLength > 0). - */ - int currentLinePos; - - /** - * Writes to the buffer only occur after every 3/5 reads when encoding, and - * every 4/8 reads when decoding. This variable helps track that. - */ - int modulus; - - Context() { - } - - /** - * Returns a String useful for debugging (especially within a debugger.) - * - * @return a String useful for debugging. - */ - @SuppressWarnings("boxing") // OK to ignore boxing here - @Override - public String toString() { - return String.format( - "%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " - + "modulus=%s, pos=%s, readPos=%s]", - this.getClass().getSimpleName(), Arrays.toString(buffer), currentLinePos, eof, ibitWorkArea, - lbitWorkArea, modulus, pos, readPos); - } - } - - /** - * EOF - * - * @since 1.7 - */ - static final int EOF = -1; - - /** - * MIME chunk size per RFC 2045 section 6.8. - * - *

    - * The {@value} character limit does not count the trailing CRLF, but counts all - * other characters, including any equal signs. - *

    - * - * @see RFC 2045 section 6.8 - */ - public static final int MIME_CHUNK_SIZE = 76; - - /** - * PEM chunk size per RFC 1421 section 4.3.2.4. - * - *

    - * The {@value} character limit does not count the trailing CRLF, but counts all - * other characters, including any equal signs. - *

    - * - * @see RFC 1421 section - * 4.3.2.4 - */ - public static final int PEM_CHUNK_SIZE = 64; - - private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2; - - /** - * Defines the default buffer size - currently {@value} - must be large enough - * for at least one encoded block+separator - */ - private static final int DEFAULT_BUFFER_SIZE = 8192; - - /** - * The maximum size buffer to allocate. - * - *

    - * This is set to the same size used in the JDK {@code java.util.ArrayList}: - *

    - *
    Some VMs reserve some header words in an array. Attempts to - * allocate larger arrays may result in OutOfMemoryError: Requested array size - * exceeds VM limit.
    - */ - private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; - - /** Mask used to extract 8 bits, used in decoding bytes */ - protected static final int MASK_8BITS = 0xff; - - /** - * Byte used to pad output. - */ - protected static final byte PAD_DEFAULT = '='; // Allow static access to default - - /** - * Chunk separator per RFC 2045 section 2.1. - * - * @see RFC 2045 section 2.1 - */ - static final byte[] CHUNK_SEPARATOR = { '\r', '\n' }; - - /** - * Compares two {@code int} values numerically treating the values as unsigned. - * Taken from JDK 1.8. - * - *

    - * TODO: Replace with JDK 1.8 Integer::compareUnsigned(int, int). - *

    - * - * @param x the first {@code int} to compare - * @param y the second {@code int} to compare - * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if - * {@code x < y} as unsigned values; and a value greater than {@code 0} - * if {@code x > y} as unsigned values - */ - private static int compareUnsigned(final int xx, final int yy) { - int x = xx + Integer.MIN_VALUE; - int y = yy + Integer.MIN_VALUE; - return (x < y) ? -1 : ((x == y) ? 0 : 1); - } - - /** - * Create a positive capacity at least as large the minimum required capacity. - * If the minimum capacity is negative then this throws an OutOfMemoryError as - * no array can be allocated. - * - * @param minCapacity the minimum capacity - * @return the capacity - * @throws OutOfMemoryError if the {@code minCapacity} is negative - */ - private static int createPositiveCapacity(final int minCapacity) { - if (minCapacity < 0) { - // overflow - throw new OutOfMemoryError("Unable to allocate array size: " + (minCapacity & 0xffffffffL)); - } - // This is called when we require buffer expansion to a very big array. - // Use the conservative maximum buffer size if possible, otherwise the biggest - // required. - // - // Note: In this situation JDK 1.8 java.util.ArrayList returns - // Integer.MAX_VALUE. - // This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a - // full - // Integer.MAX_VALUE length array. - // The result is that we may have to allocate an array of this size more than - // once if - // the capacity must be expanded again. - return (minCapacity > MAX_BUFFER_SIZE) ? minCapacity : MAX_BUFFER_SIZE; - } - - /** - * Gets a copy of the chunk separator per RFC 2045 section 2.1. - * - * @return the chunk separator - * @see RFC 2045 section 2.1 - * @since 1.15 - */ - public static byte[] getChunkSeparator() { - return CHUNK_SEPARATOR.clone(); - } - - /** - * Checks if a byte value is whitespace or not. Whitespace is taken to mean: - * space, tab, CR, LF - * - * @param byteToCheck the byte to check - * @return true if byte is whitespace, false otherwise - */ - protected static boolean isWhiteSpace(final byte byteToCheck) { - switch (byteToCheck) { - case ' ': - case '\n': - case '\r': - case '\t': - return true; - default: - return false; - } - } - - /** - * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. - * - * @param context the context to be used - * @param minCapacity the minimum required capacity - * @return the resized byte[] buffer - * @throws OutOfMemoryError if the {@code minCapacity} is negative - */ - private static byte[] resizeBuffer(final Context context, final int minCapacity) { - // Overflow-conscious code treats the min and new capacity as unsigned. - final int oldCapacity = context.buffer.length; - int newCapacity = oldCapacity * DEFAULT_BUFFER_RESIZE_FACTOR; - if (compareUnsigned(newCapacity, minCapacity) < 0) { - newCapacity = minCapacity; - } - if (compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) { - newCapacity = createPositiveCapacity(minCapacity); - } - - final byte[] b = new byte[newCapacity]; - System.arraycopy(context.buffer, 0, b, 0, context.buffer.length); - context.buffer = b; - return b; - } - - /** - * @deprecated Use {@link #pad}. Will be removed in 2.0. - */ - @Deprecated - protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later - - protected final byte pad; // instance variable just in case it needs to vary later - - /** - * Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 - * for Base32 - */ - private final int unencodedBlockSize; - - /** - * Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 - * for Base32 - */ - private final int encodedBlockSize; - - /** - * Chunksize for encoding. Not used when decoding. A value of zero or less - * implies no chunking of the encoded data. Rounded down to nearest multiple of - * encodedBlockSize. - */ - protected final int lineLength; - - /** - * Size of chunk separator. Not used unless {@link #lineLength} > 0. - */ - private final int chunkSeparatorLength; - - /** - * Defines the decoding behavior when the input bytes contain leftover trailing - * bits that cannot be created by a valid encoding. These can be bits that are - * unused from the final character or entire characters. The default mode is - * lenient decoding. Set this to {@code true} to enable strict decoding. - *
      - *
    • Lenient: Any trailing bits are composed into 8-bit bytes where possible. - * The remainder are discarded. - *
    • Strict: The decoding will raise an {@link IllegalArgumentException} if - * trailing bits are not part of a valid encoding. Any unused bits from the - * final character must be zero. Impossible counts of entire final characters - * are not allowed. - *
    - * - *

    - * When strict decoding is enabled it is expected that the decoded bytes will be - * re-encoded to a byte array that matches the original, i.e. no changes occur - * on the final character. This requires that the input bytes use the same - * padding and alphabet as the encoder. - */ - private final CodecPolicy decodingPolicy; - - /** - * Note {@code lineLength} is rounded down to the nearest multiple of the - * encoded block size. If {@code chunkSeparatorLength} is zero, then chunking is - * disabled. - * - * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) - * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) - * @param lineLength if > 0, use chunking with a length - * {@code lineLength} - * @param chunkSeparatorLength the chunk separator length, if relevant - */ - protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, - final int chunkSeparatorLength) { - this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT); - } - - /** - * Note {@code lineLength} is rounded down to the nearest multiple of the - * encoded block size. If {@code chunkSeparatorLength} is zero, then chunking is - * disabled. - * - * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) - * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) - * @param lineLength if > 0, use chunking with a length - * {@code lineLength} - * @param chunkSeparatorLength the chunk separator length, if relevant - * @param pad byte used as padding byte. - */ - protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, - final int chunkSeparatorLength, final byte pad) { - this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, pad, CodecPolicy.LENIANT); - } - - /** - * Note {@code lineLength} is rounded down to the nearest multiple of the - * encoded block size. If {@code chunkSeparatorLength} is zero, then chunking is - * disabled. - * - * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) - * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) - * @param lineLength if > 0, use chunking with a length - * {@code lineLength} - * @param chunkSeparatorLength the chunk separator length, if relevant - * @param pad byte used as padding byte. - * @param decodingPolicy Decoding policy. - * @since 1.15 - */ - protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, - final int chunkSeparatorLength, final byte pad, final CodecPolicy decodingPolicy) { - this.unencodedBlockSize = unencodedBlockSize; - this.encodedBlockSize = encodedBlockSize; - final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0; - this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0; - this.chunkSeparatorLength = chunkSeparatorLength; - this.pad = pad; - this.decodingPolicy = decodingPolicy; - } - - /** - * Returns the amount of buffered data available for reading. - * - * @param context the context to be used - * @return The amount of buffered data available for reading. - */ - int available(final Context context) { // package protected for access from I/O streams - return context.buffer != null ? context.pos - context.readPos : 0; - } - - /** - * Tests a given byte array to see if it contains any characters within the - * alphabet or PAD. - * - * Intended for use in checking line-ending arrays - * - * @param arrayOctet byte array to test - * @return {@code true} if any byte is a valid character in the alphabet or PAD; - * {@code false} otherwise - */ - protected boolean containsAlphabetOrPad(final byte[] arrayOctet) { - if (arrayOctet == null) { - return false; - } - for (int i = 0; i < arrayOctet.length; ++i) { - byte element = arrayOctet[i]; - if (pad == element || isInAlphabet(element)) { - return true; - } - } - return false; - } - - /** - * Decodes a byte[] containing characters in the Base-N alphabet. - * - * @param pArray A byte array containing Base-N character data - * @return a byte array containing binary data - */ - public byte[] decode(final byte[] pArray) { - if (pArray == null || pArray.length == 0) { - return pArray; - } - final Context context = new Context(); - decode(pArray, 0, pArray.length, context); - decode(pArray, 0, EOF, context); // Notify decoder of EOF. - final byte[] result = new byte[context.pos]; - readResults(result, 0, result.length, context); - return result; - } - - // package protected for access from I/O streams - abstract void decode(byte[] pArray, int i, int length, Context context); - - /** - * Decodes an Object using the Base-N algorithm. This method is provided in - * order to satisfy the requirements of the Decoder interface, and will throw a - * DecoderException if the supplied object is not of type byte[] or String. - * - * @param obj Object to decode - * @return An object (of type byte[]) containing the binary data which - * corresponds to the byte[] or String supplied. - * @throws DecoderException if the parameter supplied is not of type byte[] - */ - public Object decode(final Object obj) { - if (obj instanceof byte[]) { - return decode((byte[]) obj); - } else if (obj instanceof String) { - return decode((String) obj); - } else { - return null; - } - } - - /** - * Decodes a String containing characters in the Base-N alphabet. - * - * @param pArray A String containing Base-N character data - * @return a byte array containing binary data - */ - public byte[] decode(final String pArray) { - return decode(pArray.getBytes(Charset.forName("UTF-8"))); - } - - /** - * Encodes a byte[] containing binary data, into a byte[] containing characters - * in the alphabet. - * - * @param pArray a byte array containing binary data - * @return A byte array containing only the base N alphabetic character data - */ - public byte[] encode(final byte[] pArray) { - if (pArray == null || pArray.length == 0) { - return pArray; - } - return encode(pArray, 0, pArray.length); - } - - /** - * Encodes a byte[] containing binary data, into a byte[] containing characters - * in the alphabet. - * - * @param pArray a byte array containing binary data - * @param offset initial offset of the subarray. - * @param length length of the subarray. - * @return A byte array containing only the base N alphabetic character data - * @since 1.11 - */ - public byte[] encode(final byte[] pArray, final int offset, final int length) { - if (pArray == null || pArray.length == 0) { - return pArray; - } - final Context context = new Context(); - encode(pArray, offset, length, context); - encode(pArray, offset, EOF, context); // Notify encoder of EOF. - final byte[] buf = new byte[context.pos - context.readPos]; - readResults(buf, 0, buf.length, context); - return buf; - } - - // package protected for access from I/O streams - abstract void encode(byte[] pArray, int i, int length, Context context); - - /** - * Encodes an Object using the Base-N algorithm. This method is provided in - * order to satisfy the requirements of the Encoder interface, and will throw an - * EncoderException if the supplied object is not of type byte[]. - * - * @param obj Object to encode - * @return An object (of type byte[]) containing the Base-N encoded data which - * corresponds to the byte[] supplied. - * @throws EncoderException if the parameter supplied is not of type byte[] - */ - public Object encode(final Object obj) { - return encode((byte[]) obj); - } - - /** - * Encodes a byte[] containing binary data, into a String containing characters - * in the appropriate alphabet. Uses UTF8 encoding. - * - * @param pArray a byte array containing binary data - * @return String containing only character data in the appropriate alphabet. - * @since 1.5 This is a duplicate of {@link #encodeToString(byte[])}; it was - * merged during refactoring. - */ - public String encodeAsString(final byte[] pArray) { - return new String(encode(pArray), Charset.forName("UTF-8")); - } - - /** - * Encodes a byte[] containing binary data, into a String containing characters - * in the Base-N alphabet. Uses UTF8 encoding. - * - * @param pArray a byte array containing binary data - * @return A String containing only Base-N character data - */ - public String encodeToString(final byte[] pArray) { - return new String(encode(pArray), Charset.forName("UTF-8")); - } - - /** - * Ensure that the buffer has room for {@code size} bytes - * - * @param size minimum spare space required - * @param context the context to be used - * @return the buffer - */ - protected byte[] ensureBufferSize(final int size, final Context context) { - if (context.buffer == null) { - context.buffer = new byte[Math.max(size, getDefaultBufferSize())]; - context.pos = 0; - context.readPos = 0; - - // Overflow-conscious: - // x + y > z == x + y - z > 0 - } else if (context.pos + size - context.buffer.length > 0) { - return resizeBuffer(context, context.pos + size); - } - return context.buffer; - } - - /** - * Returns the decoding behavior policy. - * - *

    - * The default is lenient. If the decoding policy is strict, then decoding will - * raise an {@link IllegalArgumentException} if trailing bits are not part of a - * valid encoding. Decoding will compose trailing bits into 8-bit bytes and - * discard the remainder. - *

    - * - * @return true if using strict decoding - * @since 1.15 - */ - public CodecPolicy getCodecPolicy() { - return decodingPolicy; - } - - /** - * Get the default buffer size. Can be overridden. - * - * @return the default buffer size. - */ - protected int getDefaultBufferSize() { - return DEFAULT_BUFFER_SIZE; - } - - /** - * Calculates the amount of space needed to encode the supplied array. - * - * @param pArray byte[] array which will later be encoded - * - * @return amount of space needed to encoded the supplied array. Returns a long - * since a max-len array will require > Integer.MAX_VALUE - */ - public long getEncodedLength(final byte[] pArray) { - // Calculate non-chunked size - rounded up to allow for padding - // cast to long is needed to avoid possibility of overflow - long len = ((pArray.length + unencodedBlockSize - 1) / unencodedBlockSize) * (long) encodedBlockSize; - if (lineLength > 0) { // We're using chunking - // Round up to nearest multiple - len += ((len + lineLength - 1) / lineLength) * chunkSeparatorLength; - } - return len; - } - - /** - * Returns true if this object has buffered data for reading. - * - * @param context the context to be used - * @return true if there is data still available for reading. - */ - boolean hasData(final Context context) { // package protected for access from I/O streams - return context.buffer != null; - } - - /** - * Returns whether or not the {@code octet} is in the current alphabet. Does not - * allow whitespace or pad. - * - * @param value The value to test - * - * @return {@code true} if the value is defined in the current alphabet, - * {@code false} otherwise. - */ - protected abstract boolean isInAlphabet(byte value); - - /** - * Tests a given byte array to see if it contains only valid characters within - * the alphabet. The method optionally treats whitespace and pad as valid. - * - * @param arrayOctet byte array to test - * @param allowWSPad if {@code true}, then whitespace and PAD are also allowed - * - * @return {@code true} if all bytes are valid characters in the alphabet or if - * the byte array is empty; {@code false}, otherwise - */ - public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) { - for (int i = 0; i < arrayOctet.length; ++i) { - byte octet = arrayOctet[i]; - if (!isInAlphabet(octet) && (!allowWSPad || (octet != pad) && !isWhiteSpace(octet))) { - return false; - } - } - return true; - } - - /** - * Tests a given String to see if it contains only valid characters within the - * alphabet. The method treats whitespace and PAD as valid. - * - * @param basen String to test - * @return {@code true} if all characters in the String are valid characters in - * the alphabet or if the String is empty; {@code false}, otherwise - * @see #isInAlphabet(byte[], boolean) - */ - public boolean isInAlphabet(final String basen) { - return isInAlphabet(basen.getBytes(Charset.forName("UTF-8")), true); - } - - /** - * Returns true if decoding behavior is strict. Decoding will raise an - * {@link IllegalArgumentException} if trailing bits are not part of a valid - * encoding. - * - *

    - * The default is false for lenient decoding. Decoding will compose trailing - * bits into 8-bit bytes and discard the remainder. - *

    - * - * @return true if using strict decoding - * @since 1.15 - */ - public boolean isStrictDecoding() { - return decodingPolicy == CodecPolicy.STRICT; - } - - /** - * Extracts buffered data into the provided byte[] array, starting at position - * bPos, up to a maximum of bAvail bytes. Returns how many bytes were actually - * extracted. - *

    - * Package protected for access from I/O streams. - * - * @param b byte[] array to extract the buffered data into. - * @param bPos position in byte[] array to start extraction at. - * @param bAvail amount of bytes we're allowed to extract. We may extract fewer - * (if fewer are available). - * @param context the context to be used - * @return The number of bytes successfully extracted into the provided byte[] - * array. - */ - int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) { - if (context.buffer != null) { - final int len = Math.min(available(context), bAvail); - System.arraycopy(context.buffer, context.readPos, b, bPos, len); - context.readPos += len; - if (context.readPos >= context.pos) { - context.buffer = null; // so hasData() will return false, and this method can return -1 - } - return len; - } - return context.eof ? EOF : 0; - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BinaryHttpClient.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BinaryHttpClient.java deleted file mode 100644 index 369ff65c..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/BinaryHttpClient.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.URI; -import java.net.UnknownHostException; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import javax.net.ssl.SSLEngine; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.velocitypowered.proxy.network.TransportType.Type; - -import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultHttpRequest; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpContent; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpMethod; -import io.netty.handler.codec.http.HttpObject; -import io.netty.handler.codec.http.HttpRequest; -import io.netty.handler.codec.http.HttpResponse; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpVersion; -import io.netty.handler.codec.http.LastHttpContent; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.SslHandler; -import io.netty.handler.timeout.ReadTimeoutHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocityVersion; - -public class BinaryHttpClient { - - public static class Response { - - public final int code; - public final byte[] data; - public final Throwable exception; - - public Response(int code, byte[] data) { - this.code = code; - this.data = data; - this.exception = null; - } - - public Response(Throwable exception) { - this.code = -1; - this.data = null; - this.exception = exception; - } - - } - - private static class NettyHttpChannelFutureListener implements ChannelFutureListener { - - protected final String method; - protected final URI requestURI; - protected final Consumer responseCallback; - - protected NettyHttpChannelFutureListener(String method, URI requestURI, Consumer responseCallback) { - this.method = method; - this.requestURI = requestURI; - this.responseCallback = responseCallback; - } - - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (future.isSuccess()) { - String path = requestURI.getRawPath() - + ((requestURI.getRawQuery() == null) ? "" : ("?" + requestURI.getRawQuery())); - HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, - HttpMethod.valueOf(method), path); - request.headers().set(HttpHeaderNames.HOST, (Object) requestURI.getHost()); - request.headers().set(HttpHeaderNames.USER_AGENT, "Mozilla/5.0 " + EaglerXVelocityVersion.ID + "/" + EaglerXVelocityVersion.VERSION); - future.channel().writeAndFlush(request); - } else { - addressCache.invalidate(requestURI.getHost()); - responseCallback.accept(new Response(new IOException("Connection failed"))); - } - } - - } - - private static class NettyHttpChannelInitializer extends ChannelInitializer { - - protected final Consumer responseCallback; - protected final boolean ssl; - protected final String host; - protected final int port; - - protected NettyHttpChannelInitializer(Consumer responseCallback, boolean ssl, String host, int port) { - this.responseCallback = responseCallback; - this.ssl = ssl; - this.host = host; - this.port = port; - } - - @Override - protected void initChannel(Channel ch) throws Exception { - ch.pipeline().addLast("timeout", new ReadTimeoutHandler(5L, TimeUnit.SECONDS)); - if (this.ssl) { - SSLEngine engine = SslContextBuilder.forClient().build().newEngine(ch.alloc(), host, port); - ch.pipeline().addLast("ssl", new SslHandler(engine)); - } - - ch.pipeline().addLast("http", new HttpClientCodec()); - ch.pipeline().addLast("handler", new NettyHttpResponseHandler(responseCallback)); - } - - } - - private static class NettyHttpResponseHandler extends SimpleChannelInboundHandler { - - protected final Consumer responseCallback; - protected int responseCode = -1; - protected ByteBuf buffer = null; - - protected NettyHttpResponseHandler(Consumer responseCallback) { - this.responseCallback = responseCallback; - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { - if (msg instanceof HttpResponse) { - HttpResponse response = (HttpResponse) msg; - responseCode = response.status().code(); - if (responseCode == HttpResponseStatus.NO_CONTENT.code()) { - this.done(ctx); - return; - } - } - if (msg instanceof HttpContent) { - HttpContent content = (HttpContent) msg; - if(buffer == null) { - buffer = ctx.alloc().buffer(); - } - this.buffer.writeBytes(content.content()); - if (msg instanceof LastHttpContent) { - this.done(ctx); - } - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - responseCallback.accept(new Response(cause)); - } - - private void done(ChannelHandlerContext ctx) { - try { - byte[] array; - if(buffer != null) { - array = new byte[buffer.readableBytes()]; - buffer.readBytes(array); - buffer.release(); - }else { - array = new byte[0]; - } - responseCallback.accept(new Response(responseCode, array)); - }finally { - ctx.channel().pipeline().remove(this); - ctx.channel().close(); - } - } - - } - - private static final Cache addressCache = CacheBuilder.newBuilder().expireAfterWrite(15L, TimeUnit.MINUTES).build(); - private static EventLoopGroup eventLoop = null; - - public static void asyncRequest(String method, URI uri, Consumer responseCallback) { - EventLoopGroup eventLoop = getEventLoopGroup(); - - int port = uri.getPort(); - boolean ssl = false; - String scheme = uri.getScheme(); - switch(scheme) { - case "http": - if(port == -1) { - port = 80; - } - break; - case "https": - if(port == -1) { - port = 443; - } - ssl = true; - break; - default: - responseCallback.accept(new Response(new UnsupportedOperationException("Unsupported scheme: " + scheme))); - return; - } - - String host = uri.getHost(); - InetAddress inetHost = addressCache.getIfPresent(host); - if (inetHost == null) { - try { - inetHost = InetAddress.getByName(host); - } catch (UnknownHostException ex) { - responseCallback.accept(new Response(ex)); - return; - } - addressCache.put(host, inetHost); - } - - (new Bootstrap()).channelFactory(EaglerXVelocity.getEagler().getChannelFactory()).group(eventLoop) - .handler(new NettyHttpChannelInitializer(responseCallback, ssl, host, port)) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000).option(ChannelOption.TCP_NODELAY, true) - .remoteAddress(inetHost, port).connect() - .addListener(new NettyHttpChannelFutureListener(method, uri, responseCallback)); - } - - private static EventLoopGroup getEventLoopGroup() { - if(eventLoop == null) { - eventLoop = EaglerXVelocity.getEagler().getTransportType().createEventLoopGroup(Type.WORKER); - } - return eventLoop; - } - - public static void killEventLoop() { - if(eventLoop != null) { - EaglerXVelocity.logger().info("Stopping skin cache HTTP client..."); - eventLoop.shutdownGracefully(); - try { - eventLoop.awaitTermination(30l, TimeUnit.SECONDS); - } catch (InterruptedException var13) { - ; - } - eventLoop = null; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapePackets.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapePackets.java deleted file mode 100644 index 72d39d3e..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapePackets.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; - -public class CapePackets { - - public static final int PACKET_MY_CAPE_PRESET = 0x01; - public static final int PACKET_MY_CAPE_CUSTOM = 0x02; - - public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, CapeServiceOffline capeService) throws IOException { - if(bs.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - GameMessagePacket generatedPacket; - int packetType = (int)bs[0] & 0xFF; - switch(packetType) { - case PACKET_MY_CAPE_PRESET: - if(bs.length != 5) { - throw new IOException("Invalid length " + bs.length + " for preset cape packet"); - } - generatedPacket = new SPacketOtherCapePresetEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); - break; - case PACKET_MY_CAPE_CUSTOM: - if(bs.length != 1174) { - throw new IOException("Invalid length " + bs.length + " for custom cape packet"); - } - byte[] capePixels = new byte[bs.length - 1]; - System.arraycopy(bs, 1, capePixels, 0, capePixels.length); - generatedPacket = new SPacketOtherCapeCustomEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), capePixels); - break; - default: - throw new IOException("Unknown skin packet type: " + packetType); - } - capeService.registerEaglercraftPlayer(clientUUID, generatedPacket); - } - - public static void registerEaglerPlayerFallback(UUID clientUUID, CapeServiceOffline capeService) { - capeService.registerEaglercraftPlayer(clientUUID, new SPacketOtherCapePresetEAG( - clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), 0)); - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapeServiceOffline.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapeServiceOffline.java deleted file mode 100644 index 1d9aab55..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/CapeServiceOffline.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2024-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientCapeCustomV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientCapePresetV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapeCustomEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG; - -public class CapeServiceOffline { - - public static final int masterRateLimitPerPlayer = 250; - - private final ConcurrentMap capesCache = new ConcurrentHashMap<>(); - - public void registerEaglercraftPlayer(UUID playerUUID, GameMessagePacket capePacket) { - capesCache.put(playerUUID, capePacket); - } - - public void processGetOtherCape(UUID searchUUID, EaglerPlayerData sender) { - if(sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - GameMessagePacket maybeCape = capesCache.get(searchUUID); - if(maybeCape != null) { - sender.sendEaglerMessage(maybeCape); - }else { - sender.sendEaglerMessage(new SPacketOtherCapePresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - } - } - } - - public void processForceCape(UUID clientUUID, EaglerPlayerData initialHandler) { - GameMessagePacket maybeCape = capesCache.get(clientUUID); - if(maybeCape != null) { - if (maybeCape instanceof SPacketOtherCapePresetEAG) { - initialHandler.sendEaglerMessage( - new SPacketForceClientCapePresetV4EAG(((SPacketOtherCapePresetEAG) maybeCape).presetCape)); - } else if (maybeCape instanceof SPacketOtherCapeCustomEAG) { - initialHandler.sendEaglerMessage( - new SPacketForceClientCapeCustomV4EAG(((SPacketOtherCapeCustomEAG) maybeCape).customCape)); - } - } - } - - public void unregisterPlayer(UUID playerUUID) { - capesCache.remove(playerUUID); - } - - public GameMessagePacket getCape(UUID clientUUID) { - return capesCache.get(clientUUID); - } - - public byte[] getCapeHandshakeData(UUID clientUUID) { - GameMessagePacket capePacket = getCape(clientUUID); - if(capePacket != null) { - if(capePacket instanceof SPacketOtherCapeCustomEAG) { - SPacketOtherCapeCustomEAG pkt = (SPacketOtherCapeCustomEAG)capePacket; - byte[] ret = new byte[1174]; - ret[0] = (byte)2; - System.arraycopy(pkt.customCape, 0, ret, 1, 1173); - return ret; - }else { - SPacketOtherCapePresetEAG pkt = (SPacketOtherCapePresetEAG)capePacket; - int p = pkt.presetCape; - byte[] ret = new byte[5]; - ret[0] = (byte)1; - ret[1] = (byte)(p >>> 24); - ret[2] = (byte)(p >>> 16); - ret[3] = (byte)(p >>> 8); - ret[4] = (byte)(p & 0xFF); - return ret; - } - }else { - return null; - } - } - - public void shutdown() { - capesCache.clear(); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ICacheProvider.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ICacheProvider.java deleted file mode 100644 index 1f73d817..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ICacheProvider.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.util.UUID; - -public interface ICacheProvider { - - public static class CacheException extends RuntimeException { - - public CacheException() { - super(); - } - - public CacheException(String message, Throwable cause) { - super(message, cause); - } - - public CacheException(String message) { - super(message); - } - - public CacheException(Throwable cause) { - super(cause); - } - - } - - public static class CacheLoadedSkin { - - public final UUID uuid; - public final String url; - public final byte[] texture; - - public CacheLoadedSkin(UUID uuid, String url, byte[] texture) { - this.uuid = uuid; - this.url = url; - this.texture = texture; - } - - } - - public static class CacheLoadedProfile { - - public final UUID uuid; - public final String username; - public final String texture; - public final String model; - - public CacheLoadedProfile(UUID uuid, String username, String texture, String model) { - this.uuid = uuid; - this.username = username; - this.texture = texture; - this.model = model; - } - - public UUID getSkinUUID() { - return SkinPackets.createEaglerURLSkinUUID(texture); - } - - } - - CacheLoadedSkin loadSkinByUUID(UUID uuid) throws CacheException; - - void cacheSkinByUUID(UUID uuid, String url, byte[] textureBlob) throws CacheException; - - CacheLoadedProfile loadProfileByUUID(UUID uuid) throws CacheException; - - CacheLoadedProfile loadProfileByUsername(String username) throws CacheException; - - void cacheProfileByUUID(UUID uuid, String username, String texture, String model) throws CacheException; - - void flush() throws CacheException; - - void destroy(); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ISkinService.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ISkinService.java deleted file mode 100644 index fa833a2b..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/ISkinService.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public interface ISkinService { - - void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles); - - void processGetOtherSkin(final UUID searchUUID, final EaglerPlayerData sender); - - void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender); - - void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId); - - void unregisterPlayer(UUID clientUUID); - - default void registerTextureToPlayerAssociation(String textureURL, UUID playerUUID) { - registerTextureToPlayerAssociation(SkinPackets.createEaglerURLSkinUUID(textureURL), playerUUID); - } - - void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID); - - void flush(); - - void shutdown(); - - void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler); - - SkinPacketVersionCache getSkin(UUID playerUUID); - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/JDBCCacheProvider.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/JDBCCacheProvider.java deleted file mode 100644 index 46a4e3de..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/JDBCCacheProvider.java +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; -import java.util.UUID; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.sqlite.EaglerDrivers; - -public class JDBCCacheProvider implements ICacheProvider { - - public static JDBCCacheProvider initialize(String uri, String driverClass, String driverPath, int keepObjectsDays, - int keepProfilesDays, int maxObjects, int maxProfiles) throws CacheException { - Connection conn; - try { - conn = EaglerDrivers.connectToDatabase(uri, driverClass, driverPath, new Properties()); - if(conn == null) { - throw new IllegalStateException("Connection is null"); - } - }catch(Throwable t) { - throw new CacheException("Could not initialize '" + uri + "'!", t); - } - EaglerXVelocity.logger().info("Connected to database: " + uri); - try { - try(Statement stmt = conn.createStatement()) { - stmt.execute("CREATE TABLE IF NOT EXISTS " - + "\"eaglercraft_skins_objects\" (" - + "\"TextureUUID\" TEXT(32) NOT NULL," - + "\"TextureURL\" VARCHAR(256) NOT NULL," - + "\"TextureTime\" DATETIME NOT NULL," - + "\"TextureData\" BLOB," - + "\"TextureLength\" INT(24) NOT NULL," - + "PRIMARY KEY(\"TextureUUID\"))"); - stmt.execute("CREATE TABLE IF NOT EXISTS " - + "\"eaglercraft_skins_profiles\" (" - + "\"ProfileUUID\" TEXT(32) NOT NULL," - + "\"ProfileName\" TEXT(16) NOT NULL," - + "\"ProfileTime\" DATETIME NOT NULL," - + "\"ProfileTexture\" VARCHAR(256)," - + "\"ProfileModel\" VARCHAR(16) NOT NULL," - + "PRIMARY KEY(\"ProfileUUID\"))"); - stmt.execute("CREATE INDEX IF NOT EXISTS \"profile_name_index\" " - + "ON \"eaglercraft_skins_profiles\" (\"ProfileName\")"); - } - JDBCCacheProvider cacheProvider = new JDBCCacheProvider(conn, uri, keepObjectsDays, keepProfilesDays, maxObjects, maxProfiles); - cacheProvider.flush(); - return cacheProvider; - }catch(CacheException ex) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw ex; - }catch(Throwable t) { - try { - conn.close(); - }catch(SQLException exx) { - } - throw new CacheException("Could not initialize '" + uri + "'!", t); - } - } - - protected final Connection connection; - protected final String uri; - - protected final PreparedStatement discardExpiredObjects; - protected final PreparedStatement discardExpiredProfiles; - protected final PreparedStatement getTotalObjects; - protected final PreparedStatement getTotalProfiles; - protected final PreparedStatement deleteSomeOldestObjects; - protected final PreparedStatement deleteSomeOldestProfiles; - protected final PreparedStatement querySkinByUUID; - protected final PreparedStatement queryProfileByUUID; - protected final PreparedStatement queryProfileByUsername; - protected final PreparedStatement cacheNewSkin; - protected final PreparedStatement cacheNewProfile; - protected final PreparedStatement cacheHasSkin; - protected final PreparedStatement cacheHasProfile; - protected final PreparedStatement cacheUpdateSkin; - protected final PreparedStatement cacheUpdateProfile; - - protected long lastFlush; - - protected int keepObjectsDays; - protected int keepProfilesDays; - protected int maxObjects; - protected int maxProfiles; - - protected JDBCCacheProvider(Connection conn, String uri, int keepObjectsDays, int keepProfilesDays, int maxObjects, - int maxProfiles) throws SQLException { - this.connection = conn; - this.uri = uri; - this.lastFlush = 0l; - this.keepObjectsDays = keepObjectsDays; - this.keepProfilesDays = keepProfilesDays; - this.maxObjects = maxObjects; - this.maxProfiles = maxProfiles; - - this.discardExpiredObjects = connection.prepareStatement("DELETE FROM eaglercraft_skins_objects WHERE textureTime < ?"); - this.discardExpiredProfiles = connection.prepareStatement("DELETE FROM eaglercraft_skins_profiles WHERE profileTime < ?"); - this.getTotalObjects = connection.prepareStatement("SELECT COUNT(*) AS total_objects FROM eaglercraft_skins_objects"); - this.getTotalProfiles = connection.prepareStatement("SELECT COUNT(*) AS total_profiles FROM eaglercraft_skins_profiles"); - this.deleteSomeOldestObjects = connection.prepareStatement("DELETE FROM eaglercraft_skins_objects WHERE TextureUUID IN (SELECT TextureUUID FROM eaglercraft_skins_objects ORDER BY TextureTime ASC LIMIT ?)"); - this.deleteSomeOldestProfiles = connection.prepareStatement("DELETE FROM eaglercraft_skins_profiles WHERE ProfileUUID IN (SELECT ProfileUUID FROM eaglercraft_skins_profiles ORDER BY ProfileTime ASC LIMIT ?)"); - this.querySkinByUUID = connection.prepareStatement("SELECT TextureURL,TextureData,TextureLength FROM eaglercraft_skins_objects WHERE TextureUUID = ? LIMIT 1"); - this.queryProfileByUUID = connection.prepareStatement("SELECT ProfileName,ProfileTexture,ProfileModel FROM eaglercraft_skins_profiles WHERE ProfileUUID = ? LIMIT 1"); - this.queryProfileByUsername = connection.prepareStatement("SELECT ProfileUUID,ProfileTexture,ProfileModel FROM eaglercraft_skins_profiles WHERE ProfileName = ? LIMIT 1"); - this.cacheNewSkin = connection.prepareStatement("INSERT INTO eaglercraft_skins_objects (TextureUUID, TextureURL, TextureTime, TextureData, TextureLength) VALUES(?, ?, ?, ?, ?)"); - this.cacheNewProfile = connection.prepareStatement("INSERT INTO eaglercraft_skins_profiles (ProfileUUID, ProfileName, ProfileTime, ProfileTexture, ProfileModel) VALUES(?, ?, ?, ?, ?)"); - this.cacheHasSkin = connection.prepareStatement("SELECT COUNT(TextureUUID) AS has_object FROM eaglercraft_skins_objects WHERE TextureUUID = ? LIMIT 1"); - this.cacheHasProfile = connection.prepareStatement("SELECT COUNT(ProfileUUID) AS has_profile FROM eaglercraft_skins_profiles WHERE ProfileUUID = ? LIMIT 1"); - this.cacheUpdateSkin = connection.prepareStatement("UPDATE eaglercraft_skins_objects SET TextureURL = ?, TextureTime = ?, TextureData = ?, TextureLength = ? WHERE TextureUUID = ?"); - this.cacheUpdateProfile = connection.prepareStatement("UPDATE eaglercraft_skins_profiles SET ProfileName = ?, ProfileTime = ?, ProfileTexture = ?, ProfileModel = ? WHERE ProfileUUID = ?"); - } - - public CacheLoadedSkin loadSkinByUUID(UUID uuid) throws CacheException { - String uuidString = SkinService.getMojangUUID(uuid); - String queriedUrls; - byte[] queriedTexture; - int queriedLength; - try { - synchronized(querySkinByUUID) { - querySkinByUUID.setString(1, uuidString); - try(ResultSet resultSet = querySkinByUUID.executeQuery()) { - if(resultSet.next()) { - queriedUrls = resultSet.getString(1); - queriedTexture = resultSet.getBytes(2); - queriedLength = resultSet.getInt(3); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading cached skin", ex); - } - if(queriedLength == 0) { - return new CacheLoadedSkin(uuid, queriedUrls, new byte[0]); - }else { - byte[] decompressed = new byte[queriedLength]; - try { - GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream(queriedTexture)); - int i = 0, j = 0; - while(j < queriedLength && (i = is.read(decompressed, j, queriedLength - j)) != -1) { - j += i; - } - }catch(IOException ex) { - throw new CacheException("SQL query failure while loading cached skin"); - } - return new CacheLoadedSkin(uuid, queriedUrls, decompressed); - } - } - - public void cacheSkinByUUID(UUID uuid, String url, byte[] textureBlob) throws CacheException { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - try { - GZIPOutputStream deflateOut = new GZIPOutputStream(bao); - deflateOut.write(textureBlob); - deflateOut.close(); - }catch(IOException ex) { - throw new CacheException("Skin compression error", ex); - } - int len; - byte[] textureBlobCompressed; - if(textureBlob == null || textureBlob.length == 0) { - len = 0; - textureBlobCompressed = null; - }else { - len = textureBlob.length; - textureBlobCompressed = bao.toByteArray(); - } - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(cacheNewSkin) { - boolean has; - cacheHasSkin.setString(1, uuidString); - try(ResultSet resultSet = cacheHasSkin.executeQuery()) { - if(resultSet.next()) { - has = resultSet.getInt(1) > 0; - }else { - has = false; // ?? - } - } - if(has) { - cacheUpdateSkin.setString(1, url); - cacheUpdateSkin.setDate(2, new Date(System.currentTimeMillis())); - cacheUpdateSkin.setBytes(3, textureBlobCompressed); - cacheUpdateSkin.setInt(4, len); - cacheUpdateSkin.setString(5, uuidString); - cacheUpdateSkin.executeUpdate(); - }else { - cacheNewSkin.setString(1, uuidString); - cacheNewSkin.setString(2, url); - cacheNewSkin.setDate(3, new Date(System.currentTimeMillis())); - cacheNewSkin.setBytes(4, textureBlobCompressed); - cacheNewSkin.setInt(5, len); - cacheNewSkin.executeUpdate(); - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while caching new skin", ex); - } - } - - public CacheLoadedProfile loadProfileByUUID(UUID uuid) throws CacheException { - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(queryProfileByUUID) { - queryProfileByUUID.setString(1, uuidString); - try(ResultSet resultSet = queryProfileByUUID.executeQuery()) { - if(resultSet.next()) { - String profileName = resultSet.getString(1); - String profileTexture = resultSet.getString(2); - String profileModel = resultSet.getString(3); - return new CacheLoadedProfile(uuid, profileName, profileTexture, profileModel); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading profile by uuid", ex); - } - } - - public CacheLoadedProfile loadProfileByUsername(String username) throws CacheException { - try { - synchronized(queryProfileByUsername) { - queryProfileByUsername.setString(1, username); - try(ResultSet resultSet = queryProfileByUsername.executeQuery()) { - if(resultSet.next()) { - UUID profileUUID = SkinService.parseMojangUUID(resultSet.getString(1)); - String profileTexture = resultSet.getString(2); - String profileModel = resultSet.getString(3); - return new CacheLoadedProfile(profileUUID, username, profileTexture, profileModel); - }else { - return null; - } - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while loading profile by username", ex); - } - } - - public void cacheProfileByUUID(UUID uuid, String username, String texture, String model) throws CacheException { - try { - String uuidString = SkinService.getMojangUUID(uuid); - synchronized(cacheNewProfile) { - boolean has; - cacheHasProfile.setString(1, uuidString); - try(ResultSet resultSet = cacheHasProfile.executeQuery()) { - if(resultSet.next()) { - has = resultSet.getInt(1) > 0; - }else { - has = false; // ?? - } - } - if(has) { - cacheUpdateProfile.setString(1, username); - cacheUpdateProfile.setDate(2, new Date(System.currentTimeMillis())); - cacheUpdateProfile.setString(3, texture); - cacheUpdateProfile.setString(4, model); - cacheUpdateProfile.setString(5, uuidString); - cacheUpdateProfile.executeUpdate(); - }else { - cacheNewProfile.setString(1, uuidString); - cacheNewProfile.setString(2, username); - cacheNewProfile.setDate(3, new Date(System.currentTimeMillis())); - cacheNewProfile.setString(4, texture); - cacheNewProfile.setString(5, model); - cacheNewProfile.executeUpdate(); - } - } - }catch(SQLException ex) { - throw new CacheException("SQL query failure while caching new profile", ex); - } - } - - @Override - public void flush() { - long steadyMillis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - if(steadyMillis - lastFlush > 1200000l) { // 30 minutes - lastFlush = steadyMillis; - long millis = System.currentTimeMillis(); - try { - Date expiryObjects = new Date(millis - keepObjectsDays * 86400000l); - Date expiryProfiles = new Date(millis - keepProfilesDays * 86400000l); - - synchronized(discardExpiredObjects) { - discardExpiredObjects.setDate(1, expiryObjects); - discardExpiredObjects.execute(); - } - synchronized(discardExpiredProfiles) { - discardExpiredProfiles.setDate(1, expiryProfiles); - discardExpiredProfiles.execute(); - } - - int totalObjects, totalProfiles; - - synchronized(getTotalObjects) { - try(ResultSet resultSet = getTotalObjects.executeQuery()) { - if(resultSet.next()) { - totalObjects = resultSet.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved when checking \"eaglercraft_skins_objects\" row count"); - } - } - } - - synchronized(getTotalProfiles) { - try(ResultSet resultSet = getTotalProfiles.executeQuery()) { - if(resultSet.next()) { - totalProfiles = resultSet.getInt(1); - }else { - throw new SQLException("Empty ResultSet recieved when checking \"eaglercraft_skins_profiles\" row count"); - } - } - } - - if(totalObjects > maxObjects) { - int deleteCount = totalObjects - maxObjects + (maxObjects >> 3); - EaglerXVelocity.logger().warn( - "Skin object cache has passed {} skins in size ({}), deleting {} skins from the cache to free space", - maxObjects, totalObjects, deleteCount); - synchronized(deleteSomeOldestObjects) { - deleteSomeOldestObjects.setInt(1, deleteCount); - deleteSomeOldestObjects.executeUpdate(); - } - } - - if(totalProfiles > maxProfiles) { - int deleteCount = totalProfiles - maxProfiles + (maxProfiles >> 3); - EaglerXVelocity.logger().warn( - "Skin profile cache has passed {} profiles in size ({}), deleting {} profiles from the cache to free space", - maxProfiles, totalProfiles, deleteCount); - synchronized(deleteSomeOldestProfiles) { - deleteSomeOldestProfiles.setInt(1, deleteCount); - deleteSomeOldestProfiles.executeUpdate(); - } - } - - }catch(SQLException ex) { - throw new CacheException("SQL query failure while flushing cache!", ex); - } - } - } - - private void destroyStatement(Statement stmt) { - try { - stmt.close(); - } catch (SQLException e) { - } - } - - @Override - public void destroy() { - destroyStatement(discardExpiredObjects); - destroyStatement(discardExpiredProfiles); - destroyStatement(getTotalObjects); - destroyStatement(getTotalProfiles); - destroyStatement(deleteSomeOldestObjects); - destroyStatement(deleteSomeOldestProfiles); - destroyStatement(querySkinByUUID); - destroyStatement(queryProfileByUUID); - destroyStatement(queryProfileByUsername); - destroyStatement(cacheNewSkin); - destroyStatement(cacheNewProfile); - destroyStatement(cacheHasSkin); - destroyStatement(cacheHasProfile); - destroyStatement(cacheUpdateSkin); - destroyStatement(cacheUpdateProfile); - try { - connection.close(); - EaglerXVelocity.logger().info("Successfully disconnected from database '{}'", uri); - } catch (SQLException e) { - EaglerXVelocity.logger().warn("Exception disconnecting from database '{}'!", uri, e); - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SimpleRateLimiter.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SimpleRateLimiter.java deleted file mode 100644 index 8e0383e2..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SimpleRateLimiter.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class SimpleRateLimiter { - - private long timer; - private int count; - - public SimpleRateLimiter() { - timer = EaglerXVelocityAPIHelper.steadyTimeMillis(); - count = 0; - } - - public boolean rateLimit(int maxPerMinute) { - int t = 60000 / maxPerMinute; - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - int decr = (int)(millis - timer) / t; - if(decr > 0) { - timer += decr * t; - count -= decr; - if(count < 0) { - count = 0; - } - } - if(count >= maxPerMinute) { - return false; - }else { - ++count; - return true; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinPackets.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinPackets.java deleted file mode 100644 index 36f348a5..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinPackets.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV3EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinCustomV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class SkinPackets { - - public static final int PACKET_MY_SKIN_PRESET = 0x01; - public static final int PACKET_MY_SKIN_CUSTOM = 0x02; - - public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, ISkinService skinService, int protocolVers) throws IOException { - if(bs.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - GameMessagePacket generatedPacketV3 = null; - GameMessagePacket generatedPacketV4 = null; - int skinModel = -1; - int packetType = (int)bs[0] & 0xFF; - switch(packetType) { - case PACKET_MY_SKIN_PRESET: - if(bs.length != 5) { - throw new IOException("Invalid length " + bs.length + " for preset skin packet"); - } - generatedPacketV3 = generatedPacketV4 = new SPacketOtherSkinPresetEAG(clientUUID.getMostSignificantBits(), - clientUUID.getLeastSignificantBits(), (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); - break; - case PACKET_MY_SKIN_CUSTOM: - if(protocolVers <= 3) { - byte[] pixels = new byte[16384]; - if(bs.length != 2 + pixels.length) { - throw new IOException("Invalid length " + bs.length + " for custom skin packet"); - } - setAlphaForChestV3(pixels); - System.arraycopy(bs, 2, pixels, 0, pixels.length); - generatedPacketV3 = new SPacketOtherSkinCustomV3EAG(clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), (skinModel = (int)bs[1] & 0xFF), pixels); - }else { - byte[] pixels = new byte[12288]; - if(bs.length != 2 + pixels.length) { - throw new IOException("Invalid length " + bs.length + " for custom skin packet"); - } - setAlphaForChestV4(pixels); - System.arraycopy(bs, 2, pixels, 0, pixels.length); - generatedPacketV4 = new SPacketOtherSkinCustomV4EAG(clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), (skinModel = (int)bs[1] & 0xFF), pixels); - } - break; - default: - throw new IOException("Unknown skin packet type: " + packetType); - } - skinService.registerEaglercraftPlayer(clientUUID, new SkinPacketVersionCache(generatedPacketV3, generatedPacketV4), skinModel); - } - - public static void registerEaglerPlayerFallback(UUID clientUUID, ISkinService skinService) { - int skinModel = (clientUUID.hashCode() & 1) != 0 ? 1 : 0; - skinService.registerEaglercraftPlayer(clientUUID, SkinPacketVersionCache.createPreset( - clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), skinModel), skinModel); - } - - public static void setAlphaForChestV3(byte[] skin64x64) { - if(skin64x64.length != 16384) { - throw new IllegalArgumentException("Skin is not 64x64!"); - } - for(int y = 20; y < 32; ++y) { - for(int x = 16; x < 40; ++x) { - skin64x64[(y << 8) | (x << 2)] = (byte)0xFF; - } - } - } - - public static void setAlphaForChestV4(byte[] skin64x64) { - if(skin64x64.length != 12288) { - throw new IllegalArgumentException("Skin is not 64x64!"); - } - for(int y = 20; y < 32; ++y) { - for(int x = 16; x < 40; ++x) { - skin64x64[((y << 6) | x) * 3] |= 0x80; - } - } - } - - public static String bytesToAscii(byte[] bytes, int off, int len) { - char[] ret = new char[len]; - for(int i = 0; i < len; ++i) { - ret[i] = (char)((int)bytes[off + i] & 0xFF); - } - return new String(ret); - } - - public static String bytesToAscii(byte[] bytes) { - return bytesToAscii(bytes, 0, bytes.length); - } - - public static byte[] asciiString(String string) { - byte[] str = new byte[string.length()]; - for(int i = 0; i < str.length; ++i) { - str[i] = (byte)string.charAt(i); - } - return str; - } - - public static UUID createEaglerURLSkinUUID(String skinUrl) { - return UUID.nameUUIDFromBytes(asciiString("EaglercraftSkinURL:" + skinUrl)); - } - - public static int getModelId(String modelName) { - return "slim".equalsIgnoreCase(modelName) ? 1 : 0; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinRescaler.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinRescaler.java deleted file mode 100644 index ab8d208f..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinRescaler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -public class SkinRescaler { - - public static void convertToBytes(int[] imageIn, byte[] imageOut) { - for(int i = 0, j, k; i < imageIn.length; ++i) { - j = i << 2; - k = imageIn[i]; - imageOut[j] = (byte)(k >>> 24); - imageOut[j + 1] = (byte)(k & 0xFF); - imageOut[j + 2] = (byte)(k >>> 8); - imageOut[j + 3] = (byte)(k >>> 16); - } - } - - public static void convert64x32To64x64(int[] imageIn, byte[] imageOut) { - copyRawPixels(imageIn, imageOut, 0, 0, 0, 0, 64, 32, 64, 64, false); - copyRawPixels(imageIn, imageOut, 24, 48, 20, 52, 4, 16, 8, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 28, 48, 24, 52, 8, 16, 12, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 20, 52, 16, 64, 8, 20, 12, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 24, 52, 20, 64, 4, 20, 8, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 28, 52, 24, 64, 0, 20, 4, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 32, 52, 28, 64, 12, 20, 16, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 40, 48, 36, 52, 44, 16, 48, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 44, 48, 40, 52, 48, 16, 52, 20, 64, 64); - copyRawPixels(imageIn, imageOut, 36, 52, 32, 64, 48, 20, 52, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 40, 52, 36, 64, 44, 20, 48, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 44, 52, 40, 64, 40, 20, 44, 32, 64, 64); - copyRawPixels(imageIn, imageOut, 48, 52, 44, 64, 52, 20, 56, 32, 64, 64); - } - - private static void copyRawPixels(int[] imageIn, byte[] imageOut, int dx1, int dy1, int dx2, int dy2, int sx1, - int sy1, int sx2, int sy2, int imgSrcWidth, int imgDstWidth) { - if(dx1 > dx2) { - copyRawPixels(imageIn, imageOut, sx1, sy1, dx2, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, true); - } else { - copyRawPixels(imageIn, imageOut, sx1, sy1, dx1, dy1, sx2 - sx1, sy2 - sy1, imgSrcWidth, imgDstWidth, false); - } - } - - private static void copyRawPixels(int[] imageIn, byte[] imageOut, int srcX, int srcY, int dstX, int dstY, int width, - int height, int imgSrcWidth, int imgDstWidth, boolean flip) { - int i, j; - for(int y = 0; y < height; ++y) { - for(int x = 0; x < width; ++x) { - i = imageIn[(srcY + y) * imgSrcWidth + srcX + x]; - if(flip) { - j = (dstY + y) * imgDstWidth + dstX + width - x - 1; - }else { - j = (dstY + y) * imgDstWidth + dstX + x; - } - j = j << 2; - imageOut[j] = (byte)(i >>> 24); - imageOut[j + 1] = (byte)(i & 0xFF); - imageOut[j + 2] = (byte)(i >>> 8); - imageOut[j + 3] = (byte)(i >>> 16); - } - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinService.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinService.java deleted file mode 100644 index fce1c5b1..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinService.java +++ /dev/null @@ -1,1436 +0,0 @@ -/* - * Copyright (c) 2022-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Consumer; - -import com.google.common.collect.Multimap; -import com.google.common.collect.MultimapBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.scheduler.ScheduledTask; -import com.velocitypowered.api.util.GameProfile; -import com.velocitypowered.api.util.GameProfile.Property; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.AsyncSkinProvider.CacheFetchedProfile; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.AsyncSkinProvider.CancelException; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketForceClientSkinPresetV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class SkinService implements ISkinService { - - public static final int masterRateLimitPerPlayer = 250; - - private final ConcurrentMap onlinePlayersCache = new ConcurrentHashMap<>(); - private final ConcurrentMap onlinePlayersToTexturesMap = new ConcurrentHashMap<>(); - private final ConcurrentMap foreignSkinCache = new ConcurrentHashMap<>(); - - private final ReadWriteLock onlinePlayersFromTexturesMapLock = new ReentrantReadWriteLock(); - private final Multimap onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build(); - - private final Map pendingTextures = new HashMap<>(); - private final Map pendingUUIDs = new HashMap<>(); - private final Map pendingNameLookups = new HashMap<>(); - - private final ReadWriteLock antagonistsLock = new ReentrantReadWriteLock(); - private final Object2IntMap antagonists = new Object2IntOpenHashMap<>(); - - private long antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis(); - - private final Consumer> antagonistLogger = new Consumer>() { - - @Override - public void accept(Set t) { - if(t.size() == 1) { - int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit() << 1; - UUID offender = t.iterator().next(); - antagonistsLock.writeLock().lock(); - try { - int v = antagonists.getInt(offender); - if(v == antagonists.defaultReturnValue()) { - antagonists.put(offender, 1); - }else { - if(v <= limit) { - antagonists.put(offender, v + 1); - } - } - }finally { - antagonistsLock.writeLock().unlock(); - } - } - } - - }; - - private ICacheProvider cacheProvider = null; - - protected static class CachedForeignSkin { - - protected final UUID uuid; - protected final SkinPacketVersionCache data; - protected final int modelKnown; - protected volatile long lastHit; - - protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) { - this.uuid = uuid; - this.data = data; - this.modelKnown = modelKnown; - this.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - } - - } - - protected static class CachedPlayerSkin { - - protected final SkinPacketVersionCache data; - protected final UUID textureUUID; - protected final int modelId; - - protected CachedPlayerSkin(SkinPacketVersionCache data, UUID textureUUID, int modelId) { - this.data = data; - this.textureUUID = textureUUID; - this.modelId = modelId; - } - - } - - protected class PendingTextureDownload implements Consumer { - - protected final UUID textureUUID; - protected final String textureURL; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingTextureDownload(UUID textureUUID, String textureURL, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.textureUUID = textureUUID; - this.textureURL = textureURL; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(byte[] t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingTextures) { - finalized = true; - pendingTextures.remove(textureUUID); - } - } - } - - } - - protected class PendingProfileUUIDLookup implements Consumer { - - protected final UUID profileUUID; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.profileUUID = profileUUID; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(CacheFetchedProfile t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingUUIDs) { - finalized = true; - pendingUUIDs.remove(profileUUID); - } - } - } - - } - - protected class PendingProfileNameLookup implements Consumer { - - protected final String profileName; - - protected final Set antagonists; - protected final List> callbacks; - protected final Consumer> antagonistsCallback; - - protected final long initializedTime; - protected volatile boolean finalized; - - protected PendingProfileNameLookup(String profileName, UUID caller, Consumer callback, - Consumer> antagonistsCallback) { - this.profileName = profileName; - this.antagonists = new LinkedHashSet<>(); - this.antagonists.add(caller); - this.callbacks = new LinkedList<>(); - this.callbacks.add(callback); - this.antagonistsCallback = antagonistsCallback; - this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); - this.finalized = false; - } - - @Override - public void accept(CacheFetchedProfile t) { - for(int i = 0, l = callbacks.size(); i < l; ++i) { - try { - callbacks.get(i).accept(t); - }catch(Throwable t2) { - } - } - if(t != null) { - synchronized(pendingNameLookups) { - finalized = true; - pendingNameLookups.remove(profileName); - } - } - } - - } - - public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles) { - antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis(); - if(cacheProvider == null) { - cacheProvider = JDBCCacheProvider.initialize(uri, driverClass, driverPath, keepObjectsDays, - keepProfilesDays, maxObjects, maxProfiles); - } - resetMaps(); - } - - public void processGetOtherSkin(final UUID searchUUID, final EaglerPlayerData sender) { - if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - return; - } - - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(searchUUID); - - if(maybeCachedPacket != null) { - sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol())); - }else { - Player player = EaglerXVelocity.proxy().getPlayer(searchUUID).orElse(null); - UUID playerTexture = onlinePlayersToTexturesMap.get(searchUUID); - if(playerTexture != null) { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( - maybeCachedPacket.data, searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits()); - if(player != null) { - onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten, - maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); - } - sender.sendEaglerMessage(rewritten.get(sender.getEaglerProtocol())); - return; - } - } - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture); - if(foreignSkin != null && foreignSkin.modelKnown != -1) { - if(player != null) { - onlinePlayersCache.put(searchUUID, - new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, - searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()), - playerTexture, foreignSkin.modelKnown)); - foreignSkinCache.remove(playerTexture); - }else { - foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - } - sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); - return; - } - } - if(player != null && (player instanceof ConnectedPlayer)) { - GameProfile loginProfile = player.getGameProfile(); - if(loginProfile != null) { - List props = loginProfile.getProperties(); - if(props.size() > 0) { - for(int i = 0, l = props.size(); i < l; ++i) { - Property pp = props.get(i); - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = sanitizeTextureURL(url.getAsString()); - if(urlStr == null) { - break; - } - int model = 0; - JsonElement el = skinObj.get("metadata"); - if(el != null && el.isJsonObject()) { - el = el.getAsJsonObject().get("model"); - if(el != null) { - model = SkinPackets.getModelId(el.getAsString()); - } - } - UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr); - - CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID); - if(foreignSkin != null) { - registerTextureToPlayerAssociation(skinUUID, searchUUID); - SkinPacketVersionCache rewrite = SkinPacketVersionCache - .rewriteUUIDModel(foreignSkin.data, - searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), model); - onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model)); - sender.sendEaglerMessage(rewrite.get(sender.getEaglerProtocol())); - return; - } - - // download player skin, put in onlinePlayersCache, no limit - - if(!isLimitedAsAntagonist(player.getUniqueId())) { - final int modelf = model; - doAsync(() -> { - processResolveURLTextureForOnline(sender, searchUUID, skinUUID, urlStr, modelf); - }); - } - - return; - } - } - }catch(Throwable t) { - } - } - } - } - } - if(!isLimitedAsAntagonist(player.getUniqueId())) { - doAsync(() -> { - if(player.isOnlineMode()) { - processResolveProfileTextureByUUIDForOnline(sender, searchUUID); - }else { - processResolveProfileTextureByNameForOnline(sender, player.getUsername(), searchUUID); - } - }); - } - }else { - CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); - }else { - if (sender.skinUUIDLookupRateLimiter - .rateLimit(EaglerXVelocity.getEagler().getConfig().getUuidRateLimitPlayer()) - && !isLimitedAsAntagonist(sender.getUniqueId())) { - if(sender.isOnlineMode()) { - doAsync(() -> { - processResolveProfileTextureByUUIDForeign(sender, searchUUID); - }); - }else { - sender.sendEaglerMessage( - new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), isAlex(searchUUID) ? 1 : 0)); - } - } - } - } - } - } - - public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) { - EaglerVelocityConfig config = EaglerXVelocity.getEagler().getConfig(); - if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - return; - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); - }else { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(searchUUID)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol(), - searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits())); - return; - } - } - } - if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds - sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - return; - } - skinURL = sanitizeTextureURL(skinURL); - if(skinURL != null) { - final String skinURL_ = skinURL; - if(sender.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) { - doAsync(() -> { - processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL_, -1); - }); - } - }else { - sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - } - } - } - - private void processResolveURLTextureForOnline(final EaglerPlayerData initiator, final UUID onlineCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin; - if (t != null) { - registerTextureToPlayerAssociation(skinUUID, onlineCacheUUID); - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createCustomV3( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits(), modelId, t), - skinUUID, modelId); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits()), null, -1); - } - onlinePlayersCache.put(onlineCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveURLTextureForForeign(final EaglerPlayerData initiator, final UUID foreignCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin; - if (t != null) { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createCustomV3( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits(), modelId, t), - modelId); - } else { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createPreset( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits()), - -1); - } - foreignSkinCache.put(foreignCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForOnline(final EaglerPlayerData initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - }else { - processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - null, -1); - } - onlinePlayersCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - }else { - processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - private void processResolveProfileTextureByNameForOnline(final EaglerPlayerData initiator, final String playerName, final UUID mapUUID) { - synchronized(pendingNameLookups) { - PendingProfileNameLookup alreadyPending = pendingNameLookups.get(playerName); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - }else { - processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileNameLookup newTask = new PendingProfileNameLookup( - playerName, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(mapUUID.getMostSignificantBits(), - mapUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1); - } - onlinePlayersCache.put(mapUUID, skin); - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - }else { - processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUsername(playerName, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingNameLookups.put(playerName, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForeign(final EaglerPlayerData initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin = foreignSkinCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - } - }else { - processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin; - if (t == null) { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - -1); - } else { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - -1); - } - foreignSkinCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); - }else { - processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { - foreignSkinCache.remove(clientUUID); - onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId)); - } - - public void unregisterPlayer(UUID clientUUID) { - CachedPlayerSkin data = onlinePlayersCache.remove(clientUUID); - if(data != null) { - foreignSkinCache.put(clientUUID, new CachedForeignSkin(clientUUID, data.data, data.modelId)); - if(data.textureUUID != null) { - foreignSkinCache.put(data.textureUUID, new CachedForeignSkin(data.textureUUID, data.data, data.modelId)); - } - deletePlayerTextureAssociation(clientUUID, data.textureUUID); - }else { - deletePlayerTextureAssociation(clientUUID, null); - } - } - - private void deletePlayerTextureAssociation(UUID clientUUID, UUID textureUUID) { - if(textureUUID != null) { - onlinePlayersToTexturesMap.remove(clientUUID); - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.remove(textureUUID, clientUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - }else { - UUID removedUUID = onlinePlayersToTexturesMap.remove(clientUUID); - if(removedUUID != null) { - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.remove(removedUUID, clientUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - } - } - } - - public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) { - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.put(textureUUID, playerUUID); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - onlinePlayersToTexturesMap.put(playerUUID, textureUUID); - CachedForeignSkin foreign = foreignSkinCache.remove(textureUUID); - if(foreign != null) { - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(foreign.data, textureUUID, foreign.modelKnown)); - } - } - - public void processForceSkin(UUID playerUUID, EaglerPlayerData eaglerHandler) { - CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(playerUUID); - - if(maybeCachedPacket != null) { - eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4()); - }else { - UUID playerTexture = onlinePlayersToTexturesMap.get(playerUUID); - if(playerTexture != null) { - Collection possiblePlayers; - onlinePlayersFromTexturesMapLock.readLock().lock(); - try { - possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture)); - }finally { - onlinePlayersFromTexturesMapLock.readLock().unlock(); - } - boolean playersExist = possiblePlayers.size() > 0; - if(playersExist) { - for(UUID uuid : possiblePlayers) { - maybeCachedPacket = onlinePlayersCache.get(uuid); - if(maybeCachedPacket != null) { - SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( - maybeCachedPacket.data, playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()); - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten, - maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); - eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4()); - return; - } - } - } - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture); - if(foreignSkin != null && foreignSkin.modelKnown != -1) { - onlinePlayersCache.put(playerUUID, - new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, - playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()), - playerTexture, foreignSkin.modelKnown)); - foreignSkinCache.remove(playerTexture); - eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4()); - return; - } - } - GameProfile loginProfile = eaglerHandler.getGameProfile(); - if(loginProfile != null) { - List props = loginProfile.getProperties(); - if(props.size() > 0) { - for(int i = 0, l = props.size(); i < l; ++i) { - Property pp = props.get(i); - if(pp.getName().equals("textures")) { - try { - String jsonStr = SkinPackets.bytesToAscii(Base64.decodeBase64(pp.getValue())); - JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); - JsonObject skinObj = json.getAsJsonObject("SKIN"); - if(skinObj != null) { - JsonElement url = json.get("url"); - if(url != null) { - String urlStr = sanitizeTextureURL(url.getAsString()); - if(urlStr == null) { - break; - } - int model = 0; - JsonElement el = skinObj.get("metadata"); - if(el != null && el.isJsonObject()) { - el = el.getAsJsonObject().get("model"); - if(el != null) { - model = SkinPackets.getModelId(el.getAsString()); - } - } - UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr); - - CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID); - if(foreignSkin != null) { - registerTextureToPlayerAssociation(skinUUID, playerUUID); - SkinPacketVersionCache rewrite = SkinPacketVersionCache - .rewriteUUIDModel(foreignSkin.data, - playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), model); - onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewrite, skinUUID, model)); - eaglerHandler.sendEaglerMessage(rewrite.getForceClientV4()); - return; - } - - // download player skin, put in onlinePlayersCache, no limit - - final int modelf = model; - doAsync(() -> { - processResolveURLTextureForOnlineToForce(eaglerHandler, playerUUID, skinUUID, urlStr, modelf); - }); - - return; - } - } - }catch(Throwable t) { - } - } - } - } - doAsync(() -> { - if(eaglerHandler.isOnlineMode()) { - processResolveProfileTextureByUUIDForOnlineToForce(eaglerHandler, playerUUID); - }else { - processResolveProfileTextureByNameForOnlineToForce(eaglerHandler, eaglerHandler.getName(), playerUUID); - } - }); - }else { - CachedForeignSkin foreignSkin = foreignSkinCache.get(playerUUID); - if(foreignSkin != null) { - foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); - eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4()); - }else { - if(eaglerHandler.isOnlineMode()) { - doAsync(() -> { - processResolveProfileTextureByUUIDForeignToForce(eaglerHandler, playerUUID); - }); - }else { - eaglerHandler.sendEaglerMessage(new SPacketForceClientSkinPresetV4EAG(isAlex(playerUUID) ? 1 : 0)); - } - } - } - } - } - - private void processResolveURLTextureForOnlineToForce(final EaglerPlayerData initiator, final UUID onlineCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedPlayerSkin skin; - if (t != null) { - registerTextureToPlayerAssociation(skinUUID, onlineCacheUUID); - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createCustomV3( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits(), modelId, t), - skinUUID, modelId); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - onlineCacheUUID.getMostSignificantBits(), - onlineCacheUUID.getLeastSignificantBits()), null, -1); - } - onlinePlayersCache.put(onlineCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveURLTextureForForeignToForce(final EaglerPlayerData initiator, final UUID foreignCacheUUID, - final UUID skinUUID, final String urlStr, final int modelId) { - synchronized(pendingTextures) { - PendingTextureDownload alreadyPending = pendingTextures.get(skinUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - } - - }); - } - }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), - new Consumer() { - - @Override - public void accept(byte[] t) { - CachedForeignSkin skin; - if (t != null) { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createCustomV3( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits(), modelId, t), - modelId); - } else { - skin = new CachedForeignSkin(foreignCacheUUID, - SkinPacketVersionCache.createPreset( - foreignCacheUUID.getMostSignificantBits(), - foreignCacheUUID.getLeastSignificantBits()), - -1); - } - foreignSkinCache.put(foreignCacheUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - - }, antagonistLogger); - try { - AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingTextures.put(skinUUID, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForOnlineToForce(final EaglerPlayerData initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - null, -1); - } - onlinePlayersCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - private void processResolveProfileTextureByNameForOnlineToForce(final EaglerPlayerData initiator, final String playerName, final UUID mapUUID) { - synchronized(pendingNameLookups) { - PendingProfileNameLookup alreadyPending = pendingNameLookups.get(playerName); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileNameLookup newTask = new PendingProfileNameLookup( - playerName, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedPlayerSkin skin; - if (t == null) { - skin = new CachedPlayerSkin( - SkinPacketVersionCache.createPreset(mapUUID.getMostSignificantBits(), - mapUUID.getLeastSignificantBits()), - null, -1); - } else { - skin = new CachedPlayerSkin(SkinPacketVersionCache.createPreset( - mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1); - } - onlinePlayersCache.put(mapUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUsername(playerName, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingNameLookups.put(playerName, newTask); - } - } - } - - private void processResolveProfileTextureByUUIDForeignToForce(final EaglerPlayerData initiator, final UUID playerUUID) { - synchronized(pendingUUIDs) { - PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); - if(alreadyPending != null) { - if(alreadyPending.antagonists.add(initiator.getUniqueId())) { - alreadyPending.callbacks.add(new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin = foreignSkinCache.get(playerUUID); - if(skin != null) { - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - } - }else { - processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }); - } - }else { - PendingProfileUUIDLookup newTask = new PendingProfileUUIDLookup( - playerUUID, initiator.getUniqueId(), new Consumer() { - - @Override - public void accept(CacheFetchedProfile t) { - if(t == null || t.texture == null) { - CachedForeignSkin skin; - if (t == null) { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits()), - -1); - } else { - skin = new CachedForeignSkin(playerUUID, - SkinPacketVersionCache.createPreset(playerUUID.getMostSignificantBits(), - playerUUID.getLeastSignificantBits(), - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), - -1); - } - foreignSkinCache.put(playerUUID, skin); - initiator.sendEaglerMessage(skin.data.getForceClientV4()); - }else { - processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture, - SkinPackets.getModelId(t.model)); - } - } - - }, antagonistLogger); - try { - AsyncSkinProvider.lookupProfileByUUID(playerUUID, cacheProvider, newTask); - }catch(CancelException ex) { - return; - } - pendingUUIDs.put(playerUUID, newTask); - } - } - } - - public void flush() { - long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); - - final List foreignSkinCleanup = new ArrayList<>(4); - foreignSkinCache.entrySet().forEach((etr) -> { - if(millis - etr.getValue().lastHit > 900000l) { // 15 minutes - foreignSkinCleanup.add(etr.getKey()); - } - }); - - if(!foreignSkinCleanup.isEmpty()) { - for(UUID uuid : foreignSkinCleanup) { - foreignSkinCache.remove(uuid); - } - } - - synchronized(pendingTextures) { - Iterator itr = pendingTextures.values().iterator(); - while(itr.hasNext()) { - PendingTextureDownload etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - synchronized(pendingUUIDs) { - Iterator itr = pendingUUIDs.values().iterator(); - while(itr.hasNext()) { - PendingProfileUUIDLookup etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - synchronized(pendingNameLookups) { - Iterator itr = pendingNameLookups.values().iterator(); - while(itr.hasNext()) { - PendingProfileNameLookup etr = itr.next(); - if(millis - etr.initializedTime > (etr.finalized ? 5000l : 10000l)) { - itr.remove(); - try { - etr.antagonistsCallback.accept(etr.antagonists); - }catch(Throwable t) { - } - } - } - } - - int cooldownPeriod = 60000 / EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit(); - int elapsedCooldown = (int)(millis - antagonistCooldown); - elapsedCooldown /= cooldownPeriod; - if(elapsedCooldown > 0) { - antagonistCooldown += elapsedCooldown * cooldownPeriod; - antagonistsLock.writeLock().lock(); - try { - Iterator itr = antagonists.keySet().iterator(); - while(itr.hasNext()) { - UUID key = itr.next(); - int i = antagonists.getInt(key) - elapsedCooldown; - if(i <= 0) { - itr.remove(); - }else { - antagonists.put(key, i); - } - } - }finally { - antagonistsLock.writeLock().unlock(); - } - } - - cacheProvider.flush(); - } - - public SkinPacketVersionCache getSkin(UUID playerUUID) { - CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID); - return skin != null ? skin.data : null; - } - - public void shutdown() { - resetMaps(); - if(cacheProvider != null) { - cacheProvider.destroy(); - } - cacheProvider = null; - } - - private boolean isLimitedAsAntagonist(UUID uuid) { - int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit(); - limit += limit >> 1; - int i; - antagonistsLock.readLock().lock(); - try { - i = antagonists.getInt(uuid); - }finally { - antagonistsLock.readLock().unlock(); - } - return i != antagonists.defaultReturnValue() && i > limit; - } - - private void resetMaps() { - onlinePlayersCache.clear(); - onlinePlayersFromTexturesMapLock.writeLock().lock(); - try { - onlinePlayersFromTexturesMap.clear(); - }finally { - onlinePlayersFromTexturesMapLock.writeLock().unlock(); - } - onlinePlayersToTexturesMap.clear(); - foreignSkinCache.clear(); - synchronized(pendingTextures) { - pendingTextures.clear(); - } - synchronized(pendingUUIDs) { - pendingUUIDs.clear(); - } - synchronized(pendingNameLookups) { - pendingNameLookups.clear(); - } - antagonistsLock.writeLock().lock(); - try { - antagonists.clear(); - }finally { - antagonistsLock.writeLock().unlock(); - } - } - - private ScheduledTask doAsync(Runnable handler) { - return EaglerXVelocity.proxy().getScheduler().buildTask(EaglerXVelocity.getEagler(), handler).schedule(); - } - - public static String sanitizeTextureURL(String url) { - try { - URI uri = URI.create(url); - StringBuilder builder = new StringBuilder(); - String scheme = uri.getScheme(); - if(scheme == null) { - return null; - } - String host = uri.getHost(); - if(host == null || !EaglerXVelocity.getEagler().getConfig().isValidSkinHost(host)) { - return null; - } - scheme = scheme.toLowerCase(); - builder.append(scheme).append("://"); - builder.append(host); - int port = uri.getPort(); - if(port != -1) { - switch(scheme) { - case "http": - if(port == 80) { - port = -1; - } - break; - case "https": - if(port == 443) { - port = -1; - } - break; - default: - return null; - } - if(port != -1) { - builder.append(":").append(port); - } - } - String path = uri.getRawPath(); - if(path != null) { - if(path.contains("//")) { - path = String.join("/", path.split("[\\/]+")); - } - int len = path.length(); - if(len > 1 && path.charAt(len - 1) == '/') { - path = path.substring(0, len - 1); - } - builder.append(path); - } - return builder.toString(); - }catch(Throwable t) { - return null; - } - } - - private static final String hexString = "0123456789abcdef"; - - private static final char[] HEX = new char[] { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - public static String getMojangUUID(UUID uuid) { - char[] ret = new char[32]; - long msb = uuid.getMostSignificantBits(); - long lsb = uuid.getLeastSignificantBits(); - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - ret[i] = HEX[(int)((msb >> j) & 15l)]; - ret[i + 16] = HEX[(int)((lsb >> j) & 15l)]; - } - return new String(ret); - } - - public static UUID parseMojangUUID(String uuid) { - long msb = 0l; - long lsb = 0l; - for(int i = 0, j; i < 16; ++i) { - j = (15 - i) << 2; - msb |= ((long)hexString.indexOf(uuid.charAt(i)) << j); - lsb |= ((long)hexString.indexOf(uuid.charAt(i + 16)) << j); - } - return new UUID(msb, lsb); - } - - public static boolean isAlex(UUID skinUUID) { - return (skinUUID.hashCode() & 1) != 0; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinServiceOffline.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinServiceOffline.java deleted file mode 100644 index 8b6415b2..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/skins/SkinServiceOffline.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2022-2025 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; - -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; - -public class SkinServiceOffline implements ISkinService { - - public static final int masterRateLimitPerPlayer = 250; - - private static class CachedSkin { - - protected final UUID uuid; - protected final SkinPacketVersionCache packet; - - protected CachedSkin(UUID uuid, SkinPacketVersionCache packet) { - this.uuid = uuid; - this.packet = packet; - } - - } - - private final ConcurrentMap skinCache = new ConcurrentHashMap<>(); - - public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, - int maxObjects, int maxProfiles) { - skinCache.clear(); - } - - public void processGetOtherSkin(UUID searchUUID, EaglerPlayerData sender) { - CachedSkin cached = skinCache.get(searchUUID); - if(cached != null) { - sender.sendEaglerMessage(cached.packet.get(sender.getEaglerProtocol())); - }else { - sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), (searchUUID.hashCode() & 1) != 0 ? 1 : 0)); - } - } - - public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) { - if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds - sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), 0)); - return; - } - sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), - searchUUID.getLeastSignificantBits(), (searchUUID.hashCode() & 1) != 0 ? 1 : 0)); - } - - public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { - skinCache.put(clientUUID, new CachedSkin(clientUUID, generatedPacket)); - } - - public void unregisterPlayer(UUID clientUUID) { - skinCache.remove(clientUUID); - } - - public void registerTextureToPlayerAssociation(String textureURL, UUID playerUUID) { - } - - public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) { - } - - public void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler) { - CachedSkin cached = skinCache.get(playerUUID); - if(cached != null) { - initialHandler.sendEaglerMessage(cached.packet.getForceClientV4()); - } - } - - public void flush() { - // no - } - - public void shutdown() { - skinCache.clear(); - } - - public SkinPacketVersionCache getSkin(UUID playerUUID) { - CachedSkin cached = skinCache.get(playerUUID); - return cached != null ? cached.packet : null; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/sqlite/EaglerDrivers.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/sqlite/EaglerDrivers.java deleted file mode 100644 index 50809fd4..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/sqlite/EaglerDrivers.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.sqlite; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.sql.Connection; -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; - -public class EaglerDrivers { - - private static Driver initializeDriver(String address, String driverClass) { - URLClassLoader classLoader = driversJARs.get(address); - if(classLoader == null) { - File driver; - if(address.equalsIgnoreCase("internal")) { - driver = new File(EaglerXVelocity.getEagler().getDataFolder(), "drivers/sqlite-jdbc.jar"); - driver.getParentFile().mkdirs(); - if(!driver.exists()) { - try { - URL u = new URL("https://repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.45.0.0/sqlite-jdbc-3.45.0.0.jar"); - EaglerXVelocity.logger().info("Downloading from maven: {}", u); - copyURLToFile(u, driver); - } catch (Throwable ex) { - EaglerXVelocity.logger().error("Could not download sqlite-jdbc.jar from repo1.maven.org!"); - EaglerXVelocity.logger().error("Please download \"org.xerial:sqlite-jdbc:3.45.0.0\" jar to file: " + driver.getAbsolutePath()); - throw new ExceptionInInitializerError(ex); - } - } - }else { - driver = new File(address); - } - URL driverURL; - try { - driverURL = driver.toURI().toURL(); - }catch(MalformedURLException ex) { - EaglerXVelocity.logger().error("Invalid JDBC driver path: " + address); - throw new ExceptionInInitializerError(ex); - } - classLoader = URLClassLoader.newInstance(new URL[] { driverURL }, ClassLoader.getSystemClassLoader()); - driversJARs.put(address, classLoader); - } - - Class loadedDriver; - try { - loadedDriver = classLoader.loadClass(driverClass); - }catch(ClassNotFoundException ex) { - try { - classLoader.close(); - } catch (IOException e) { - } - EaglerXVelocity.logger().error("Could not find JDBC driver class: " + driverClass); - throw new ExceptionInInitializerError(ex); - } - Driver sqlDriver = null; - try { - sqlDriver = (Driver) loadedDriver.newInstance(); - }catch(Throwable ex) { - try { - classLoader.close(); - } catch (IOException e) { - } - EaglerXVelocity.logger().error("Could not initialize JDBC driver class: " + driverClass); - throw new ExceptionInInitializerError(ex); - } - - return sqlDriver; - } - - private static final Map driversJARs = new HashMap<>(); - private static final Map driversDrivers = new HashMap<>(); - - public static Connection connectToDatabase(String address, String driverClass, String driverPath, Properties props) - throws SQLException { - if(driverClass.equalsIgnoreCase("internal")) { - driverClass = "org.sqlite.JDBC"; - } - if(driverPath == null) { - try { - Class.forName(driverClass); - } catch (ClassNotFoundException e) { - throw new SQLException("Driver class not found in JRE: " + driverClass, e); - } - return DriverManager.getConnection(address, props); - }else { - String driverMapPath = "" + driverPath + "?" + driverClass; - Driver dv = driversDrivers.get(driverMapPath); - if(dv == null) { - dv = initializeDriver(driverPath, driverClass); - driversDrivers.put(driverMapPath, dv); - } - return dv.connect(address, props); - } - } - - private static void copyURLToFile(URL url, File file) throws IOException { - try(InputStream is = url.openStream()) { - try(OutputStream os = new FileOutputStream(file)) { - byte[] buf = new byte[32768]; - int i; - while((i = is.read(buf)) != -1) { - os.write(buf, 0, i); - } - } - } - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/ExpiringSet.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/ExpiringSet.java deleted file mode 100644 index a6e14aba..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/ExpiringSet.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; - -public class ExpiringSet extends HashSet { - private final long expiration; - private final ExpiringEvent event; - - private final Map timestamps = new HashMap<>(); - - public ExpiringSet(long expiration) { - this.expiration = expiration; - this.event = null; - } - - public ExpiringSet(long expiration, ExpiringEvent event) { - this.expiration = expiration; - this.event = event; - } - - public interface ExpiringEvent { - void onExpiration(T item); - } - - public void checkForExpirations() { - Iterator iterator = this.timestamps.keySet().iterator(); - long now = EaglerXVelocityAPIHelper.steadyTimeMillis(); - while (iterator.hasNext()) { - T element = iterator.next(); - if (super.contains(element)) { - if (this.timestamps.get(element) + this.expiration < now) { - if (this.event != null) this.event.onExpiration(element); - iterator.remove(); - super.remove(element); - } - } else { - iterator.remove(); - super.remove(element); - } - } - } - - public boolean add(T o) { - checkForExpirations(); - boolean success = super.add(o); - if (success) timestamps.put(o, EaglerXVelocityAPIHelper.steadyTimeMillis()); - return success; - } - - public boolean remove(Object o) { - checkForExpirations(); - boolean success = super.remove(o); - if (success) timestamps.remove(o); - return success; - } - - public void clear() { - this.timestamps.clear(); - super.clear(); - } - - public boolean contains(Object o) { - checkForExpirations(); - return super.contains(o); - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceServerImpl.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceServerImpl.java deleted file mode 100644 index 618b7e36..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceServerImpl.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import com.velocitypowered.api.proxy.server.ServerInfo; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalConnectAnnounceV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalConnectV3EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalConnectV4EAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalDescEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalDisconnectPeerEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalGlobalEAG; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalICEEAG; - -public class VoiceServerImpl { - - private final ServerInfo server; - private final GameMessagePacket iceServersPacket; - - private final Map voicePlayers = new HashMap<>(); - private final Map> voiceRequests = new HashMap<>(); - private final Set voicePairs = new HashSet<>(); - - private static final int VOICE_CONNECT_RATELIMIT = 15; - - private static class VoicePair { - - private final UUID uuid1; - private final UUID uuid2; - - @Override - public int hashCode() { - return uuid1.hashCode() ^ uuid2.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - VoicePair other = (VoicePair) obj; - return (uuid1.equals(other.uuid1) && uuid2.equals(other.uuid2)) - || (uuid1.equals(other.uuid2) && uuid2.equals(other.uuid1)); - } - - private VoicePair(UUID uuid1, UUID uuid2) { - this.uuid1 = uuid1; - this.uuid2 = uuid2; - } - - private boolean anyEquals(UUID uuid) { - return uuid1.equals(uuid) || uuid2.equals(uuid); - } - } - - VoiceServerImpl(ServerInfo server, GameMessagePacket iceServersPacket) { - this.server = server; - this.iceServersPacket = iceServersPacket; - } - - public void handlePlayerLoggedIn(EaglerPlayerData player) { - player.sendEaglerMessage(iceServersPacket); - player.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.DISABLED); - if(player.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - player.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - } - } - - public void handlePlayerLoggedOut(EaglerPlayerData player) { - removeUser(player.getUniqueId()); - } - - void handleVoiceSignalPacketTypeRequest(UUID player, EaglerPlayerData sender) { - UUID senderUUID; - EaglerPlayerData targetPlayerCon; - synchronized (voicePlayers) { - senderUUID = sender.getUniqueId(); - if (senderUUID.equals(player)) - return; // prevent duplicates - if (!voicePlayers.containsKey(senderUUID)) - return; - targetPlayerCon = voicePlayers.get(player); - if (targetPlayerCon == null) - return; - VoicePair newPair = new VoicePair(player, senderUUID); - if (voicePairs.contains(newPair)) - return; // already paired - ExpiringSet senderRequestSet = voiceRequests.get(senderUUID); - if (senderRequestSet == null) { - voiceRequests.put(senderUUID, senderRequestSet = new ExpiringSet<>(2000)); - } - if (!senderRequestSet.add(player)) { - return; - } - - // check if other has requested earlier - ExpiringSet theSet; - if ((theSet = voiceRequests.get(player)) != null && theSet.contains(senderUUID)) { - theSet.remove(senderUUID); - if (theSet.isEmpty()) - voiceRequests.remove(player); - senderRequestSet.remove(player); - if (senderRequestSet.isEmpty()) - voiceRequests.remove(senderUUID); - // send each other add data - voicePairs.add(newPair); - }else { - return; - } - } - if (targetPlayerCon.getEaglerProtocol().ver <= 3) { - targetPlayerCon.sendEaglerMessage(new SPacketVoiceSignalConnectV3EAG( - senderUUID.getMostSignificantBits(), senderUUID.getLeastSignificantBits(), false, false)); - } else { - targetPlayerCon.sendEaglerMessage(new SPacketVoiceSignalConnectV4EAG( - senderUUID.getMostSignificantBits(), senderUUID.getLeastSignificantBits(), false)); - } - if (sender.getEaglerProtocol().ver <= 3) { - sender.sendEaglerMessage(new SPacketVoiceSignalConnectV3EAG( - player.getMostSignificantBits(), player.getLeastSignificantBits(), false, true)); - } else { - sender.sendEaglerMessage(new SPacketVoiceSignalConnectV4EAG( - player.getMostSignificantBits(), player.getLeastSignificantBits(), true)); - } - } - - void handleVoiceSignalPacketTypeConnect(EaglerPlayerData sender) { - if(!sender.voiceConnectRateLimiter.rateLimit(VOICE_CONNECT_RATELIMIT)) { - return; - } - sender.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.ENABLED); - if(sender.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - sender.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_ENABLED); - } - UUID senderUuid = sender.getUniqueId(); - List lst; - synchronized (voicePlayers) { - if (voicePlayers.containsKey(senderUuid)) { - return; - } - boolean hasNoOtherPlayers = voicePlayers.isEmpty(); - voicePlayers.put(senderUuid, sender); - if (hasNoOtherPlayers) { - return; - } - lst = new ArrayList<>(voicePlayers.values()); - } - GameMessagePacket v3p = null; - GameMessagePacket v4p = null; - for (EaglerPlayerData handler : lst) { - if (handler.getEaglerProtocol().ver <= 3) { - handler.sendEaglerMessage( - v3p == null - ? (v3p = new SPacketVoiceSignalConnectV3EAG(senderUuid.getMostSignificantBits(), - senderUuid.getLeastSignificantBits(), true, false)) - : v3p); - } else { - handler.sendEaglerMessage( - v4p == null - ? (v4p = new SPacketVoiceSignalConnectAnnounceV4EAG(senderUuid.getMostSignificantBits(), - senderUuid.getLeastSignificantBits())) - : v4p); - } - } - Collection userDatas = new ArrayList<>(voicePlayers.size()); - for(EaglerPlayerData userCon : lst) { - UUID uuid = userCon.getUniqueId(); - userDatas.add(new SPacketVoiceSignalGlobalEAG.UserData(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), userCon.getName())); - } - GameMessagePacket packetToBroadcast = new SPacketVoiceSignalGlobalEAG(userDatas); - for (EaglerPlayerData userCon : lst) { - userCon.sendEaglerMessage(packetToBroadcast); - } - } - - void handleVoiceSignalPacketTypeICE(UUID player, byte[] str, EaglerPlayerData sender) { - EaglerPlayerData pass; - VoicePair pair = new VoicePair(player, sender.getUniqueId()); - synchronized (voicePlayers) { - pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; - } - if (pass != null) { - UUID uuid = sender.getUniqueId(); - pass.sendEaglerMessage( - new SPacketVoiceSignalICEEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); - } - } - - void handleVoiceSignalPacketTypeDesc(UUID player, byte[] str, EaglerPlayerData sender) { - EaglerPlayerData pass; - VoicePair pair = new VoicePair(player, sender.getUniqueId()); - synchronized (voicePlayers) { - pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; - } - if (pass != null) { - UUID uuid = sender.getUniqueId(); - pass.sendEaglerMessage( - new SPacketVoiceSignalDescEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); - } - } - - void handleVoiceSignalPacketTypeDisconnect(EaglerPlayerData sender) { - removeUser(sender.getUniqueId()); - } - - void handleVoiceSignalPacketTypeDisconnectPeer(UUID player, EaglerPlayerData sender) { - List peersToDisconnect = new ArrayList<>(); - synchronized (voicePlayers) { - if (!voicePlayers.containsKey(player)) { - return; - } - Iterator pairsItr = voicePairs.iterator(); - while (pairsItr.hasNext()) { - VoicePair voicePair = pairsItr.next(); - UUID target = null; - if (voicePair.uuid1.equals(player)) { - target = voicePair.uuid2; - } else if (voicePair.uuid2.equals(player)) { - target = voicePair.uuid1; - } - if (target != null) { - pairsItr.remove(); - final EaglerPlayerData conn = voicePlayers.get(target); - final UUID target2 = target; - peersToDisconnect.add(() -> { - if (conn != null) { - conn.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG(player.getMostSignificantBits(), - player.getLeastSignificantBits())); - } - sender.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG(target2.getMostSignificantBits(), - target2.getLeastSignificantBits())); - }); - } - } - } - for(Runnable r : peersToDisconnect) { - r.run(); - } - } - - public void removeUser(final UUID user) { - List peersToDisconnect; - synchronized (voicePlayers) { - final EaglerPlayerData connRemove; - if ((connRemove = voicePlayers.remove(user)) == null) { - return; - } - peersToDisconnect = new ArrayList<>(); - if(connRemove != null){ - peersToDisconnect.add(() -> { - connRemove.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.DISABLED); - if(connRemove.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - connRemove.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_DISABLED); - } - }); - } - voiceRequests.remove(user); - if (voicePlayers.size() > 0) { - Collection userDatas = new ArrayList<>(voicePlayers.size()); - for(EaglerPlayerData userCon : voicePlayers.values()) { - UUID uuid = userCon.getUniqueId(); - userDatas.add(new SPacketVoiceSignalGlobalEAG.UserData(uuid.getMostSignificantBits(), - uuid.getLeastSignificantBits(), userCon.getName())); - } - final GameMessagePacket voicePlayersPkt = new SPacketVoiceSignalGlobalEAG(userDatas); - for (final EaglerPlayerData userCon : voicePlayers.values()) { - if (!user.equals(userCon.getUniqueId())) { - peersToDisconnect.add(() -> { - userCon.sendEaglerMessage(voicePlayersPkt); - }); - } - } - } - Iterator pairsItr = voicePairs.iterator(); - while (pairsItr.hasNext()) { - VoicePair voicePair = pairsItr.next(); - UUID target = null; - if (voicePair.uuid1.equals(user)) { - target = voicePair.uuid2; - } else if (voicePair.uuid2.equals(user)) { - target = voicePair.uuid1; - } - if (target != null) { - pairsItr.remove(); - if (voicePlayers.size() > 0) { - final EaglerPlayerData conn = voicePlayers.get(target); - if (conn != null) { - peersToDisconnect.add(() -> { - conn.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG( - user.getMostSignificantBits(), user.getLeastSignificantBits())); - }); - } - } - } - } - } - for(Runnable r : peersToDisconnect) { - r.run(); - } - } - - EnumVoiceState getPlayerVoiceState(UUID uniqueId) { - synchronized (voicePlayers) { - if(voicePlayers.containsKey(uniqueId)) { - return EnumVoiceState.ENABLED; - } - } - return EnumVoiceState.DISABLED; - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceService.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceService.java deleted file mode 100644 index b2917c51..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceService.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import com.velocitypowered.api.proxy.server.RegisteredServer; -import com.velocitypowered.api.proxy.server.ServerInfo; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.SPacketRPCEventToggledVoice; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EnumVoiceState; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.EaglercraftVoiceStatusChangeEvent; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVelocityConfig; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol.EnumSubscribedEvent; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket; -import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalAllowedEAG; - -public class VoiceService { - - private final Map serverMap = new HashMap<>(); - private final GameMessagePacket disableVoicePacket; - - public VoiceService(EaglerVelocityConfig conf) { - this.disableVoicePacket = new SPacketVoiceSignalAllowedEAG(false, null); - String[] iceServers = conf.getICEServers().toArray(new String[conf.getICEServers().size()]); - SPacketVoiceSignalAllowedEAG iceServersPacket = new SPacketVoiceSignalAllowedEAG(true, iceServers); - Collection servers = EaglerXVelocity.proxy().getAllServers(); - for(RegisteredServer s : servers) { - ServerInfo inf = s.getServerInfo(); - if(!conf.getDisableVoiceOnServersSet().contains(inf.getName())) { - serverMap.put(inf.getName(), new VoiceServerImpl(inf, iceServersPacket)); - } - } - } - - public void handlePlayerLoggedIn(EaglerPlayerData player) { - - } - - public void handlePlayerLoggedOut(EaglerPlayerData player) { - for(VoiceServerImpl svr : serverMap.values()) { - svr.handlePlayerLoggedOut(player); - } - } - - public void handleServerConnected(EaglerPlayerData player, ServerInfo server) { - VoiceServerImpl svr = serverMap.get(server.getName()); - if(svr != null) { - svr.handlePlayerLoggedIn(player); - }else { - player.sendEaglerMessage(disableVoicePacket); - player.fireVoiceStateChange(EaglercraftVoiceStatusChangeEvent.EnumVoiceState.SERVER_DISABLE); - if(player.getRPCEventSubscribed(EnumSubscribedEvent.TOGGLE_VOICE)) { - player.getRPCSessionHandler().handleVoiceStateTransition(SPacketRPCEventToggledVoice.VOICE_STATE_SERVER_DISABLE); - } - } - } - - public void handleServerDisconnected(EaglerPlayerData player, ServerInfo server) { - VoiceServerImpl svr = serverMap.get(server.getName()); - if(svr != null) { - svr.handlePlayerLoggedOut(player); - } - } - - public void handleVoiceSignalPacketTypeRequest(UUID player, EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeRequest(player, sender); - } - } - } - - public void handleVoiceSignalPacketTypeConnect(EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeConnect(sender); - } - } - } - - public void handleVoiceSignalPacketTypeICE(UUID player, byte[] str, EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeICE(player, str, sender); - } - } - } - - public void handleVoiceSignalPacketTypeDesc(UUID player, byte[] str, EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDesc(player, str, sender); - } - } - } - - public void handleVoiceSignalPacketTypeDisconnect(EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDisconnect(sender); - } - } - } - - public void handleVoiceSignalPacketTypeDisconnectPeer(UUID player, EaglerPlayerData sender) { - if(sender.getConnectedServer() != null) { - VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); - if(svr != null) { - svr.handleVoiceSignalPacketTypeDisconnectPeer(player, sender); - } - } - } - - public EnumVoiceState getPlayerVoiceState(UUID player, ServerInfo info) { - VoiceServerImpl svr = serverMap.get(info.getName()); - if(svr != null) { - return svr.getPlayerVoiceState(player); - }else { - return EnumVoiceState.SERVER_DISABLE; - } - } - -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_authservice.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_authservice.yml deleted file mode 100644 index cdaa330f..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_authservice.yml +++ /dev/null @@ -1,17 +0,0 @@ -enable_authentication_system: true -use_onboard_eaglerx_system: true -auth_db_uri: 'jdbc:sqlite:eaglercraft_auths.db' -sql_driver_class: 'internal' -sql_driver_path: 'internal' -password_prompt_screen_text: 'Enter your password to join:' -wrong_password_screen_text: 'Password Incorrect!' -not_registered_screen_text: 'You are not registered on this server!' -eagler_command_name: 'eagler' -use_register_command_text: '&aUse /eagler to set an Eaglercraft password on this account' -use_change_command_text: '&bUse /eagler to change your Eaglercraft password' -command_success_text: '&bYour eagler password was changed successfully.' -last_eagler_login_message: 'Your last Eaglercraft login was on $date from $ip' -too_many_registrations_message: '&cThe maximum number of registrations has been reached for your IP address' -need_vanilla_to_register_message: '&cYou need to log in with a vanilla account to use this command' -override_eagler_to_vanilla_skins: false -max_registration_per_ip: -1 \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_http_mime_types.json b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_http_mime_types.json deleted file mode 100644 index 38458bdd..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_http_mime_types.json +++ /dev/null @@ -1,180 +0,0 @@ -{ - "text/html": { - "files": [ "html", "htm", "shtml" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/javascript": { - "files": [ "js" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/octet-stream": { - "files": [ "epk" ], - "expires": 14400 - }, - "text/css": { - "files": [ "css" ], - "expires": 14400, - "charset": "utf-8" - }, - "text/xml": { - "files": [ "xml" ], - "expires": 3600, - "charset": "utf-8" - }, - "text/plain": { - "files": [ "txt" ], - "expires": 3600, - "charset": "utf-8" - }, - "image/png": { - "files": [ "png" ], - "expires": 14400 - }, - "image/jpeg": { - "files": [ "jpeg", "jpg", "jfif" ], - "expires": 14400 - }, - "image/gif": { - "files": [ "gif" ], - "expires": 14400 - }, - "image/webp": { - "files": [ "webp" ], - "expires": 14400 - }, - "image/svg+xml": { - "files": [ "svg", "svgz" ], - "expires": 14400, - "charset": "utf-8" - }, - "image/tiff": { - "files": [ "tiff", "tif" ], - "expires": 14400 - }, - "image/avif": { - "files": [ "avif" ], - "expires": 14400 - }, - "image/x-ms-bmp": { - "files": [ "bmp" ], - "expires": 14400 - }, - "image/x-icon": { - "files": [ "ico" ], - "expires": 14400 - }, - "image/woff": { - "files": [ "woff" ], - "expires": 43200 - }, - "image/woff2": { - "files": [ "woff2" ], - "expires": 43200 - }, - "application/json": { - "files": [ "json" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/pdf": { - "files": [ "pdf" ], - "expires": 14400 - }, - "application/rtf": { - "files": [ "rtf" ], - "expires": 14400 - }, - "application/java-archive": { - "files": [ "jar", "war", "ear" ], - "expires": 14400 - }, - "application/wasm": { - "files": [ "wasm" ], - "expires": 3600 - }, - "application/xhtml+xml": { - "files": [ "xhtml" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/zip": { - "files": [ "zip" ], - "expires": 14400 - }, - "audio/midi": { - "files": [ "mid", "midi", "kar" ], - "expires": 43200 - }, - "audio/mpeg": { - "files": [ "mp3" ], - "expires": 43200 - }, - "audio/ogg": { - "files": [ "ogg" ], - "expires": 43200 - }, - "audio/x-m4a": { - "files": [ "m4a" ], - "expires": 43200 - }, - "application/atom+xml": { - "files": [ "atom" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/rss+xml": { - "files": [ "rss" ], - "expires": 3600, - "charset": "utf-8" - }, - "application/x-shockwave-flash": { - "files": [ "swf" ], - "expires": 43200 - }, - "video/3gpp": { - "files": [ "3gpp", "3gp" ], - "expires": 43200 - }, - "video/mp4": { - "files": [ "mp4" ], - "expires": 43200 - }, - "video/mpeg": { - "files": [ "mpeg", "mpg" ], - "expires": 43200 - }, - "video/quicktime": { - "files": [ "mov" ], - "expires": 43200 - }, - "video/webm": { - "files": [ "webm" ], - "expires": 43200 - }, - "video/x-motion-jpeg": { - "files": [ "mjpg" ], - "expires": 14400 - }, - "video/x-flv": { - "files": [ "flv" ], - "expires": 43200 - }, - "video/x-m4v": { - "files": [ "m4v" ], - "expires": 43200 - }, - "video/x-mng": { - "files": [ "3mng" ], - "expires": 43200 - }, - "video/x-ms-wmv": { - "files": [ "wmv" ], - "expires": 43200 - }, - "video/x-msvideo": { - "files": [ "avi" ], - "expires": 43200 - } -} \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_ice_servers.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_ice_servers.yml deleted file mode 100644 index c771aa10..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_ice_servers.yml +++ /dev/null @@ -1,20 +0,0 @@ -voice_servers_no_passwd: -- 'stun:stun.l.google.com:19302' -- 'stun:stun1.l.google.com:19302' -- 'stun:stun2.l.google.com:19302' -- 'stun:stun3.l.google.com:19302' -- 'stun:stun4.l.google.com:19302' -- 'stun:openrelay.metered.ca:80' -voice_servers_passwd: - openrelay1: - url: 'turn:openrelay.metered.ca:80' - username: 'openrelayproject' - password: 'openrelayproject' - openrelay2: - url: 'turn:openrelay.metered.ca:443' - username: 'openrelayproject' - password: 'openrelayproject' - openrelay3: - url: 'turn:openrelay.metered.ca:443?transport=tcp' - username: 'openrelayproject' - password: 'openrelayproject' \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_listeners.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_listeners.yml deleted file mode 100644 index 4d505a7d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_listeners.yml +++ /dev/null @@ -1,70 +0,0 @@ -listener_01: - address: 0.0.0.0:8081 - address_v6: 'null' - max_players: 60 - forward_ip: false - forward_ip_header: X-Real-IP - redirect_legacy_clients_to: 'null' - server_icon: server-icon.png - server_motd: - - '&6An EaglercraftX server' - allow_motd: true - allow_query: true - min_minecraft_protocol: 47 - max_minecraft_protocol: 340 - allow_protocol_v3: true - allow_protocol_v4: true - protocol_v4_defrag_send_delay: 10 - use_haproxy_protocol: false - allow_cookie_revoke_query: true - request_motd_cache: - cache_ttl: 7200 - online_server_list_animation: false - online_server_list_results: true - online_server_list_trending: true - online_server_list_portfolios: false - http_server: - enabled: false - root: 'web' - page_404_not_found: 'default' - page_index_name: - - 'index.html' - - 'index.htm' - allow_voice: false - ratelimit: - ip: - enable: true - period: 90 - limit: 60 - limit_lockout: 80 - lockout_duration: 1200 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - login: - enable: true - period: 50 - limit: 5 - limit_lockout: 10 - lockout_duration: 300 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - motd: - enable: true - period: 30 - limit: 5 - limit_lockout: 15 - lockout_duration: 300 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' - query: - enable: true - period: 30 - limit: 15 - limit_lockout: 25 - lockout_duration: 900 - exceptions: - - '127.*' - - '0:0:0:0:0:0:0:1' \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_example.html b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_example.html deleted file mode 100644 index ce854a05..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_example.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - -Eaglercraft Server - - - - - -

    Message API Test

    -

    Server Version: {% global `plugin_name` %} {% global `plugin_version` %}

    -

    Make sure you enable javascript in "pause_menu.yml"

    -

    Message:

    -

    Recieved from server:

    -
      - - \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_v1.js b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_v1.js deleted file mode 100644 index 95e20d72..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_v1.js +++ /dev/null @@ -1,63 +0,0 @@ -"use strict"; -window.serverMessageAPI = (function() { - var channelOpen = null; - var messageHandlers = []; - window.addEventListener("message", function(evt) { - var dat = evt.data; - if((typeof dat === "object") && dat.ver === 1 && (typeof dat.type === "string") && (typeof dat.channel === "string") && dat.channel.length > 0) { - for(var i = 0; i < messageHandlers.length; ++i) { - messageHandlers[i](dat); - } - } - }); - var ServerMessageAPIError = function(message) { - this.name = "ServerMessageAPIError"; - this.message = message; - }; - ServerMessageAPIError.prototype = Error.prototype; - var openCh = function(chName) { - if(channelOpen !== null) throw new ServerMessageAPIError("Cannot open multiple channels, this feature is not supported!"); - channelOpen = chName; - window.parent.postMessage({ver:1,channel:chName,open:true}, "*"); - }; - var closeCh = function(chName) { - if(channelOpen !== chName) throw new ServerMessageAPIError("Cannot close channel \"" + chName + "\", that channel is not open!"); - channelOpen = null; - window.parent.postMessage({ver:1,channel:chName,open:false}, "*"); - }; - var addListener = function(name, handler) { - if(name === "message") messageHandlers.push(handler); - }; - var remListener = function(name, handler) { - if(name === "message") messageHandlers = messageHandlers.filter(function(o) { return o !== handler; }); - }; - var fixTypedArray = function(arr) { - if(arr.length === arr.buffer.byteLength) { - return arr.buffer; - }else { - var toSend = (data instanceof Uint8Array) ? new Uint8Array(arr.length) : new Int8Array(arr.length); - toSend.set(arr); - return toSend.buffer; - } - }; - var send = function(chName, data) { - if(channelOpen !== chName) throw new ServerMessageAPIError("Cannot send message on channel \"" + chName + "\", that channel is not open!"); - if(typeof data === "string") { - window.parent.postMessage({ver:1,channel:chName,data:data}, "*"); - }else if(data instanceof ArrayBuffer) { - window.parent.postMessage({ver:1,channel:chName,data:data}, "*"); - }else if((data instanceof Uint8Array) || (data instanceof Int8Array)) { - window.parent.postMessage({ver:1,channel:chName,data:fixTypedArray(data)}, "*"); - }else { - throw new ServerMessageAPIError("Only strings, ArrayBuffers, Uint8Arrays, and Int8Arrays can be sent with this function!"); - } - }; - return { - ServerMessageAPIError: ServerMessageAPIError, - openChannel: openCh, - closeChannel: closeCh, - addEventListener: addListener, - removeEventListener: remListener, - send: send - }; -})(); diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu.yml deleted file mode 100644 index 9042249d..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu.yml +++ /dev/null @@ -1,43 +0,0 @@ -enable_custom_pause_menu: false -server_info_button: - enable_button: true - button_text: 'Server Info' - button_mode_open_new_tab: false - server_info_embed_url: '' - button_mode_embed_file: true - server_info_embed_file: 'server_info.html' - server_info_embed_screen_title: 'Server Info' - server_info_embed_send_chunk_rate: 1 - server_info_embed_send_chunk_size: 24576 - enable_template_macros: true - server_info_embed_template_globals: - example_global: 'eagler' - allow_embed_template_eval_macro: false - enable_webview_javascript: false - enable_webview_message_api: false - enable_webview_strict_csp: true -discord_button: - enable_button: true - button_text: 'Discord' - button_url: 'https://invite url here' -custom_images: - icon_title_L: '' - icon_title_R: '' - icon_backToGame_L: '' - icon_backToGame_R: '' - icon_achievements_L: '' - icon_achievements_R: '' - icon_statistics_L: '' - icon_statistics_R: '' - icon_serverInfo_L: '' - icon_serverInfo_R: '' - icon_options_L: '' - icon_options_R: '' - icon_discord_L: '' - icon_discord_R: '' - icon_disconnect_L: '' - icon_disconnect_R: '' - icon_background_pause: 'test_image.png' - icon_background_all: 'test_image.png' - icon_watermark_pause: '' - icon_watermark_all: '' \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_server_info.html b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_server_info.html deleted file mode 100644 index ee7077aa..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_server_info.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - -Eaglercraft Server - - - - -

      Hello World

      - -{% htmlescape on %} -

      Server Name: {% global `server_name` %}

      -

      Using: {% global `plugin_name` %} {% global `plugin_version` %}

      -

      JVM: {% property `java.vm.name` `(unknown)` %} ({% property `java.vm.info` `null` %}) {% property `java.vm.vendor` `(unknown)` %}

      -{% htmlescape off %} - -

      - - - - - - \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_test_image.png b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_test_image.png deleted file mode 100644 index 9c9fc898..00000000 Binary files a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_test_image.png and /dev/null differ diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_settings.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_settings.yml deleted file mode 100644 index 99c36e1b..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_settings.yml +++ /dev/null @@ -1,28 +0,0 @@ -server_name: 'EaglercraftXVelocity Server' -server_uuid: ${random_uuid} -websocket_connection_timeout: 15000 -websocket_handshake_timeout: 5000 -builtin_http_server_timeout: 10000 -http_websocket_compression_level: 6 -download_vanilla_skins_to_clients: true -valid_skin_download_urls: - - 'textures.minecraft.net' -uuid_lookup_ratelimit_player: 50 -uuid_lookup_ratelimit_global: 175 -skin_download_ratelimit_player: 1000 -skin_download_ratelimit_global: 30000 -skin_cache_db_uri: 'jdbc:sqlite:eaglercraft_skins_cache.db' -skin_cache_keep_objects_days: 45 -skin_cache_keep_profiles_days: 7 -skin_cache_max_objects: 32768 -skin_cache_max_profiles: 32768 -skin_cache_antagonists_ratelimit: 15 -sql_driver_class: 'internal' -sql_driver_path: 'internal' -eagler_players_vanilla_skin: '' -enable_is_eagler_player_property: true -disable_voice_chat_on_servers: [] -disable_fnaw_skins_everywhere: false -disable_fnaw_skins_on_servers: [] -enable_backend_rpc_api: false -use_modernized_channel_names: false \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_updates.yml b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_updates.yml deleted file mode 100644 index d341cec4..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_updates.yml +++ /dev/null @@ -1,9 +0,0 @@ -block_all_client_updates: false -discard_login_packet_certs: false -cert_packet_data_rate_limit: 524288 -enable_eagcert_folder: true -download_latest_certs: true -download_certs_from: -- 'https://eaglercraft.com/backup.cert' -- 'https://deev.is/eagler/backup.cert' -check_for_update_every: 28800 \ No newline at end of file diff --git a/gateway/EaglercraftXVelocity/src/main/resources/velocity-plugin.json b/gateway/EaglercraftXVelocity/src/main/resources/velocity-plugin.json deleted file mode 100644 index 0aaa0c74..00000000 --- a/gateway/EaglercraftXVelocity/src/main/resources/velocity-plugin.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"eaglerxvelocity","name":"EaglercraftXVelocity","version":"1.1.7","description":"Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks","authors":["lax1dude", "ayunami2000"],"dependencies":[],"main":"net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity"} \ No newline at end of file diff --git a/gateway/PlaceholderServer/Java-WebSocket-1.5.1-with-dependencies.jar b/gateway/PlaceholderServer/Java-WebSocket-1.5.1-with-dependencies.jar deleted file mode 100644 index 8f103a76..00000000 Binary files a/gateway/PlaceholderServer/Java-WebSocket-1.5.1-with-dependencies.jar and /dev/null differ diff --git a/gateway/PlaceholderServer/PlaceholderServer-Latest.jar b/gateway/PlaceholderServer/PlaceholderServer-Latest.jar deleted file mode 100644 index ec68b8bf..00000000 Binary files a/gateway/PlaceholderServer/PlaceholderServer-Latest.jar and /dev/null differ diff --git a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/DummyConnection.java b/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/DummyConnection.java deleted file mode 100644 index 6d059f3b..00000000 --- a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/DummyConnection.java +++ /dev/null @@ -1,112 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.placeholder_server; - -import java.nio.ByteBuffer; - -import org.java_websocket.WebSocket; -import org.json.JSONArray; -import org.json.JSONObject; - -/** - * Copyright (c) 2022 LAX1DUDE. All Rights Reserved. - * - * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES - * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED - * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE - * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. - * - * NOT FOR COMMERCIAL OR MALICIOUS USE - * - * (please read the 'LICENSE' file this repo's root directory for more info) - * - */ -public class DummyConnection { - - public final long age; - public long sendRedirectAt = 0l; - public final WebSocket sock; - - private boolean hasFirstPacket = false; - - public DummyConnection(WebSocket sock) { - this.age = System.currentTimeMillis(); - this.sock = sock; - } - - public void processString(String str) { - if(!hasFirstPacket) { - hasFirstPacket = true; - str = str.toLowerCase(); - if(str.startsWith("accept:")) { - str = str.substring(7).trim(); - if(str.startsWith("motd")) { - String subType = "motd"; - int i = str.indexOf('.'); - if(i > 0 && i != str.length() - 1) { - subType = str.substring(i + 1); - } - JSONObject json = new JSONObject(); - json.put("name", PlaceholderServerConfig.serverName); - json.put("brand", "lax1dude"); - json.put("vers", "EaglerXPlaceholder/1.0"); - json.put("cracked", true); - json.put("secure", false); - json.put("time", System.currentTimeMillis()); - json.put("uuid", PlaceholderServerConfig.serverUUID); - json.put("type", str); - JSONObject motdData = new JSONObject(); - boolean icon = false; - if(subType.startsWith("cache.anim")) { - motdData.put("unsupported", true); - }else { - if(subType.startsWith("cache")) { - JSONArray arr = new JSONArray(); - arr.put("animation"); - arr.put("results"); - arr.put("trending"); - arr.put("portfolio"); - motdData.put("cache", arr); - motdData.put("ttl", 7200); - }else { - motdData.put("cache", true); - } - JSONArray motdLines = new JSONArray(); - String motd1 = PlaceholderServerConfig.motd1; - String motd2 = PlaceholderServerConfig.motd2; - if(motd1 != null && motd1.length() > 0) motdLines.put(motd1); - if(motd2 != null && motd2.length() > 0) motdLines.put(motd2); - motdData.put("motd", motdLines); - icon = PlaceholderServerConfig.cachedIconPacket != null && !subType.startsWith("noicon") - && !subType.startsWith("cache.noicon"); - motdData.put("icon", icon); - motdData.put("online", 0); - motdData.put("max", 0); - motdData.put("players", new JSONArray()); - } - json.put("data", motdData); - sock.send(json.toString()); - if(icon) { - sock.send(PlaceholderServerConfig.cachedIconPacket); - } - } - } - sock.close(); - } - } - - public void processBinary(ByteBuffer bin) { - if(!hasFirstPacket) { - hasFirstPacket = true; - if(bin.remaining() > 2) { - if(bin.get(0) == (byte)2 && bin.get(1) == (byte)69) { - sock.send(PlaceholderServerConfig.cachedLegacyKickRedirectPacket); - sendRedirectAt = System.currentTimeMillis(); - return; - }else if(bin.get(0) == (byte)1) { - sock.send(PlaceholderServerConfig.cachedKickPacket); - } - } - sock.close(); - } - } - -} diff --git a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServer.java b/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServer.java deleted file mode 100644 index 6153725f..00000000 --- a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServer.java +++ /dev/null @@ -1,121 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.placeholder_server; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; - -import org.java_websocket.WebSocket; -import org.java_websocket.handshake.ClientHandshake; -import org.java_websocket.server.WebSocketServer; - -/** - * Copyright (c) 2022 LAX1DUDE. All Rights Reserved. - * - * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES - * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED - * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE - * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. - * - * NOT FOR COMMERCIAL OR MALICIOUS USE - * - * (please read the 'LICENSE' file this repo's root directory for more info) - * - */ -public class PlaceholderServer extends WebSocketServer { - - public static PlaceholderServer websocketServer = null; - private boolean isOpen = false; - - public static void main(String[] args) throws IOException { - System.out.println(); - System.out.println("Copyright (c) 2022 lax1dude"); - System.out.println("All rights reserved."); - System.out.println(); - System.out.println("Starting placeholder 1.8 server..."); - System.out.println(); - - PlaceholderServerConfig.load(); - - System.out.println("Starting WebSocket server..."); - System.out.println(); - websocketServer = new PlaceholderServer(new InetSocketAddress(PlaceholderServerConfig.host, PlaceholderServerConfig.port)); - websocketServer.start(); - - long redirTimeout = (PlaceholderServerConfig.redirect != null && PlaceholderServerConfig.redirect.length() > 0) ? 500l : 100l; - while(true) { - try { - Thread.sleep(200l); - long millis = System.currentTimeMillis(); - for(WebSocket ws : websocketServer.getConnections()) { - DummyConnection conn = ws.getAttachment(); - if (conn != null && ((conn.sendRedirectAt > 0l && millis - conn.sendRedirectAt > redirTimeout) - || millis - conn.age > (long) PlaceholderServerConfig.clientTimeout)) { - ws.close(); - } - } - } catch (Throwable t) { - } - } - } - - private PlaceholderServer(InetSocketAddress addr) { - super(addr); - setReuseAddr(true); - setTcpNoDelay(true); - } - - @Override - public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) { - } - - @Override - public void onError(WebSocket arg0, Exception arg1) { - System.err.println(); - if(arg0 != null) { - System.err.println("Caught WebSocket exception on " + arg0.getRemoteSocketAddress() + "!"); - arg0.close(); - }else { - System.err.println("Caught WebSocket exception!"); - } - arg1.printStackTrace(); - if(!isOpen) { - System.exit(-1); - } - } - - @Override - public void onMessage(WebSocket arg0, String arg1) { - ((DummyConnection)arg0.getAttachment()).processString(arg1); - } - - @Override - public void onMessage(WebSocket arg0, ByteBuffer arg1) { - ((DummyConnection)arg0.getAttachment()).processBinary(arg1); - } - - @Override - public void onOpen(WebSocket arg0, ClientHandshake arg1) { - arg0.setAttachment(new DummyConnection(arg0)); - } - - @Override - public void onStart() { - System.out.println(); - System.out.println("Listening on: " + getAddress()); - isOpen = true; - - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - @Override - public void run() { - try { - PlaceholderServer.this.stop(); - } catch (Throwable t) { - t.printStackTrace(); - } - } - }, "Shutdown Thread")); - - System.out.println("Use CTRL+C to exit"); - } - -} diff --git a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServerConfig.java b/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServerConfig.java deleted file mode 100644 index 9b48cbe4..00000000 --- a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/PlaceholderServerConfig.java +++ /dev/null @@ -1,180 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.placeholder_server; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -import org.json.JSONArray; -import org.json.JSONObject; - -/** - * Copyright (c) 2022 LAX1DUDE. All Rights Reserved. - * - * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES - * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED - * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE - * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. - * - * NOT FOR COMMERCIAL OR MALICIOUS USE - * - * (please read the 'LICENSE' file this repo's root directory for more info) - * - */ -public class PlaceholderServerConfig { - - public static final File configFile = new File("config.json"); - - public static String host = "0.0.0.0"; - public static int port = 8081; - public static String icon = null; - public static String serverName = "EaglercraftX 1.8 Server"; - public static String serverUUID = ""; - public static int clientTimeout = 3000; - public static String motd1 = "Coming Soon"; - public static String motd2 = ""; - public static String kick = "This server is still under construction"; - public static String redirect = ""; - - public static byte[] cachedIconPacket = null; - public static byte[] cachedLegacyKickRedirectPacket = null; - public static byte[] cachedKickPacket = null; - - public static void load() throws IOException { - if(!configFile.exists()) { - System.out.println("Writing new config file to: " + configFile.getName()); - int i; - try(Reader is = new InputStreamReader(PlaceholderServerConfig.class.getResourceAsStream("/config_default.json")); - OutputStream os = new FileOutputStream(configFile)) { - char[] copyBuffer = new char[1024]; - StringBuilder sb = new StringBuilder(); - while((i = is.read(copyBuffer)) != -1) { - sb.append(copyBuffer, 0, i); - } - String str = sb.toString(); - str = str.replace("${random_uuid}", UUID.randomUUID().toString()); - os.write(str.getBytes(StandardCharsets.UTF_8)); - } - try(InputStream is = PlaceholderServerConfig.class.getResourceAsStream("/server-icon_default.png"); - OutputStream os = new FileOutputStream(new File("server-icon.png"))) { - byte[] copyBuffer = new byte[1024]; - while((i = is.read(copyBuffer)) != -1) { - os.write(copyBuffer, 0, i); - } - } - } - - System.out.println("Reading config file: " + configFile.getName()); - byte[] fileBytes = new byte[(int)configFile.length()]; - try(InputStream is = new FileInputStream(configFile)) { - int i = 0, j; - while(i < fileBytes.length && (j = is.read(fileBytes, i, fileBytes.length - i)) != -1) { - i += j; - } - } - - try { - JSONObject loaded = new JSONObject(new String(fileBytes, StandardCharsets.UTF_8)); - host = loaded.getString("server_host"); - port = loaded.getInt("server_port"); - icon = loaded.getString("server_icon"); - serverName = loaded.getString("server_name"); - serverUUID = loaded.getString("server_uuid"); - clientTimeout = loaded.getInt("client_timeout"); - JSONArray motd = loaded.getJSONArray("server_motd"); - motd1 = motd.getString(0); - if(motd.length() > 1) { - motd2 = motd.getString(1); - } - kick = loaded.getString("kick_message"); - if(kick.length() > 255) { - kick = kick.substring(0, 255); - System.err.println("Warning: kick message was truncated to 255 characters"); - } - redirect = loaded.optString("redirect_legacy", null); - }catch(Throwable t) { - throw new IOException("Could not load config file \"" + configFile.getAbsolutePath() + "\"!", t); - } - - cacheKickPacket(); - cacheRedirectPacket(); - - if(icon != null && icon.length() > 0) { - cacheIconPacket(); - } - } - - private static void cacheKickPacket() throws IOException { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bao); - dos.writeByte(0xFF); - dos.writeByte(0x08); - dos.writeByte(kick.length()); - for(int i = 0, l = kick.length(); i < l; ++i) { - dos.writeByte(kick.charAt(i) & 0xFF); - } - cachedKickPacket = bao.toByteArray(); - } - - private static void cacheRedirectPacket() throws IOException { - ByteArrayOutputStream bao = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bao); - if(redirect == null || redirect.length() == 0) { - String message = "This is an EaglercraftX 1.8 server, it is not compatible with 1.5.2!"; - dos.writeByte(0xFF); - dos.writeShort(message.length()); - for(int i = 0, l = message.length(), j; i < l; ++i) { - j = message.charAt(i); - dos.writeByte((j >> 8) & 0xFF); - dos.writeByte(j & 0xFF); - } - }else { - // Packet1Login - dos.writeByte(0x01); - dos.writeInt(0); - dos.writeShort(0); - dos.writeByte(0); - dos.writeByte(0); - dos.writeByte(0xFF); - dos.writeByte(0); - dos.writeByte(0); - // Packet250CustomPayload - dos.writeByte(0xFA); - String channel = "EAG|Reconnect"; - int cl = channel.length(); - dos.writeShort(cl); - for(int i = 0; i < cl; ++i) { - dos.writeChar(channel.charAt(i)); - } - byte[] redirect_ = redirect.getBytes(StandardCharsets.UTF_8); - dos.writeShort(redirect_.length); - dos.write(redirect_); - } - cachedLegacyKickRedirectPacket = bao.toByteArray(); - } - - private static void cacheIconPacket() throws IOException { - File f = new File(icon); - int[] iconPixels = ServerIconLoader.createServerIcon(f); - if(iconPixels != null) { - cachedIconPacket = new byte[16384]; - for(int i = 0, j; i < 4096; ++i) { - j = i << 2; - cachedIconPacket[j] = (byte)((iconPixels[i] >> 16) & 0xFF); - cachedIconPacket[j + 1] = (byte)((iconPixels[i] >> 8) & 0xFF); - cachedIconPacket[j + 2] = (byte)(iconPixels[i] & 0xFF); - cachedIconPacket[j + 3] = (byte)((iconPixels[i] >> 24) & 0xFF); - } - }else { - System.err.println("Could not load server icon \"" + f.getAbsolutePath() + "\"!"); - } - } -} diff --git a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/ServerIconLoader.java b/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/ServerIconLoader.java deleted file mode 100644 index 5c698ad7..00000000 --- a/gateway/PlaceholderServer/src/main/java/net/lax1dude/eaglercraft/v1_8/placeholder_server/ServerIconLoader.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.placeholder_server; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -/** - * Copyright (c) 2022 LAX1DUDE. All Rights Reserved. - * - * WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES - * NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED - * TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE - * SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR. - * - * NOT FOR COMMERCIAL OR MALICIOUS USE - * - * (please read the 'LICENSE' file this repo's root directory for more info) - * - */ -class ServerIconLoader { - - static int[] createServerIcon(BufferedImage awtIcon) { - BufferedImage icon = awtIcon; - boolean gotScaled = false; - if(icon.getWidth() != 64 || icon.getHeight() != 64) { - icon = new BufferedImage(64, 64, awtIcon.getType()); - Graphics2D g = (Graphics2D) icon.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ? - RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC); - g.setBackground(new Color(0, true)); - g.clearRect(0, 0, 64, 64); - int ow = awtIcon.getWidth(); - int oh = awtIcon.getHeight(); - int nw, nh; - float aspectRatio = (float)oh / (float)ow; - if(aspectRatio >= 1.0f) { - nw = (int)(64 / aspectRatio); - nh = 64; - }else { - nw = 64; - nh = (int)(64 * aspectRatio); - } - g.drawImage(awtIcon, (64 - nw) / 2, (64 - nh) / 2, (64 - nw) / 2 + nw, (64 - nh) / 2 + nh, 0, 0, awtIcon.getWidth(), awtIcon.getHeight(), null); - g.dispose(); - gotScaled = true; - } - int[] pxls = icon.getRGB(0, 0, 64, 64, new int[4096], 0, 64); - if(gotScaled) { - for(int i = 0; i < pxls.length; ++i) { - if((pxls[i] & 0xFFFFFF) == 0) { - pxls[i] = 0; - } - } - } - return pxls; - } - - static int[] createServerIcon(InputStream f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - - static int[] createServerIcon(File f) { - try { - return createServerIcon(ImageIO.read(f)); - }catch(Throwable t) { - return null; - } - } - -} diff --git a/gateway/PlaceholderServer/src/main/resources/config_default.json b/gateway/PlaceholderServer/src/main/resources/config_default.json deleted file mode 100644 index b94378a5..00000000 --- a/gateway/PlaceholderServer/src/main/resources/config_default.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "server_host": "0.0.0.0", - "server_port": 8081, - "server_icon": "server-icon.png", - "server_motd": [ - "1.8 is still under construction" - ], - "server_name": "EaglercraftX 1.8 Server", - "server_uuid": "${random_uuid}", - "client_timeout": 3000, - "kick_message": "This EaglercraftX 1.8 server is still under construction!", - "redirect_legacy": null -} \ No newline at end of file diff --git a/gateway/PlaceholderServer/src/main/resources/server-icon_default.png b/gateway/PlaceholderServer/src/main/resources/server-icon_default.png deleted file mode 100644 index c9cd76d6..00000000 Binary files a/gateway/PlaceholderServer/src/main/resources/server-icon_default.png and /dev/null differ diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/EaglerBackendRPCProtocol.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/EaglerBackendRPCProtocol.java deleted file mode 100644 index e79051a0..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/EaglerBackendRPCProtocol.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.*; - -public enum EaglerBackendRPCProtocol { - INIT(0, - define_CLIENT_(0x00, CPacketRPCEnabled.class), - define_SERVER_(0x01, SPacketRPCEnabledSuccess.class), - define_SERVER_(0x02, SPacketRPCEnabledFailure.class) - ), V1(1, - define_CLIENT_(0x03, CPacketRPCDisabled.class), - define_CLIENT_(0x04, CPacketRPCRequestPlayerInfo.class), - define_CLIENT_(0x05, CPacketRPCSubscribeEvents.class), - define_CLIENT_(0x06, CPacketRPCSetPlayerSkin.class), - define_CLIENT_(0x07, CPacketRPCSetPlayerCape.class), - define_CLIENT_(0x08, CPacketRPCSetPlayerCookie.class), - define_CLIENT_(0x09, CPacketRPCSetPlayerFNAWEn.class), - define_CLIENT_(0x0A, CPacketRPCSetPauseMenuCustom.class), - define_CLIENT_(0x0B, CPacketRPCRedirectPlayer.class), - define_CLIENT_(0x0C, CPacketRPCResetPlayerMulti.class), - define_SERVER_(0x0D, SPacketRPCResponseTypeNull.class), - define_SERVER_(0x0E, SPacketRPCResponseTypeBytes.class), - define_SERVER_(0x0F, SPacketRPCResponseTypeString.class), - define_SERVER_(0x10, SPacketRPCResponseTypeUUID.class), - define_SERVER_(0x11, SPacketRPCResponseTypeCookie.class), - define_SERVER_(0x12, SPacketRPCResponseTypeVoiceStatus.class), - define_SERVER_(0x13, SPacketRPCResponseTypeWebViewStatus.class), - define_SERVER_(0x14, SPacketRPCResponseTypeError.class), - define_CLIENT_(0x15, CPacketRPCSendWebViewMessage.class), - define_SERVER_(0x16, SPacketRPCEventWebViewOpenClose.class), - define_SERVER_(0x17, SPacketRPCEventWebViewMessage.class), - define_SERVER_(0x18, SPacketRPCEventToggledVoice.class), - define_CLIENT_(0x19, CPacketRPCNotifIconRegister.class), - define_CLIENT_(0x1A, CPacketRPCNotifIconRelease.class), - define_CLIENT_(0x1B, CPacketRPCNotifBadgeShow.class), - define_CLIENT_(0x1C, CPacketRPCNotifBadgeHide.class), - define_CLIENT_(0x1D, CPacketRPCSendRawMessage.class) - ); - - public static final String CHANNEL_NAME = "EAG|1.8-RPC"; - public static final String CHANNEL_NAME_READY = "EAG|1.8-Ready"; - - public static final String CHANNEL_NAME_MODERN = "eagler:1-8-rpc"; - public static final String CHANNEL_NAME_READY_MODERN = "eagler:1-8-ready"; - - public static final int CLIENT_TO_SERVER = 0; - public static final int SERVER_TO_CLIENT = 1; - - public final int vers; - - private final PacketDef[] idMap = new PacketDef[32]; // May need to grow this in the future - private final Map, PacketDef> classMap = new HashMap<>(); - - private EaglerBackendRPCProtocol(int vers, PacketDef...pkts) { - this.vers = vers; - for(int i = 0; i < pkts.length; ++i) { - PacketDef def = pkts[i]; - if(idMap[def.id] != null) { - throw new IllegalArgumentException("Packet ID " + def.id + " registered twice!"); - } - idMap[def.id] = def; - if(classMap.put(def.pkt, def) != null) { - throw new IllegalArgumentException("Packet class " + def.pkt.getSimpleName() + " registered twice!"); - } - } - } - - private static PacketDef define_CLIENT_(int id, Class pkt) { - return new PacketDef(id, 0, pkt); - } - - private static PacketDef define_SERVER_(int id, Class pkt) { - return new PacketDef(id, 1, pkt); - } - - private static class PacketDef { - - private final int id; - private final int dir; - private final Class pkt; - - private PacketDef(int id, int dir, Class pkt) { - this.id = id; - this.dir = dir; - this.pkt = pkt; - } - - } - - public EaglerBackendRPCPacket readPacket(DataInput buffer, int dir) throws IOException { - int pktId = buffer.readUnsignedByte(); - if(pktId >= idMap.length) { - throw new IOException("Packet ID is out of range: 0x" + Integer.toHexString(pktId)); - } - PacketDef pp = idMap[pktId]; - if(pp == null || pp.dir != dir) { - throw new IOException("Unknown packet ID: 0x" + Integer.toHexString(pktId)); - } - EaglerBackendRPCPacket newPkt; - try { - newPkt = pp.pkt.newInstance(); - }catch(Throwable t) { - throw new RuntimeException("Reflection failed to call packet constructor for \"" + pp.pkt.getSimpleName() + "\"! (is it defined?)", t); - } - newPkt.readPacket(buffer); - return newPkt; - } - - public void writePacket(DataOutput buffer, int dir, EaglerBackendRPCPacket packet) throws IOException { - Class clazz = packet.getClass(); - PacketDef def = classMap.get(clazz); - if(def == null || def.dir != dir) { - throw new IOException("Unknown packet type or wrong direction: " + clazz); - } - buffer.writeByte(def.id); - packet.writePacket(buffer); - } - - public static EaglerBackendRPCProtocol getByID(int id) { - switch(id) { - case 0: return INIT; - case 1: return V1; - default: return null; - } - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCHandler.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCHandler.java deleted file mode 100644 index 53de99d4..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCHandler.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.*; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server.*; - -public interface EaglerBackendRPCHandler { - - default void handleClient(CPacketRPCEnabled packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCRequestPlayerInfo packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSubscribeEvents packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSetPlayerSkin packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSetPlayerCape packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSetPlayerCookie packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSetPlayerFNAWEn packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCRedirectPlayer packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCResetPlayerMulti packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSendWebViewMessage packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSetPauseMenuCustom packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCNotifIconRegister packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCNotifIconRelease packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCNotifBadgeShow packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCNotifBadgeHide packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCDisabled packet) { - throw new WrongRPCPacketException(); - } - - default void handleClient(CPacketRPCSendRawMessage packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCEnabledSuccess packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCEnabledFailure packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeNull packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeBytes packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeString packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeUUID packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeCookie packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeVoiceStatus packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeWebViewStatus packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCResponseTypeError packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCEventWebViewOpenClose packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCEventWebViewMessage packet) { - throw new WrongRPCPacketException(); - } - - default void handleServer(SPacketRPCEventToggledVoice packet) { - throw new WrongRPCPacketException(); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCPacket.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCPacket.java deleted file mode 100644 index 838a5882..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/EaglerBackendRPCPacket.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; - -public interface EaglerBackendRPCPacket { - - void readPacket(DataInput buffer) throws IOException; - - void writePacket(DataOutput buffer) throws IOException; - - void handlePacket(EaglerBackendRPCHandler handler); - - int length(); - - public static void writeString(DataOutput buffer, String str, boolean len16, Charset charset) throws IOException { - if(str == null || str.length() == 0) { - if(len16) { - buffer.writeShort(0); - }else { - buffer.writeByte(0); - } - return; - } - byte[] bytes = str.getBytes(charset); - if(bytes.length > (len16 ? 65535 : 255)) { - throw new IOException("String is too long!"); - } - if(len16) { - buffer.writeShort(bytes.length); - }else { - buffer.writeByte(bytes.length); - } - buffer.write(bytes); - } - - public static String readString(DataInput buffer, int maxLen, boolean len16, Charset charset) throws IOException { - int len = len16 ? buffer.readUnsignedShort() : buffer.readUnsignedByte(); - if(len > maxLen) { - throw new IOException("String is too long!"); - } - if(len == 0) { - return ""; - } - byte[] toRead = new byte[len]; - buffer.readFully(toRead); - String ret = new String(toRead, charset); - if(charset != StandardCharsets.US_ASCII && ret.length() > maxLen) { - throw new IOException("String is too long!"); - } - return ret; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/WrongRPCPacketException.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/WrongRPCPacketException.java deleted file mode 100644 index 63c491b5..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/WrongRPCPacketException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt; - -public class WrongRPCPacketException extends RuntimeException { - - public WrongRPCPacketException() { - super("Wrong RPC packet type recieved for the current handler!"); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCDisabled.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCDisabled.java deleted file mode 100644 index 2c72fbd2..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCDisabled.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCDisabled implements EaglerBackendRPCPacket { - - public CPacketRPCDisabled() { - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 0; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCEnabled.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCEnabled.java deleted file mode 100644 index a296323c..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCEnabled.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCEnabled implements EaglerBackendRPCPacket { - - public int[] supportedProtocols; - - public CPacketRPCEnabled() { - } - - public CPacketRPCEnabled(int[] supportedProtocols) { - this.supportedProtocols = supportedProtocols; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - supportedProtocols = new int[buffer.readUnsignedShort()]; - for(int i = 0; i < supportedProtocols.length; ++i) { - supportedProtocols[i] = buffer.readUnsignedShort(); - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeShort(supportedProtocols.length); - for(int i = 0; i < supportedProtocols.length; ++i) { - buffer.writeShort(supportedProtocols[i]); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 2 + supportedProtocols.length * 2; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeHide.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeHide.java deleted file mode 100644 index b8e0239c..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeHide.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCNotifBadgeHide implements EaglerBackendRPCPacket { - - public UUID badgeUUID; - - public CPacketRPCNotifBadgeHide() { - } - - public CPacketRPCNotifBadgeHide(UUID badgeUUID) { - this.badgeUUID = badgeUUID; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - badgeUUID = new UUID(buffer.readLong(), buffer.readLong()); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeLong(badgeUUID.getMostSignificantBits()); - buffer.writeLong(badgeUUID.getLeastSignificantBits()); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 16; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeShow.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeShow.java deleted file mode 100644 index c09b8f12..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifBadgeShow.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.readString; -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.writeString; - -public class CPacketRPCNotifBadgeShow implements EaglerBackendRPCPacket { - - public static enum EnumBadgePriority { - LOW(0), NORMAL(1), HIGHER(2), HIGHEST(3); - - public final int priority; - - private EnumBadgePriority(int priority) { - this.priority = priority; - } - - private static final EnumBadgePriority[] lookup = new EnumBadgePriority[4]; - - public static EnumBadgePriority getByID(int id) { - if(id >= 0 && id < lookup.length) { - return lookup[id]; - }else { - return NORMAL; - } - } - - static { - EnumBadgePriority[] _values = values(); - for(int i = 0; i < _values.length; ++i) { - lookup[_values[i].priority] = _values[i]; - } - } - } - - public UUID badgeUUID; - public String bodyComponent; - public String titleComponent; - public String sourceComponent; - public long originalTimestampSec; - public boolean silent; - public EnumBadgePriority priority; - public UUID mainIconUUID; - public UUID titleIconUUID; - public int hideAfterSec; - public int expireAfterSec; - public int backgroundColor; - public int bodyTxtColor; - public int titleTxtColor; - public int sourceTxtColor; - - public CPacketRPCNotifBadgeShow() { - } - - public CPacketRPCNotifBadgeShow(UUID badgeUUID, String bodyComponent, String titleComponent, String sourceComponent, - long originalTimestampSec, UUID mainIconUUID, UUID titleIconUUID, boolean silent, - EnumBadgePriority priority, int hideAfterSec, int expireAfterSec, int backgroundColor, int bodyTxtColor, - int titleTxtColor, int sourceTxtColor) { - this.badgeUUID = badgeUUID; - this.bodyComponent = bodyComponent; - this.titleComponent = titleComponent; - this.sourceComponent = sourceComponent; - this.originalTimestampSec = originalTimestampSec; - this.mainIconUUID = mainIconUUID; - this.titleIconUUID = titleIconUUID; - this.silent = silent; - this.priority = priority; - this.hideAfterSec = hideAfterSec; - this.expireAfterSec = expireAfterSec; - this.backgroundColor = backgroundColor; - this.bodyTxtColor = bodyTxtColor; - this.titleTxtColor = titleTxtColor; - this.sourceTxtColor = sourceTxtColor; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - badgeUUID = new UUID(buffer.readLong(), buffer.readLong()); - bodyComponent = readString(buffer, 32767, true, StandardCharsets.UTF_8); - titleComponent = readString(buffer, 255, false, StandardCharsets.UTF_8); - sourceComponent = readString(buffer, 255, false, StandardCharsets.UTF_8); - originalTimestampSec = ((long)buffer.readUnsignedShort() << 32l) | ((long)buffer.readInt() & 0xFFFFFFFFl); - int flags = buffer.readUnsignedByte(); - silent = (flags & 1) != 0; - priority = EnumBadgePriority.getByID((flags >>> 1) & 3); - hideAfterSec = buffer.readUnsignedByte(); - expireAfterSec = buffer.readUnsignedShort(); - mainIconUUID = (flags & 8) != 0 ? new UUID(buffer.readLong(), buffer.readLong()) : null; - titleIconUUID = (flags & 16) != 0 ? new UUID(buffer.readLong(), buffer.readLong()) : null; - backgroundColor = (buffer.readUnsignedByte() << 16) | (buffer.readUnsignedByte() << 8) | buffer.readUnsignedByte(); - bodyTxtColor = (buffer.readUnsignedByte() << 16) | (buffer.readUnsignedByte() << 8) | buffer.readUnsignedByte(); - titleTxtColor = (buffer.readUnsignedByte() << 16) | (buffer.readUnsignedByte() << 8) | buffer.readUnsignedByte(); - sourceTxtColor = (buffer.readUnsignedByte() << 16) | (buffer.readUnsignedByte() << 8) | buffer.readUnsignedByte(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeLong(badgeUUID.getMostSignificantBits()); - buffer.writeLong(badgeUUID.getLeastSignificantBits()); - writeString(buffer, bodyComponent, true, StandardCharsets.UTF_8); - writeString(buffer, titleComponent, false, StandardCharsets.UTF_8); - writeString(buffer, sourceComponent, false, StandardCharsets.UTF_8); - buffer.writeShort((int)((originalTimestampSec >> 32l) & 0xFFFFl)); - buffer.writeInt((int)(originalTimestampSec & 0xFFFFFFFFl)); - int flags = (silent ? 1 : 0); - flags |= ((priority != null ? priority.priority : 1) << 1); - flags |= (mainIconUUID != null ? 8 : 0); - flags |= (titleIconUUID != null ? 16 : 0); - buffer.writeByte(flags); - buffer.writeByte(hideAfterSec); - buffer.writeShort(expireAfterSec); - if(mainIconUUID != null) { - buffer.writeLong(mainIconUUID.getMostSignificantBits()); - buffer.writeLong(mainIconUUID.getLeastSignificantBits()); - } - if(titleIconUUID != null) { - buffer.writeLong(titleIconUUID.getMostSignificantBits()); - buffer.writeLong(titleIconUUID.getLeastSignificantBits()); - } - buffer.writeByte((backgroundColor >>> 16) & 0xFF); - buffer.writeByte((backgroundColor >>> 8) & 0xFF); - buffer.writeByte(backgroundColor & 0xFF); - buffer.writeByte((bodyTxtColor >>> 16) & 0xFF); - buffer.writeByte((bodyTxtColor >>> 8) & 0xFF); - buffer.writeByte(bodyTxtColor & 0xFF); - buffer.writeByte((titleTxtColor >>> 16) & 0xFF); - buffer.writeByte((titleTxtColor >>> 8) & 0xFF); - buffer.writeByte(titleTxtColor & 0xFF); - buffer.writeByte((sourceTxtColor >>> 16) & 0xFF); - buffer.writeByte((sourceTxtColor >>> 8) & 0xFF); - buffer.writeByte(sourceTxtColor & 0xFF); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return -1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRegister.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRegister.java deleted file mode 100644 index 47c5df5e..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRegister.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; - -public class CPacketRPCNotifIconRegister implements EaglerBackendRPCPacket { - - public Map notifIcons; - - public CPacketRPCNotifIconRegister() { - } - - public CPacketRPCNotifIconRegister(Map notifIcons) { - this.notifIcons = notifIcons; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - notifIcons = new HashMap<>(); - int cnt = buffer.readUnsignedByte(); - for(int i = 0; i < cnt; ++i) { - UUID uuid = new UUID(buffer.readLong(), buffer.readLong()); - PacketImageData img = PacketImageData.readRGB16(buffer); - notifIcons.put(uuid, img); - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(notifIcons != null && !notifIcons.isEmpty()) { - int l = notifIcons.size(); - if(l > 255) { - throw new IOException("Too many notification icons in packet! (Max is 255, got " + l + " total)"); - } - buffer.writeByte(l); - for(Entry etr : notifIcons.entrySet()) { - UUID uuid = etr.getKey(); - buffer.writeLong(uuid.getMostSignificantBits()); - buffer.writeLong(uuid.getLeastSignificantBits()); - PacketImageData.writeRGB16(buffer, etr.getValue()); - } - }else { - buffer.writeByte(0); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - int i = 1 + (notifIcons.size() << 4); - for(PacketImageData dat : notifIcons.values()) { - i += dat.getByteLengthRGB16(); - } - return i; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRelease.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRelease.java deleted file mode 100644 index 0dff7782..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCNotifIconRelease.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.RandomAccess; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCNotifIconRelease implements EaglerBackendRPCPacket { - - public Collection iconsToRelease; - - public CPacketRPCNotifIconRelease() { - } - - public CPacketRPCNotifIconRelease(Collection iconsToRelease) { - this.iconsToRelease = iconsToRelease; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - int cnt = buffer.readUnsignedByte(); - iconsToRelease = new ArrayList<>(cnt); - for(int i = 0; i < cnt; ++i) { - iconsToRelease.add(new UUID(buffer.readLong(), buffer.readLong())); - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(iconsToRelease != null && !iconsToRelease.isEmpty()) { - int cnt = iconsToRelease.size(); - if(cnt > 255) { - throw new IOException("Too many notification icons in packet! (Max is 255, got " + cnt + " total)"); - } - buffer.writeByte(cnt); - if(iconsToRelease instanceof RandomAccess) { - List vigg = (List)iconsToRelease; - for(int i = 0; i < cnt; ++i) { - UUID uuid = vigg.get(i); - buffer.writeLong(uuid.getMostSignificantBits()); - buffer.writeLong(uuid.getLeastSignificantBits()); - } - }else { - for(UUID uuid : iconsToRelease) { - buffer.writeLong(uuid.getMostSignificantBits()); - buffer.writeLong(uuid.getLeastSignificantBits()); - } - } - }else { - buffer.writeByte(0); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 1 + (iconsToRelease.size() << 4); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRedirectPlayer.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRedirectPlayer.java deleted file mode 100644 index 40865967..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRedirectPlayer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCRedirectPlayer implements EaglerBackendRPCPacket { - - public String redirectURI; - - public CPacketRPCRedirectPlayer() { - } - - public CPacketRPCRedirectPlayer(String redirectURI) { - this.redirectURI = redirectURI; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - byte[] redirectURIBytes = new byte[buffer.readUnsignedShort()]; - buffer.readFully(redirectURIBytes); - redirectURI = new String(redirectURIBytes, StandardCharsets.US_ASCII); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(redirectURI.length() > 65535) { - throw new IOException("Redirect URI is too long!"); - } - byte[] redirectURIBytes = redirectURI.getBytes(StandardCharsets.US_ASCII); - buffer.writeShort(redirectURIBytes.length); - buffer.write(redirectURIBytes); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 2 + redirectURI.length(); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRequestPlayerInfo.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRequestPlayerInfo.java deleted file mode 100644 index 94f91266..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCRequestPlayerInfo.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCRequestPlayerInfo implements EaglerBackendRPCPacket { - - public static final int REQUEST_PLAYER_REAL_UUID = 0; - public static final int REQUEST_PLAYER_REAL_IP = 1; - public static final int REQUEST_PLAYER_ORIGIN = 2; - public static final int REQUEST_PLAYER_USER_AGENT = 3; - public static final int REQUEST_PLAYER_SKIN_DATA = 4; - public static final int REQUEST_PLAYER_CAPE_DATA = 5; - public static final int REQUEST_PLAYER_COOKIE = 6; - public static final int REQUEST_PLAYER_CLIENT_BRAND_STR = 7; - public static final int REQUEST_PLAYER_CLIENT_VERSION_STR = 8; - public static final int REQUEST_PLAYER_CLIENT_BRAND_VERSION_STR = 9; - public static final int REQUEST_PLAYER_CLIENT_BRAND_UUID = 10; - public static final int REQUEST_PLAYER_CLIENT_VOICE_STATUS = 11; - public static final int REQUEST_PLAYER_CLIENT_WEBVIEW_STATUS = 12; - - public int requestID; - public int requestType; - - public CPacketRPCRequestPlayerInfo() { - } - - public CPacketRPCRequestPlayerInfo(int requestID, int requestType) { - this.requestID = requestID; - this.requestType = requestType; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - requestType = buffer.readUnsignedByte(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - buffer.writeByte(requestType); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 5; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCResetPlayerMulti.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCResetPlayerMulti.java deleted file mode 100644 index d5c661bc..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCResetPlayerMulti.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCResetPlayerMulti implements EaglerBackendRPCPacket { - - public boolean resetSkin; - public boolean resetCape; - public boolean resetFNAWForce; - public boolean notifyOtherPlayers; - - public CPacketRPCResetPlayerMulti() { - } - - public CPacketRPCResetPlayerMulti(boolean resetSkin, boolean resetCape, boolean resetFNAWForce, - boolean notifyOtherPlayers) { - this.resetSkin = resetSkin; - this.resetCape = resetCape; - this.resetFNAWForce = resetFNAWForce; - this.notifyOtherPlayers = notifyOtherPlayers; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - int flags = buffer.readUnsignedByte(); - resetSkin = (flags & 1) != 0; - resetCape = (flags & 2) != 0; - resetFNAWForce = (flags & 4) != 0; - notifyOtherPlayers = (flags & 8) != 0; - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeByte((resetSkin ? 1 : 0) | (resetCape ? 2 : 0) | - (resetFNAWForce ? 4 : 0) | (notifyOtherPlayers ? 8 : 0)); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendRawMessage.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendRawMessage.java deleted file mode 100644 index 5f17db7a..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendRawMessage.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.readString; -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.writeString; - -public class CPacketRPCSendRawMessage implements EaglerBackendRPCPacket { - - public String messageChannel; - public byte[] messageData; - - public CPacketRPCSendRawMessage() { - } - - public CPacketRPCSendRawMessage(String messageChannel, byte[] messageData) { - this.messageChannel = messageChannel; - this.messageData = messageData; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - messageChannel = readString(buffer, 32, false, StandardCharsets.US_ASCII); - messageData = new byte[buffer.readUnsignedShort()]; - buffer.readFully(messageData); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(messageChannel.length() > 32) { - throw new IOException("Message channel name cannot be longer than 32 chars!"); - } - if(messageData.length > 32720) { - throw new IOException("Message data cannot be longer than 32720 bytes!"); - } - writeString(buffer, messageChannel, false, StandardCharsets.US_ASCII); - buffer.writeShort(messageData.length); - buffer.write(messageData); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 1 + messageChannel.length() + 2 + messageData.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendWebViewMessage.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendWebViewMessage.java deleted file mode 100644 index c63f441c..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSendWebViewMessage.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSendWebViewMessage implements EaglerBackendRPCPacket { - - public static final int MESSAGE_TYPE_STRING = 0; - public static final int MESSAGE_TYPE_BINARY = 1; - - public String channelName; - public int messageType; - public byte[] messageContent; - - public CPacketRPCSendWebViewMessage() { - } - - public CPacketRPCSendWebViewMessage(String channelName, int messageType, byte[] messageContent) { - this.channelName = channelName; - this.messageType = messageType; - this.messageContent = messageContent; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - byte[] nameBytes = new byte[buffer.readUnsignedByte()]; - buffer.readFully(nameBytes); - channelName = new String(nameBytes, StandardCharsets.US_ASCII); - messageType = buffer.readUnsignedByte(); - messageContent = new byte[buffer.readUnsignedShort()]; - buffer.readFully(messageContent); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(channelName == null || channelName.length() == 0) { - throw new IOException("Channel name cannot be empty!"); - } - if(channelName.length() > 255) { - throw new IOException("Channel name cannot be more than 255 chars! (got " + channelName.length() + " chars)"); - } - if(messageContent == null) { - throw new IOException("Message contents cannot be null!"); - } - if(messageContent.length > 32720) { - throw new IOException("Message contents cannot be more then 32720 bytes! (got " + messageContent.length + " bytes)"); - } - byte[] nameBytes = channelName.getBytes(StandardCharsets.US_ASCII); - buffer.writeByte(nameBytes.length); - buffer.write(nameBytes); - buffer.writeByte(messageType); - buffer.writeShort(messageContent.length); - buffer.write(messageContent); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 4 + channelName.length() + messageContent.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPauseMenuCustom.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPauseMenuCustom.java deleted file mode 100644 index 75ff2c6f..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPauseMenuCustom.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util.PacketImageData; - -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.readString; -import static net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket.writeString; - -public class CPacketRPCSetPauseMenuCustom implements EaglerBackendRPCPacket { - - public static final int SERVER_INFO_MODE_NONE = 0; - public static final int SERVER_INFO_MODE_EXTERNAL_URL = 1; - public static final int SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP = 2; - public static final int SERVER_INFO_MODE_SHOW_EMBED_OVER_WS = 3; - public static final int SERVER_INFO_MODE_INHERIT_DEFAULT = 4; - - public static final int SERVER_INFO_EMBED_PERMS_JAVASCRIPT = 1; - public static final int SERVER_INFO_EMBED_PERMS_MESSAGE_API = 2; - public static final int SERVER_INFO_EMBED_PERMS_STRICT_CSP = 4; - - public static final int DISCORD_MODE_NONE = 0; - public static final int DISCORD_MODE_INVITE_URL = 1; - public static final int DISCORD_MODE_INHERIT_DEFAULT = 2; - - public int serverInfoMode; - public String serverInfoButtonText; - public String serverInfoURL; - public byte[] serverInfoHash; - public int serverInfoEmbedPerms; - public String serverInfoEmbedTitle; - public int discordButtonMode; - public String discordButtonText; - public String discordInviteURL; - - public Map imageMappings; - public List imageData; - - public CPacketRPCSetPauseMenuCustom() { - } - - public CPacketRPCSetPauseMenuCustom(int serverInfoMode, String serverInfoButtonText, String serverInfoURL, - byte[] serverInfoHash, int serverInfoEmbedPerms, String serverInfoEmbedTitle, int discordButtonMode, - String discordButtonText, String discordInviteURL, Map imageMappings, - List imageData) { - this.serverInfoMode = serverInfoMode; - this.serverInfoButtonText = serverInfoButtonText; - this.serverInfoURL = serverInfoURL; - this.serverInfoHash = serverInfoHash; - this.serverInfoEmbedPerms = serverInfoEmbedPerms; - this.serverInfoEmbedTitle = serverInfoEmbedTitle; - this.discordButtonMode = discordButtonMode; - this.discordButtonText = discordButtonText; - this.discordInviteURL = discordInviteURL; - this.imageMappings = imageMappings; - this.imageData = imageData; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - imageMappings = null; - imageData = null; - int flags = buffer.readUnsignedByte(); - serverInfoMode = (flags & 15); - discordButtonMode = ((flags >> 4) & 15); - switch(serverInfoMode) { - case SERVER_INFO_MODE_EXTERNAL_URL: - serverInfoButtonText = readString(buffer, 127, false, StandardCharsets.UTF_8); - serverInfoURL = readString(buffer, 65535, true, StandardCharsets.US_ASCII); - serverInfoEmbedPerms = 0; - serverInfoHash = null; - break; - case SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP: - serverInfoButtonText = readString(buffer, 127, false, StandardCharsets.UTF_8); - serverInfoURL = readString(buffer, 65535, true, StandardCharsets.US_ASCII); - serverInfoEmbedPerms = buffer.readUnsignedByte(); - serverInfoHash = null; - serverInfoEmbedTitle = readString(buffer, 127, false, StandardCharsets.UTF_8); - break; - case SERVER_INFO_MODE_SHOW_EMBED_OVER_WS: - serverInfoButtonText = readString(buffer, 127, false, StandardCharsets.UTF_8); - serverInfoURL = null; - serverInfoEmbedPerms = buffer.readUnsignedByte(); - serverInfoHash = new byte[20]; - serverInfoEmbedTitle = readString(buffer, 127, false, StandardCharsets.UTF_8); - buffer.readFully(serverInfoHash); - break; - case SERVER_INFO_MODE_INHERIT_DEFAULT: - default: - serverInfoButtonText = null; - serverInfoURL = null; - serverInfoEmbedPerms = 0; - serverInfoHash = null; - break; - } - if(discordButtonMode == DISCORD_MODE_INVITE_URL) { - discordButtonText = readString(buffer, 127, false, StandardCharsets.UTF_8); - discordInviteURL = readString(buffer, 65535, true, StandardCharsets.US_ASCII); - }else { - discordButtonText = null; - discordInviteURL = null; - } - int mappingsCount = buffer.readUnsignedShort(); - if(mappingsCount > 0) { - imageMappings = new HashMap<>(); - imageData = new ArrayList<>(); - for(int i = 0; i < mappingsCount; ++i) { - imageMappings.put(readString(buffer, 255, false, StandardCharsets.US_ASCII), buffer.readUnsignedShort()); - } - int imageDataCount = buffer.readUnsignedShort(); - for(int i = 0; i < imageDataCount; ++i) { - int w = buffer.readUnsignedByte(); - int h = buffer.readUnsignedByte(); - int pixelCount = w * h; - int[] pixels = new int[pixelCount]; - for(int j = 0, p, pR, pG, pB; j < pixelCount; ++j) { - p = buffer.readUnsignedShort(); - pR = (p >>> 11) & 0x1F; - pG = (p >>> 5) & 0x3F; - pB = p & 0x1F; - if(pR + pG + pB > 0) { - pB = (pB - 1) * 31 / 30; - pixels[j] = 0xFF000000 | (pR << 19) | (pG << 10) | (pB << 3); - }else { - pixels[j] = 0; - } - } - imageData.add(new PacketImageData(w, h, pixels)); - } - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeByte(serverInfoMode | (discordButtonMode << 4)); - switch(serverInfoMode) { - case SERVER_INFO_MODE_EXTERNAL_URL: - writeString(buffer, serverInfoButtonText, false, StandardCharsets.UTF_8); - writeString(buffer, serverInfoURL, true, StandardCharsets.US_ASCII); - break; - case SERVER_INFO_MODE_SHOW_EMBED_OVER_HTTP: - writeString(buffer, serverInfoButtonText, false, StandardCharsets.UTF_8); - writeString(buffer, serverInfoURL, true, StandardCharsets.US_ASCII); - buffer.writeByte(serverInfoEmbedPerms); - writeString(buffer, serverInfoEmbedTitle, false, StandardCharsets.UTF_8); - break; - case SERVER_INFO_MODE_SHOW_EMBED_OVER_WS: - writeString(buffer, serverInfoButtonText, false, StandardCharsets.UTF_8); - buffer.writeByte(serverInfoEmbedPerms); - writeString(buffer, serverInfoEmbedTitle, false, StandardCharsets.UTF_8); - if(serverInfoHash.length != 20) { - throw new IOException("Hash must be 20 bytes! (" + serverInfoHash.length + " given)"); - } - buffer.write(serverInfoHash); - break; - case SERVER_INFO_MODE_INHERIT_DEFAULT: - default: - break; - } - if(discordButtonMode == DISCORD_MODE_INVITE_URL) { - writeString(buffer, discordButtonText, false, StandardCharsets.UTF_8); - writeString(buffer, discordInviteURL, true, StandardCharsets.US_ASCII); - } - if(imageMappings != null && !imageMappings.isEmpty()) { - buffer.writeShort(imageMappings.size()); - for(Entry etr : imageMappings.entrySet()) { - writeString(buffer, etr.getKey(), false, StandardCharsets.US_ASCII); - buffer.writeShort(etr.getValue().intValue()); - } - buffer.writeShort(imageData.size()); - for(PacketImageData etr : imageData) { - if(etr.width < 1 || etr.width > 64 || etr.height < 1 || etr.height > 64) { - throw new IOException("Invalid image dimensions in packet, must be between 1x1 and 64x64, got " + etr.width + "x" + etr.height); - } - PacketImageData.writeRGB16(buffer, etr); - } - }else { - buffer.writeByte(0); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return -1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCape.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCape.java deleted file mode 100644 index 02c93d63..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCape.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSetPlayerCape implements EaglerBackendRPCPacket { - - public boolean notifyOthers; - public byte[] capePacket; - - public CPacketRPCSetPlayerCape() { - } - - public CPacketRPCSetPlayerCape(boolean notifyOthers, byte[] capePacket) { - this.notifyOthers = notifyOthers; - this.capePacket = capePacket; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - notifyOthers = buffer.readBoolean(); - capePacket = new byte[buffer.readUnsignedShort()]; - buffer.readFully(capePacket); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(capePacket.length > 32720) { - throw new IOException("Cape data cannot be longer than 32720 bytes!"); - } - buffer.writeBoolean(notifyOthers); - buffer.writeShort(capePacket.length); - buffer.write(capePacket); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 3 + capePacket.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCookie.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCookie.java deleted file mode 100644 index 4e346bf3..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerCookie.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSetPlayerCookie implements EaglerBackendRPCPacket { - - public boolean revokeQuerySupported; - public boolean saveToDisk; - public int expires; - public byte[] cookieData; - - public CPacketRPCSetPlayerCookie() { - } - - public CPacketRPCSetPlayerCookie(boolean revokeQuerySupported, boolean saveToDisk, int expires, - byte[] cookieData) { - this.revokeQuerySupported = revokeQuerySupported; - this.saveToDisk = saveToDisk; - this.expires = expires; - this.cookieData = cookieData; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - int flags = buffer.readUnsignedByte(); - revokeQuerySupported = (flags & 1) == 1; - saveToDisk = (flags & 2) == 2; - expires = buffer.readInt(); - int cookieLen = buffer.readUnsignedByte(); - if(cookieLen > 0) { - cookieData = new byte[cookieLen]; - buffer.readFully(cookieData); - }else { - cookieData = null; - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(cookieData != null && cookieData.length > 255) { - throw new IOException("Cookie cannot be longer than 255 bytes!"); - } - buffer.writeByte((revokeQuerySupported ? 1 : 0) | (saveToDisk ? 2 : 0)); - buffer.writeInt(expires); - if(cookieData != null) { - buffer.writeByte(cookieData.length); - buffer.write(cookieData); - }else { - buffer.writeByte(0); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 6 + (cookieData != null ? cookieData.length : 0); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerFNAWEn.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerFNAWEn.java deleted file mode 100644 index 402c0927..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerFNAWEn.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSetPlayerFNAWEn implements EaglerBackendRPCPacket { - - public boolean enable; - public boolean force; - - public CPacketRPCSetPlayerFNAWEn() { - } - - public CPacketRPCSetPlayerFNAWEn(boolean enable, boolean force) { - this.enable = enable; - this.force = force; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - int flags = buffer.readUnsignedByte(); - enable = (flags & 1) != 0; - force = (flags & 2) != 0; - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeByte((enable ? 1 : 0) | (force ? 2 : 0)); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerSkin.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerSkin.java deleted file mode 100644 index 9ae8d357..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSetPlayerSkin.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSetPlayerSkin implements EaglerBackendRPCPacket { - - public boolean notifyOthers; - public byte[] skinPacket; - - public CPacketRPCSetPlayerSkin() { - } - - public CPacketRPCSetPlayerSkin(boolean notifyOthers, byte[] skinPacket) { - this.notifyOthers = notifyOthers; - this.skinPacket = skinPacket; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - notifyOthers = buffer.readBoolean(); - skinPacket = new byte[buffer.readUnsignedShort()]; - buffer.readFully(skinPacket); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(skinPacket.length > 32720) { - throw new IOException("Skin data cannot be longer than 32720 bytes!"); - } - buffer.writeBoolean(notifyOthers); - buffer.writeShort(skinPacket.length); - buffer.write(skinPacket); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 3 + skinPacket.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSubscribeEvents.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSubscribeEvents.java deleted file mode 100644 index 5890dffb..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/client/CPacketRPCSubscribeEvents.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class CPacketRPCSubscribeEvents implements EaglerBackendRPCPacket { - - public static final int SUBSCRIBE_EVENT_WEBVIEW_OPEN_CLOSE = 1; - public static final int SUBSCRIBE_EVENT_WEBVIEW_MESSAGE = 2; - public static final int SUBSCRIBE_EVENT_TOGGLE_VOICE = 4; - - public int eventsToEnable; - - public CPacketRPCSubscribeEvents() { - } - - public CPacketRPCSubscribeEvents(int eventsToEnable) { - this.eventsToEnable = eventsToEnable; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - eventsToEnable = buffer.readUnsignedShort(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeShort(eventsToEnable); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleClient(this); - } - - @Override - public int length() { - return 2; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledFailure.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledFailure.java deleted file mode 100644 index f4de4785..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledFailure.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCEnabledFailure implements EaglerBackendRPCPacket { - - public static final int FAILURE_CODE_NOT_ENABLED = 0; - public static final int FAILURE_CODE_NOT_EAGLER_PLAYER = 1; - public static final int FAILURE_CODE_OUTDATED_SERVER = 2; - public static final int FAILURE_CODE_OUTDATED_CLIENT = 3; - public static final int FAILURE_CODE_INTERNAL_ERROR = 0xFF; - - public int failureCode; - - public SPacketRPCEnabledFailure() { - } - - public SPacketRPCEnabledFailure(int failureCode) { - this.failureCode = failureCode; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - failureCode = buffer.readUnsignedByte(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeByte(failureCode); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledSuccess.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledSuccess.java deleted file mode 100644 index 1e4d7cef..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEnabledSuccess.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCEnabledSuccess implements EaglerBackendRPCPacket { - - public int selectedRPCProtocol; - public int playerClientProtocol; - - public SPacketRPCEnabledSuccess() { - } - - public SPacketRPCEnabledSuccess(int selectedRPCProtocol, int playerClientProtocol) { - this.selectedRPCProtocol = selectedRPCProtocol; - this.playerClientProtocol = playerClientProtocol; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - selectedRPCProtocol = buffer.readUnsignedShort(); - playerClientProtocol = buffer.readUnsignedShort(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeShort(selectedRPCProtocol); - buffer.writeShort(playerClientProtocol); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 4; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventToggledVoice.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventToggledVoice.java deleted file mode 100644 index f96d38c0..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventToggledVoice.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCEventToggledVoice implements EaglerBackendRPCPacket { - - public static final int VOICE_STATE_SERVER_DISABLE = 0; - public static final int VOICE_STATE_DISABLED = 1; - public static final int VOICE_STATE_ENABLED = 2; - - public int oldVoiceState; - public int newVoiceState; - - public SPacketRPCEventToggledVoice() { - } - - public SPacketRPCEventToggledVoice(int oldVoiceState, int newVoiceState) { - this.oldVoiceState = oldVoiceState; - this.newVoiceState = newVoiceState; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - int i = buffer.readUnsignedByte(); - oldVoiceState = (i >>> 4) & 15; - newVoiceState = i & 15; - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeByte((oldVoiceState << 4) | newVoiceState); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewMessage.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewMessage.java deleted file mode 100644 index 43f89ce6..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewMessage.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCEventWebViewMessage implements EaglerBackendRPCPacket { - - public static final int MESSAGE_TYPE_STRING = 0; - public static final int MESSAGE_TYPE_BINARY = 1; - - public String channelName; - public int messageType; - public byte[] messageContent; - - public SPacketRPCEventWebViewMessage() { - } - - public SPacketRPCEventWebViewMessage(String channelName, int messageType, byte[] messageContent) { - this.channelName = channelName; - this.messageType = messageType; - this.messageContent = messageContent; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - byte[] nameBytes = new byte[buffer.readUnsignedByte()]; - buffer.readFully(nameBytes); - channelName = new String(nameBytes, StandardCharsets.US_ASCII); - messageType = buffer.readUnsignedByte(); - messageContent = new byte[buffer.readUnsignedShort()]; - buffer.readFully(messageContent); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(channelName == null || channelName.length() == 0) { - throw new IOException("Channel name cannot be empty!"); - } - if(channelName.length() > 255) { - throw new IOException("Channel name cannot be more than 255 chars! (got " + channelName.length() + " chars)"); - } - if(messageContent == null) { - throw new IOException("Message contents cannot be null!"); - } - if(messageContent.length > 32720) { - throw new IOException("Message contents cannot be more then 32720 bytes! (got " + messageContent.length + " bytes)"); - } - byte[] nameBytes = channelName.getBytes(StandardCharsets.US_ASCII); - buffer.writeByte(nameBytes.length); - buffer.write(nameBytes); - buffer.writeByte(messageType); - buffer.writeShort(messageContent.length); - buffer.write(messageContent); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 4 + channelName.length() + messageContent.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewOpenClose.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewOpenClose.java deleted file mode 100644 index 6798fb23..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCEventWebViewOpenClose.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCEventWebViewOpenClose implements EaglerBackendRPCPacket { - - public boolean channelOpen; - public String channelName; - - public SPacketRPCEventWebViewOpenClose() { - } - - public SPacketRPCEventWebViewOpenClose(boolean channelOpen, String channelName) { - this.channelOpen = channelOpen; - this.channelName = channelName; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - channelOpen = buffer.readBoolean(); - byte[] nameBytes = new byte[buffer.readUnsignedByte()]; - buffer.readFully(nameBytes); - channelName = new String(nameBytes, StandardCharsets.US_ASCII); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(channelName == null || channelName.length() == 0) { - throw new IOException("Channel name cannot be empty!"); - } - if(channelName.length() > 255) { - throw new IOException("Channel name cannot be more than 255 chars! (got " + channelName.length() + " chars)"); - } - buffer.writeBoolean(channelOpen); - byte[] nameBytes = channelName.getBytes(StandardCharsets.US_ASCII); - buffer.writeByte(nameBytes.length); - buffer.write(nameBytes); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 2 + channelName.length(); - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeBytes.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeBytes.java deleted file mode 100644 index 4682715e..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeBytes.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeBytes implements EaglerBackendRPCPacket { - - public int requestID; - public byte[] response; - - public SPacketRPCResponseTypeBytes() { - } - - public SPacketRPCResponseTypeBytes(int requestID, byte[] response) { - this.requestID = requestID; - this.response = response; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - response = new byte[buffer.readUnsignedShort()]; - buffer.readFully(response); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - if(response.length > 32720) { - throw new IOException("Response is too long, max is 32720 bytes! (got " + response.length + " bytes)"); - } - buffer.writeInt(requestID); - buffer.writeShort(response.length); - buffer.write(response); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 6 + response.length; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeCookie.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeCookie.java deleted file mode 100644 index 43bd8420..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeCookie.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeCookie implements EaglerBackendRPCPacket { - - public int requestID; - public boolean cookiesEnabled; - public byte[] cookieData; - - public SPacketRPCResponseTypeCookie() { - } - - public SPacketRPCResponseTypeCookie(int requestID, boolean cookiesEnabled, byte[] cookieData) { - this.requestID = requestID; - this.cookiesEnabled = cookiesEnabled; - this.cookieData = cookieData; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - int flags = buffer.readUnsignedByte(); - cookiesEnabled = (flags & 1) != 0; - int len = cookiesEnabled ? buffer.readUnsignedByte() : 0; - if(cookiesEnabled && len > 0) { - cookieData = new byte[len]; - buffer.readFully(cookieData); - }else { - cookieData = null; - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - if(cookiesEnabled) { - buffer.writeByte(1); - if(cookieData != null && cookieData.length > 0) { - if(cookieData.length > 255) { - throw new IOException("Cookie is too long, max is 255 bytes! (got " + cookieData.length + " bytes)"); - } - buffer.writeByte(cookieData.length); - buffer.write(cookieData); - }else { - buffer.writeByte(0); - } - }else { - buffer.writeByte(0); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return cookiesEnabled ? (cookieData != null ? (6 + cookieData.length) : 6) : 5; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeError.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeError.java deleted file mode 100644 index d5221691..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeError.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeError implements EaglerBackendRPCPacket { - - public int requestID; - public String errorMessage; - - public SPacketRPCResponseTypeError() { - } - - public SPacketRPCResponseTypeError(int requestID, String errorMessage) { - this.requestID = requestID; - this.errorMessage = errorMessage; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - errorMessage = buffer.readUTF(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - buffer.writeUTF(errorMessage); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return -1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeNull.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeNull.java deleted file mode 100644 index 7e032071..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeNull.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeNull implements EaglerBackendRPCPacket { - - public int requestID; - - public SPacketRPCResponseTypeNull() { - } - - public SPacketRPCResponseTypeNull(int requestID) { - this.requestID = requestID; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 4; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeString.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeString.java deleted file mode 100644 index 72d94657..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeString.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeString implements EaglerBackendRPCPacket { - - public int requestID; - public String response; - - public SPacketRPCResponseTypeString() { - } - - public SPacketRPCResponseTypeString(int requestID, String response) { - this.requestID = requestID; - this.response = response; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - byte[] responseBytes = new byte[buffer.readUnsignedShort()]; - buffer.readFully(responseBytes); - response = new String(responseBytes, StandardCharsets.UTF_8); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8); - if(responseBytes.length > 32720) { - throw new IOException("Response is too long, max is 32720 bytes! (got " + responseBytes.length + " bytes)"); - } - buffer.writeInt(requestID); - buffer.writeShort(responseBytes.length); - buffer.write(responseBytes); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return -1; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeUUID.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeUUID.java deleted file mode 100644 index a3ae44c2..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeUUID.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeUUID implements EaglerBackendRPCPacket { - - public int requestID; - public UUID uuid; - - public SPacketRPCResponseTypeUUID() { - } - - public SPacketRPCResponseTypeUUID(int requestID, UUID uuid) { - this.requestID = requestID; - this.uuid = uuid; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - uuid = new UUID(buffer.readLong(), buffer.readLong()); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - buffer.writeLong(uuid.getMostSignificantBits()); - buffer.writeLong(uuid.getLeastSignificantBits()); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 20; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeVoiceStatus.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeVoiceStatus.java deleted file mode 100644 index f8b1d0f7..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeVoiceStatus.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeVoiceStatus implements EaglerBackendRPCPacket { - - public static final int VOICE_STATE_SERVER_DISABLE = 0; - public static final int VOICE_STATE_DISABLED = 1; - public static final int VOICE_STATE_ENABLED = 2; - - public int requestID; - public int voiceState; - - public SPacketRPCResponseTypeVoiceStatus() { - } - - public SPacketRPCResponseTypeVoiceStatus(int requestID, int voiceState) { - this.requestID = requestID; - this.voiceState = voiceState; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - voiceState = buffer.readUnsignedByte(); - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - buffer.writeByte(voiceState); - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return 5; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeWebViewStatus.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeWebViewStatus.java deleted file mode 100644 index f20dec5c..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/pkt/server/SPacketRPCResponseTypeWebViewStatus.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.server; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCHandler; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.EaglerBackendRPCPacket; - -public class SPacketRPCResponseTypeWebViewStatus implements EaglerBackendRPCPacket { - - public static final int WEBVIEW_STATE_NOT_SUPPORTED = 0; - public static final int WEBVIEW_STATE_SERVER_DISABLE = 1; - public static final int WEBVIEW_STATE_CHANNEL_CLOSED = 2; - public static final int WEBVIEW_STATE_CHANNEL_OPEN = 3; - - public int requestID; - public int webviewState; - public String channelName; - - public SPacketRPCResponseTypeWebViewStatus() { - } - - public SPacketRPCResponseTypeWebViewStatus(int requestID, int webviewState, String channelName) { - this.requestID = requestID; - this.webviewState = webviewState; - this.channelName = channelName; - } - - @Override - public void readPacket(DataInput buffer) throws IOException { - requestID = buffer.readInt(); - webviewState = buffer.readUnsignedByte(); - if(webviewState == WEBVIEW_STATE_CHANNEL_OPEN) { - byte[] nameBytes = new byte[buffer.readUnsignedByte()]; - buffer.readFully(nameBytes); - channelName = new String(nameBytes, StandardCharsets.US_ASCII); - } - } - - @Override - public void writePacket(DataOutput buffer) throws IOException { - buffer.writeInt(requestID); - buffer.writeByte(webviewState); - if(webviewState == WEBVIEW_STATE_CHANNEL_OPEN) { - if(channelName.length() > 255) { - throw new IOException("Channel name cannot be more than 255 chars! (got " + channelName.length() + " chars)"); - } - byte[] nameBytes = channelName.getBytes(StandardCharsets.US_ASCII); - buffer.writeByte(nameBytes.length); - buffer.write(nameBytes); - } - } - - @Override - public void handlePacket(EaglerBackendRPCHandler handler) { - handler.handleServer(this); - } - - @Override - public int length() { - return webviewState == WEBVIEW_STATE_CHANNEL_OPEN ? (6 + channelName.length()) : 5; - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/PacketImageData.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/PacketImageData.java deleted file mode 100644 index 1859e304..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/PacketImageData.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class PacketImageData { - - public final int width; - public final int height; - public final int[] rgba; - - public PacketImageData(int width, int height, int[] rgba) { - this.width = width; - this.height = height; - this.rgba = rgba; - } - - public int getByteLengthRGB16() { - return 2 + (rgba.length << 1); - } - - public static PacketImageData readRGB16(DataInput buffer) throws IOException { - int w = buffer.readUnsignedByte(); - int h = buffer.readUnsignedByte(); - int pixelCount = w * h; - int[] pixels = new int[pixelCount]; - for(int j = 0, p, pR, pG, pB; j < pixelCount; ++j) { - p = buffer.readUnsignedShort(); - pR = (p >>> 11) & 0x1F; - pG = (p >>> 5) & 0x3F; - pB = p & 0x1F; - if(pR + pG + pB > 0) { - pB = (int)((pB - 1) * 8.5f); - pixels[j] = 0xFF000000 | (pR << 19) | (pG << 10) | pB; - }else { - pixels[j] = 0; - } - } - return new PacketImageData(w, h, pixels); - } - - public static void writeRGB16(DataOutput buffer, PacketImageData imageData) throws IOException { - if(imageData.width < 1 || imageData.width > 255 || imageData.height < 1 || imageData.height > 255) { - throw new IOException("Invalid image dimensions in packet, must be between 1x1 and 255x255, got " + imageData.width + "x" + imageData.height); - } - buffer.writeByte(imageData.width); - buffer.writeByte(imageData.height); - int pixelCount = imageData.width * imageData.height; - for(int j = 0, p, pR, pG, pB; j < pixelCount; ++j) { - p = imageData.rgba[j]; - if((p >>> 24) > 0x7F) { - pR = (p >>> 19) & 0x1F; - pG = (p >>> 10) & 0x3F; - pB = (int)((p & 0xFF) * 0.1176471f) + 1; - buffer.writeShort((pR << 11) | (pG << 5) | pB); - }else { - buffer.writeShort(0); - } - } - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/SkinPacketHelper.java b/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/SkinPacketHelper.java deleted file mode 100644 index a15dc69f..00000000 --- a/gateway/backend-rpc-protocol/src/backend-rpc-protocol/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/SkinPacketHelper.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import javax.imageio.ImageIO; - -public class SkinPacketHelper { - - public static byte[] writePresetSkinPacket(int presetId) { - byte[] tex = new byte[5]; - tex[0] = (byte)1; - tex[1] = (byte)(presetId >>> 24); - tex[2] = (byte)(presetId >>> 16); - tex[3] = (byte)(presetId >>> 8); - tex[4] = (byte)(presetId & 0xFF); - return tex; - } - - public static byte[] loadCustomSkin(File texture64x64) throws IOException { - return loadCustomSkin(ImageIO.read(texture64x64)); - } - - public static byte[] loadCustomSkin(InputStream texture64x64) throws IOException { - return loadCustomSkin(ImageIO.read(texture64x64)); - } - - public static byte[] loadCustomSkin(BufferedImage texture64x64) { - if(texture64x64.getWidth() != 64 || texture64x64.getHeight() != 64) { - throw new IllegalArgumentException("Image is not 64x64!"); - } - byte[] tex = new byte[16384]; - for(int y = 0; y < 64; ++y) { - for(int x = 0; x < 64; ++x) { - int idx = (y << 8) | (x << 2); - int rgba = texture64x64.getRGB(x, y); - tex[idx] = (byte)(rgba >>> 24); - tex[idx + 1] = (byte)(rgba & 0xFF); - tex[idx + 2] = (byte)(rgba >>> 8); - tex[idx + 3] = (byte)(rgba >>> 16); - } - } - return tex; - } - - public static byte[] writeCustomSkinPacket(int modelId, byte[] texture64x64) { - if(texture64x64.length != 16384) { - throw new IllegalArgumentException("Wrong array length for 64x64 RGBA texture!"); - } - byte[] tex = new byte[2 + texture64x64.length]; - tex[0] = (byte)2; - tex[1] = (byte)modelId; - System.arraycopy(texture64x64, 0, tex, 2, texture64x64.length); - return tex; - } - - public static byte[] writeCustomSkinPacket(int modelId, File texture64x64) throws IOException { - return writeCustomSkinPacket(modelId, ImageIO.read(texture64x64)); - } - - public static byte[] writeCustomSkinPacket(int modelId, InputStream texture64x64) throws IOException { - return writeCustomSkinPacket(modelId, ImageIO.read(texture64x64)); - } - - public static byte[] writeCustomSkinPacket(int modelId, BufferedImage texture64x64) { - if(texture64x64.getWidth() != 64 || texture64x64.getHeight() != 64) { - throw new IllegalArgumentException("Image is not 64x64!"); - } - byte[] tex = new byte[16386]; - tex[0] = (byte)2; - tex[1] = (byte)modelId; - for(int y = 0; y < 64; ++y) { - for(int x = 0; x < 64; ++x) { - int idx = (y << 8) | (x << 2); - int rgba = texture64x64.getRGB(x, y); - tex[idx + 2] = (byte)(rgba >>> 24); - tex[idx + 3] = (byte)(rgba & 0xFF); - tex[idx + 4] = (byte)(rgba >>> 8); - tex[idx + 5] = (byte)(rgba >>> 16); - } - } - return tex; - } - - public static byte[] writePresetCapePacket(int presetId) { - byte[] tex = new byte[5]; - tex[0] = (byte)1; - tex[1] = (byte)(presetId >>> 24); - tex[2] = (byte)(presetId >>> 16); - tex[3] = (byte)(presetId >>> 8); - tex[4] = (byte)(presetId & 0xFF); - return tex; - } - - public static byte[] loadCustomCape(File textureNx32) throws IOException { - return loadCustomCape(ImageIO.read(textureNx32)); - } - - public static byte[] loadCustomCape(InputStream textureNx32) throws IOException { - return loadCustomCape(ImageIO.read(textureNx32)); - } - - public static byte[] loadCustomCape(BufferedImage textureNx32) { - if((textureNx32.getWidth() != 32 && textureNx32.getWidth() != 64) || textureNx32.getHeight() != 32) { - throw new IllegalArgumentException("Image is not 32x32 or 64x32!"); - } - byte[] tex = new byte[4096]; - for(int y = 0; y < 32; ++y) { - for(int x = 0; x < 32; ++x) { - int idx = (y << 7) | (x << 2); - int rgba = textureNx32.getRGB(x, y); - tex[idx] = (byte)(rgba >>> 24); - tex[idx + 1] = (byte)(rgba & 0xFF); - tex[idx + 2] = (byte)(rgba >>> 8); - tex[idx + 3] = (byte)(rgba >>> 16); - } - } - return tex; - } - - public static byte[] writeCustomCapePacket(File textureNx32) throws IOException { - return writeCustomCapePacket(ImageIO.read(textureNx32)); - } - - public static byte[] writeCustomCapePacket(InputStream textureNx32) throws IOException { - return writeCustomCapePacket(ImageIO.read(textureNx32)); - } - - public static byte[] writeCustomCapePacket(BufferedImage textureNx32) { - byte[] tex = loadCustomCape(textureNx32); - byte[] ret = new byte[1174]; - ret[0] = (byte)2; - convertCape32x32RGBAto23x17RGB(tex, 0, ret, 1); - return ret; - } - - public static byte[] writeCustomCapePacket(byte[] texture32x32) { - if(texture32x32.length != 4096) { - throw new IllegalArgumentException("Wrong array length for 32x32 RGBA texture!"); - } - byte[] tex = new byte[1174]; - tex[0] = (byte)2; - convertCape32x32RGBAto23x17RGB(texture32x32, 0, tex, 1); - return tex; - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, byte[] skinOut) { - convertCape32x32RGBAto23x17RGB(skinIn, 0, skinOut, 0); - } - - public static void convertCape32x32RGBAto23x17RGB(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = inOffset + ((y * 32 + x) << 2); - j = outOffset + ((y * 23 + x) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - for(int y = 0; y < 11; ++y) { - i = inOffset + (((y + 11) * 32 + 22) << 2); - j = outOffset + (((y + 6) * 23 + 22) * 3); - skinOut[j] = skinIn[i + 1]; - skinOut[j + 1] = skinIn[i + 2]; - skinOut[j + 2] = skinIn[i + 3]; - } - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, byte[] skinOut) { - convertCape23x17RGBto32x32RGBA(skinIn, 0, skinOut, 0); - } - - public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, int inOffset, byte[] skinOut, int outOffset) { - int i, j; - for(int y = 0; y < 17; ++y) { - for(int x = 0; x < 22; ++x) { - i = outOffset + ((y * 32 + x) << 2); - j = inOffset + ((y * 23 + x) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - for(int y = 0; y < 11; ++y) { - i = outOffset + (((y + 11) * 32 + 22) << 2); - j = inOffset + (((y + 6) * 23 + 22) * 3); - skinOut[i] = (byte)0xFF; - skinOut[i + 1] = skinIn[j]; - skinOut[i + 2] = skinIn[j + 1]; - skinOut[i + 3] = skinIn[j + 2]; - } - } - -} \ No newline at end of file diff --git a/gateway/backend-rpc-protocol/src/notif-builder-bungee/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/NotificationBadgeBuilder.java b/gateway/backend-rpc-protocol/src/notif-builder-bungee/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/NotificationBadgeBuilder.java deleted file mode 100644 index bfc2bd7b..00000000 --- a/gateway/backend-rpc-protocol/src/notif-builder-bungee/java/net/lax1dude/eaglercraft/v1_8/plugin/backend_rpc_protocol/util/NotificationBadgeBuilder.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.util; - -import java.util.UUID; - -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCNotifBadgeShow; -import net.lax1dude.eaglercraft.v1_8.plugin.backend_rpc_protocol.pkt.client.CPacketRPCNotifBadgeShow.EnumBadgePriority; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.chat.ComponentSerializer; - -public class NotificationBadgeBuilder { - - public static enum BadgePriority { - LOW, NORMAL, HIGHER, HIGHEST; - } - - private UUID badgeUUID = null; - private BaseComponent bodyComponent = null; - private BaseComponent titleComponent = null; - private BaseComponent sourceComponent = null; - private long originalTimestampSec = 0l; - private boolean silent = false; - private BadgePriority priority = BadgePriority.NORMAL; - private UUID mainIconUUID = null; - private UUID titleIconUUID = null; - private int hideAfterSec = 10; - private int expireAfterSec = 3600; - private int backgroundColor = 0xFFFFFF; - private int bodyTxtColor = 0xFFFFFF; - private int titleTxtColor = 0xFFFFFF; - private int sourceTxtColor = 0xFFFFFF; - - private CPacketRPCNotifBadgeShow packetCache = null; - private boolean packetDirty = true; - - public NotificationBadgeBuilder() { - originalTimestampSec = System.currentTimeMillis() / 1000l; - } - - public NotificationBadgeBuilder(NotificationBadgeBuilder builder) { - badgeUUID = builder.badgeUUID; - bodyComponent = builder.bodyComponent; - titleComponent = builder.titleComponent; - sourceComponent = builder.sourceComponent; - originalTimestampSec = builder.originalTimestampSec; - silent = builder.silent; - priority = builder.priority; - mainIconUUID = builder.mainIconUUID; - titleIconUUID = builder.titleIconUUID; - hideAfterSec = builder.hideAfterSec; - backgroundColor = builder.backgroundColor; - bodyTxtColor = builder.bodyTxtColor; - titleTxtColor = builder.titleTxtColor; - sourceTxtColor = builder.sourceTxtColor; - packetCache = !builder.packetDirty ? builder.packetCache : null; - packetDirty = builder.packetDirty; - } - - private static BaseComponent fixParsedComponent(BaseComponent[] comps) { - if(comps.length == 0) { - return null; - }else if(comps.length == 1) { - return comps[0]; - }else { - TextComponent cmp = new TextComponent(""); - for(int i = 0; i < comps.length; ++i) { - cmp.addExtra(comps[i]); - } - return cmp; - } - } - - public NotificationBadgeBuilder(CPacketRPCNotifBadgeShow packet) { - badgeUUID = packet.badgeUUID; - try { - bodyComponent = fixParsedComponent(ComponentSerializer.parse(packet.bodyComponent)); - }catch(Throwable t) { - bodyComponent = new TextComponent(packet.bodyComponent); - } - try { - titleComponent = fixParsedComponent(ComponentSerializer.parse(packet.titleComponent)); - }catch(Throwable t) { - titleComponent = new TextComponent(packet.titleComponent); - } - try { - sourceComponent = fixParsedComponent(ComponentSerializer.parse(packet.sourceComponent)); - }catch(Throwable t) { - sourceComponent = new TextComponent(packet.sourceComponent); - } - originalTimestampSec = packet.originalTimestampSec; - silent = packet.silent; - switch(packet.priority) { - case LOW: - default: - priority = BadgePriority.LOW; - break; - case NORMAL: - priority = BadgePriority.NORMAL; - break; - case HIGHER: - priority = BadgePriority.HIGHER; - break; - case HIGHEST: - priority = BadgePriority.HIGHEST; - break; - } - mainIconUUID = packet.mainIconUUID; - titleIconUUID = packet.titleIconUUID; - hideAfterSec = packet.hideAfterSec; - backgroundColor = packet.backgroundColor; - bodyTxtColor = packet.bodyTxtColor; - titleTxtColor = packet.titleTxtColor; - sourceTxtColor = packet.sourceTxtColor; - packetCache = packet; - packetDirty = false; - } - - public UUID getBadgeUUID() { - return badgeUUID; - } - - public NotificationBadgeBuilder setBadgeUUID(UUID badgeUUID) { - this.badgeUUID = badgeUUID; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBadgeUUIDRandom() { - this.badgeUUID = UUID.randomUUID(); - this.packetDirty = true; - return this; - } - - public BaseComponent getBodyComponent() { - return bodyComponent; - } - - public NotificationBadgeBuilder setBodyComponent(BaseComponent bodyComponent) { - this.bodyComponent = bodyComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyComponent(String bodyText) { - this.bodyComponent = new TextComponent(bodyText); - this.packetDirty = true; - return this; - } - - public BaseComponent getTitleComponent() { - return titleComponent; - } - - public NotificationBadgeBuilder setTitleComponent(BaseComponent titleComponent) { - this.titleComponent = titleComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleComponent(String titleText) { - this.titleComponent = new TextComponent(titleText); - this.packetDirty = true; - return this; - } - - public BaseComponent getSourceComponent() { - return sourceComponent; - } - - public NotificationBadgeBuilder setSourceComponent(BaseComponent sourceComponent) { - this.sourceComponent = sourceComponent; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceComponent(String sourceText) { - this.sourceComponent = new TextComponent(sourceText); - this.packetDirty = true; - return this; - } - - public long getOriginalTimestampSec() { - return originalTimestampSec; - } - - public NotificationBadgeBuilder setOriginalTimestampSec(long originalTimestampSec) { - this.originalTimestampSec = originalTimestampSec; - this.packetDirty = true; - return this; - } - - public boolean isSilent() { - return silent; - } - - public NotificationBadgeBuilder setSilent(boolean silent) { - this.silent = silent; - this.packetDirty = true; - return this; - } - - public BadgePriority getPriority() { - return priority; - } - - public NotificationBadgeBuilder setPriority(BadgePriority priority) { - this.priority = priority; - this.packetDirty = true; - return this; - } - - public UUID getMainIconUUID() { - return mainIconUUID; - } - - public NotificationBadgeBuilder setMainIconUUID(UUID mainIconUUID) { - this.mainIconUUID = mainIconUUID; - this.packetDirty = true; - return this; - } - - public UUID getTitleIconUUID() { - return titleIconUUID; - } - - public NotificationBadgeBuilder setTitleIconUUID(UUID titleIconUUID) { - this.titleIconUUID = titleIconUUID; - this.packetDirty = true; - return this; - } - - public int getHideAfterSec() { - return hideAfterSec; - } - - public NotificationBadgeBuilder setHideAfterSec(int hideAfterSec) { - this.hideAfterSec = hideAfterSec; - this.packetDirty = true; - return this; - } - - public int getExpireAfterSec() { - return expireAfterSec; - } - - public NotificationBadgeBuilder setExpireAfterSec(int expireAfterSec) { - this.expireAfterSec = expireAfterSec; - this.packetDirty = true; - return this; - } - - public int getBackgroundColor() { - return backgroundColor; - } - - public NotificationBadgeBuilder setBackgroundColor(int backgroundColor) { - this.backgroundColor = backgroundColor; - this.packetDirty = true; - return this; - } - - public int getBodyTxtColorRGB() { - return bodyTxtColor; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorRGB) { - this.bodyTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setBodyTxtColorRGB(int colorR, int colorG, int colorB) { - this.bodyTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getTitleTxtColorRGB() { - return titleTxtColor; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorRGB) { - this.titleTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setTitleTxtColorRGB(int colorR, int colorG, int colorB) { - this.titleTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public int getSourceTxtColorRGB() { - return sourceTxtColor; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorRGB) { - this.sourceTxtColor = colorRGB; - this.packetDirty = true; - return this; - } - - public NotificationBadgeBuilder setSourceTxtColorRGB(int colorR, int colorG, int colorB) { - this.sourceTxtColor = (colorR << 16) | (colorG << 8) | colorB; - this.packetDirty = true; - return this; - } - - public Object clone() { - return new NotificationBadgeBuilder(this); - } - - public CPacketRPCNotifBadgeShow buildPacket() { - if(packetDirty || packetCache == null) { - if(badgeUUID == null) { - badgeUUID = UUID.randomUUID(); - }else if(badgeUUID.getMostSignificantBits() == 0l && badgeUUID.getLeastSignificantBits() == 0l) { - throw new IllegalStateException("Badge UUID cannot be 0!"); - } - EnumBadgePriority internalPriority; - switch(priority) { - case LOW: - default: - internalPriority = EnumBadgePriority.LOW; - break; - case NORMAL: - internalPriority = EnumBadgePriority.NORMAL; - break; - case HIGHER: - internalPriority = EnumBadgePriority.HIGHER; - break; - case HIGHEST: - internalPriority = EnumBadgePriority.HIGHEST; - break; - } - String bodyComp = bodyComponent != null ? ComponentSerializer.toString(bodyComponent) : ""; - if(bodyComp.length() > 32767) { - throw new IllegalStateException("Body component is longer than 32767 chars serialized!"); - } - String titleComp = titleComponent != null ? ComponentSerializer.toString(titleComponent) : ""; - if(titleComp.length() > 255) { - throw new IllegalStateException("Title component is longer than 255 chars serialized!"); - } - String sourceComp = sourceComponent != null ? ComponentSerializer.toString(sourceComponent) : ""; - if(sourceComp.length() > 255) { - throw new IllegalStateException("Body component is longer than 255 chars serialized!"); - } - packetCache = new CPacketRPCNotifBadgeShow(badgeUUID, bodyComp, titleComp, sourceComp, originalTimestampSec, - mainIconUUID, titleIconUUID, silent, internalPriority, hideAfterSec, expireAfterSec, - backgroundColor, bodyTxtColor, titleTxtColor, sourceTxtColor); - packetDirty = false; - } - return packetCache; - } - -} \ No newline at end of file diff --git a/gateway_version b/gateway_version deleted file mode 100644 index 6f96ed08..00000000 --- a/gateway_version +++ /dev/null @@ -1 +0,0 @@ -1.3.6 \ No newline at end of file diff --git a/gateway_version_velocity b/gateway_version_velocity deleted file mode 100644 index a5ba9325..00000000 --- a/gateway_version_velocity +++ /dev/null @@ -1 +0,0 @@ -1.1.7 \ No newline at end of file