From 173727c8c458b22736b6521c445f9e95fb6aa762 Mon Sep 17 00:00:00 2001 From: lax1dude Date: Sat, 21 Sep 2024 12:03:57 -0700 Subject: [PATCH] <1.1.0> Add protocol V4 support to EaglerXVelocity --- README_EAGLERXVELOCITY.md | 200 ++ gateway/EaglercraftXVelocity/.gitignore | 9 +- .../EaglerXVelocity-Latest.jar | Bin 287884 -> 609633 bytes gateway/EaglercraftXVelocity/build.gradle | 43 + gateway/EaglercraftXVelocity/deps/readme.txt | 3 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 60756 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + gateway/EaglercraftXVelocity/gradlew | 234 ++ gateway/EaglercraftXVelocity/gradlew.bat | 89 + gateway/EaglercraftXVelocity/settings.gradle | 2 + .../gateway_velocity/EaglerXVelocity.java | 56 +- .../EaglerXVelocityVersion.java | 4 +- .../api/EaglerXVelocityAPIHelper.java | 1042 +++++- .../gateway_velocity/api/EnumVoiceState.java | 22 + .../api/EnumWebViewState.java | 23 + .../api/JSONLegacySerializer.java | 27 + .../api/NotificationBadgeBuilder.java | 361 ++ .../event/EaglercraftClientBrandEvent.java | 87 + .../EaglercraftHandleAuthCookieEvent.java | 205 ++ .../EaglercraftHandleAuthPasswordEvent.java | 35 +- .../event/EaglercraftIsAuthRequiredEvent.java | 11 +- .../event/EaglercraftRegisterCapeEvent.java | 17 +- .../event/EaglercraftRegisterSkinEvent.java | 24 +- .../EaglercraftRevokeSessionQueryEvent.java | 90 + .../EaglercraftVoiceStatusChangeEvent.java | 64 + .../event/EaglercraftWebSocketOpenEvent.java | 66 + .../event/EaglercraftWebViewChannelEvent.java | 56 + .../event/EaglercraftWebViewMessageEvent.java | 119 + .../api/query/MOTDConnection.java | 3 +- .../auth/AuthLoadingCache.java | 10 +- .../auth/DefaultAuthSystem.java | 8 +- .../command/CommandClientBrand.java | 82 + .../command/CommandDomain.java | 5 +- .../config/EaglerListenerConfig.java | 43 +- .../config/EaglerPauseMenuConfig.java | 251 ++ .../config/EaglerRateLimiter.java | 9 +- .../config/EaglerVelocityConfig.java | 105 +- .../config/ServerInfoTemplateParser.java | 258 ++ .../config/TestOutputStream.java | 31 + .../handlers/EaglerPacketEventListener.java | 126 +- .../repackage/lang3/StrBuilder.java | 3136 +++++++++++++++++ .../repackage/lang3/StrMatcher.java | 437 +++ .../repackage/lang3/StrTokenizer.java | 1124 ++++++ .../server/EaglerConnectionInstance.java | 4 +- .../server/EaglerMinecraftDecoder.java | 3 +- .../server/EaglerPipeline.java | 129 +- .../server/EaglerPlayerData.java | 404 ++- .../server/EaglerUpdateSvc.java | 13 +- .../server/HttpHandshakeHandler.java | 24 +- .../server/HttpServerQueryHandler.java | 17 + .../server/HttpWebSocketHandler.java | 533 ++- .../BackendRPCSessionHandler.java | 307 ++ .../EnumSubscribedEvent.java | 22 + .../ServerV1RPCProtocolHandler.java | 439 +++ .../GameProtocolMessageController.java | 302 ++ .../protocol/ServerV3MessageHandler.java | 87 + .../protocol/ServerV4MessageHandler.java | 180 + .../server/query/MOTDQueryHandler.java | 5 +- .../server/query/QueryManager.java | 6 +- .../query/RevokeSessionQueryHandler.java | 74 + .../server/query/VersionQueryHandler.java | 9 +- .../server/web/HttpContentType.java | 2 +- .../server/web/HttpWebServer.java | 23 +- .../skins/AsyncSkinProvider.java | 4 +- .../gateway_velocity/skins/CapePackets.java | 70 +- .../skins/CapeServiceOffline.java | 75 +- .../gateway_velocity/skins/ISkinService.java | 15 +- .../skins/JDBCCacheProvider.java | 8 +- .../skins/SimpleRateLimiter.java | 6 +- .../gateway_velocity/skins/SkinPackets.java | 211 +- .../gateway_velocity/skins/SkinService.java | 854 ++++- .../skins/SkinServiceOffline.java | 66 +- .../sqlite/EaglerDrivers.java | 8 +- .../gateway_velocity/voice/ExpiringSet.java | 6 +- .../voice/VoiceServerImpl.java | 183 +- .../gateway_velocity/voice/VoiceService.java | 64 +- .../voice/VoiceSignalPackets.java | 195 - .../config/default_ice_servers.yml | 4 +- .../config/default_listeners.yml | 4 + .../config/default_message_api_example.html | 68 + .../config/default_message_api_v1.js | 63 + .../config/default_pause_menu.yml | 43 + .../default_pause_menu_server_info.html | 30 + .../config/default_pause_menu_test_image.png | Bin 0 -> 1258 bytes .../config/default_settings.yml | 3 +- .../src/main/resources/velocity-plugin.json | 2 +- gateway_version_velocity | 2 +- 87 files changed, 11988 insertions(+), 1102 deletions(-) create mode 100644 README_EAGLERXVELOCITY.md create mode 100644 gateway/EaglercraftXVelocity/build.gradle create mode 100644 gateway/EaglercraftXVelocity/deps/readme.txt create mode 100644 gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.jar create mode 100644 gateway/EaglercraftXVelocity/gradle/wrapper/gradle-wrapper.properties create mode 100644 gateway/EaglercraftXVelocity/gradlew create mode 100644 gateway/EaglercraftXVelocity/gradlew.bat create mode 100644 gateway/EaglercraftXVelocity/settings.gradle create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumVoiceState.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumWebViewState.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/JSONLegacySerializer.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/NotificationBadgeBuilder.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftClientBrandEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthCookieEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRevokeSessionQueryEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftVoiceStatusChangeEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebSocketOpenEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewChannelEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewMessageEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandClientBrand.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerPauseMenuConfig.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerInfoTemplateParser.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/TestOutputStream.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrBuilder.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrMatcher.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrTokenizer.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/BackendRPCSessionHandler.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/EnumSubscribedEvent.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/GameProtocolMessageController.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV3MessageHandler.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV4MessageHandler.java create mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/RevokeSessionQueryHandler.java delete mode 100644 gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceSignalPackets.java create mode 100644 gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_example.html create mode 100644 gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_v1.js create mode 100644 gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu.yml create mode 100644 gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_server_info.html create mode 100644 gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_test_image.png diff --git a/README_EAGLERXVELOCITY.md b/README_EAGLERXVELOCITY.md new file mode 100644 index 00000000..8711c9f2 --- /dev/null +++ b/README_EAGLERXVELOCITY.md @@ -0,0 +1,200 @@ +# 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. + +## Compiling EaglerXVelocity + +Minimum JDK version is 8, 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. + +### `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. +- **`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. +- **`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/EaglercraftXVelocity/.gitignore b/gateway/EaglercraftXVelocity/.gitignore index 512a13eb..1d62218f 100644 --- a/gateway/EaglercraftXVelocity/.gitignore +++ b/gateway/EaglercraftXVelocity/.gitignore @@ -1,4 +1,11 @@ lib/* .idea/* *.iml -out/* \ No newline at end of file +out/* +deps/Velocity.jar +/.gradle/ +/.settings/ +.classpath +.project +/build/ +/bin/ diff --git a/gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar b/gateway/EaglercraftXVelocity/EaglerXVelocity-Latest.jar index ab5a03d58e2e6052bc6019bba64e875a45b61648..e2280916ddeca6541889b9f9bae6713aa4638418 100644 GIT binary patch literal 609633 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�PS*6W4+CPAWFEJ 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

_4Y{VyYsbnOsivO3 z@Xm>vVvl6$v2CgYgrNCo7s49Lu3^cz`H>?fGodUbPFwrdeaX(J|Bax-?^kXU-(dBK zBTne8C2j!s4R-Wi%)#|^pH~+SP92K-9;iwUdFQp_hA`}$-UldOQ0HOh_C$ooq8voY98d4m6QjHe&qWb*lw{K6S+EDY zh~<|jyM%HO^w_>_eoC7x{BND9U1HXSi!kzd$444hJ`Nt#u?5CJrxoYArI%w(n_o6c z1EWym2j_Vs>3n|I?SGCNjy~v zeHbi`(05%hwPP|0MA!@4CLb#xlL0w zot=a3wMl=gS)nt^JWl??PsADH=-+j##xN~&wd)F{)t};cqq#0711|)I@pQ~K8-plQ zrz>9olX#{nzuJd+hmFdzBME-@renBBER|AO@}JirLWA4c>7t`n}`uc9bKvz2yG zlKK~ScAmq?*wRXvhqqKB*1xhwNgZd{sph(D>d_d~IVRd!`8j2jY&kwv0}!9eWw<7* zvWyh5Ny(8DNZ;Zs+8%406~O2jyIirIHR+su{E>LPlEO1=H_0Q;8-J9u?`oAOUVqFJ z*}dx(`-fam>Zu}pVPvcMuB%M7Q&!o=Kn1}u=}k>l@R>Yj${i;JS4Pq0J+0qpS3)IL z1G+nt$5SxrUsg6U%BEfR45R{arvR>$#fZNg4(j-K6X{%pkI4O_a8`)Zu3U-{)061@ z@Dnxp4u#7qj1SrtCi?ne$OBpS z#@Zj)+_b<$Zlgtw)-RwQP>xi;N7|t8w>A* zDB0Ws@elZT5C#%Gj|`rB%Xb6*O+8;lQV{?q;W4 z&hU;@U}m-Z#a{NEXFz!7$4Xm*ft$Vvh^7%;euxElNC9iG2+j!&jA1fmXq1Q{s!J@J z!~%ce}SKZozC=hna z^}HRdTURo}3MxGuff(8Rr}8l1hvRl^RE~Qzi%1Kv)aRBRimzJTK2d^&cMh%8Yk^3Y zgn~^JoefaL1#P1}GU6-#c$_w(1+A)t_@wj%D#>CAu zJp?)>FC21vg*YDKaXb1DtrWS^8s}zFF3?{KYMC7UxW0$)?3hCIM&m^R`K`=X?xLa2j z@~>z%L`|Ms|4DRR_|2PXBhtT5L5JO6_+`e3`C@(VP2ci4c39|Uz2G)LqlTgU4Q#3OYqt%}2AF*2-I3;L#44aLWhY=B)YGXGM6co1-> zb9M8?75hfLQ&#&kHsf9}!#u8n`!Wa!kAhJ7dUp+MMBT-27RZHRMk~ETOJ2Dvk=A}+a3B;|$naI0fJ<~xbA_*S zy*q#Bj7q{vej^Ra=7Kt@o5wu=c~hJk0fR-ui5&Nr%nCP-;j+HbI))QiIm9OxsM9WY z8)EXu#c#W-wCW9}Hm#C0e5p9u8Byy$aIXwBzuW`9*LM7<(a!ThcR5mmiQ%0*k+g1I zEG8TC(#?gD9aDU~U%o7qoq$3hby~zv zuhBJdh6{6zBrlqAKr1N@LuZ3k#-2mkp(%+K%ZHb2HJ4cQUR|8GnMtc$4iEcWDWz1} zhrJ88=IfeM^>rkAk$Pw6x&0pD{D*WiA$9%loUYmcyzEjT{_p4?Ou8cWYv084o|C*+ zX;?$UH$BS*h$N@?d~*@bs1;B%e{kM@#J=~3I|>)o(gWP)a9%B$u*A4D$XC7vc)TH% zRs=^3t_7{1)G3Xwg~gvh9!v-X{hye!roRvhSBTo8ePK{nj~OF;1Q-yt8st&OoZK0i~Km z?9UP1*i9wln~e4SFn80VbWjbchv>v3`V4Vv$9AnX)%7)lWxN4)5SK)X-Y0Hfs_@^D z6``3G$R%eY@cg^#F>|UIwe@Y~4J~==-K?9JckXXc30HG#C`}9xb`8QVjXvCbYC&6@G$YV|R<1`o8?{jxBMy>TF@;rJ$!?L-=d=_!{Z=}EUpQ)m( zOcIvOXL9nyDL`474aCg#={AOhaytv$Pp=NVoKjre7vni(!o-ERxC-1FQ#%aZdGTj8 z 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

At3@^ZntF;l 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 z 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�>sIvFLriH`n2);Ekz!+`#Wkt;we0hK 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%0A8eLGHj8c0s!_3i~`|1T1%Il9i)Ds`xp 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

md8$M1{iosLkyEe!>$eD@X z-FUHad&lxg%(z*|s)qxFY$a$9;kJ*wApAXds`Si`lT5<>XK#j*nO>NzzedpX`{csc zuwkKO9>;-6j+UDVo{%9jpOrOsT}rf_kvR{Ms7x`FWpkW0>TW73i90A!R=_ zJ!DA1{d@1v&CP)c(p&~l2kQd)zde~kZn2?zhHlJK%3cx2mWs)$GcEUDzU;BkE##V% zm*~@(oqY<|<~AQ;MKalM`O*HCYTlYCie9}Z1o0oxqtM~#VT1*R-sz$$6>a)|DHVMs zDaxvI+U|oEMRMC-D17PM_Vp3%=-0l%c}RCkH9Z=_FwPo&ukYbIxA=uJl}EntTXn2q z@W8O6A&$~z9)+N0#iB>PFTG>H=B?m|f(dw_3R zl0zpc`9(aLH$cKH>mUI>ZtiaH6a}wFy0K7@jMAi7P`YQ)bceXaUe2hVREZ_a^`f-h zEp?y6fSr2mYgc4fVWKQKv-sqk*rHG{PJNzy0VC>!TYyS^ulmS<^Tm5Vz=pUL`$Y|0Nh?SWF zLojv6X&~@0H%+GC7_lx*0#?O}b2>!;O`UNW)i$=X;Z#{NPj1Nw`NZNZg`qo%MAG0y z!JYcU>V5m{u)h0Kqj`x8wVsS{-V6;n)3b^MzSo0P*XwJqfp=$qyG7%nph_hBUS&iL zxp1hq@z{_9Bx510)j9dVX=%4aP_@i4#A)ZC@vIG*UOtIM0|~7Q$IdaF z8LTep1;ATAZX%^gB8VWxRcDt2n=-Nt#$^N!uoyU~}^> zpNN^nwLU`g*1GxYR)G^_YDD7e5R(_?kLJFEd|OfXM;WE(itCU<*2qop41LRJiF6xl z%K6K-2Py4aqgSy0%;;i%nGu`U@~Oa<$=H(P) zOMicpX5HtS@TW9|z*A2`VYNO~hZ~3*q$84nr+2*Y~kA1Cgs8 zLMj}FM7pTa;Gd}PYbo_mrQLcQY1YbY3Y`CDnz2Nv7T4}#@~S(%b^8NZYeAc!X;muq9RXxnjWIG1w{3qB)c9C>o}g{V*0$$>R9r z;*PAa0PDD)kfSJ-o;r~zjZtr*?nZvhxFTzT=BjRY{}DfdqFPz-#Y!nhCN#Nt%Znf* z1~wyuS)bgxLi{cyjAW#NdTb8+JMLWxT#HN#%*zVB*SAn-)D~Lg^Z5cE+bd=JWt{Iu@@kl)BX_5)A}3yTMk5;oQY za0wfW2XF~1OS<0zHkP-aIc(HV+uU?HW`-;|yH;@C@c;IDFFSw9oj*{4kGK}Cfno!d{VF${0ExF`x%mmt!z!08SscZSl zRi+@T^k`goxj6deYD8GXOaA#~S8DQbn)#$A6K9mWmIAK{`Z%u7iZ(xtbKJ&t-z%d= z*^8k$xnw|g_&h*I-KO`s&_1tP;9RQ35XdyzG1!3hB$H#f2;TH8!}HAbo<>%Pb$U>e z#Q>Jb3!ARvM3CNby7=$Ot?+R@D|`Y2{-f%#4!tC zCc+!99v!9Lr}E_W;MppZ9R?ON<~%q!zTX+~C}EvF^8{N-niW#6Q8qs28&CsT3ku|6)k%e7ASVT_{RIF5Z* zns?*)*q*xPEz&V}+AzWTc)AmAs+mNG5PN7b3T)0fA7+jMbc@~5)PnD9?L-Mh2~}UO z1>Ar`lbojL=PCXnFoV6@Wz?%JMHX@K(@9iQ%^Zeq9-@aUyjvJPH$2$R*4tPX$TZh7 z|I9~L3h=Rh-z>h`nJM~|8?Z$O`;&!X_;B!Gb(b_u&uN8Tc;_*@6UAN{$u1#%&$H1( zAH@$6Y;PHXiw5wv6w&WDdh5&YJl~hiG(=BA^<=y5ciW(%=9}u|k*_~{43;i2RjJ;% z>a12D4+kD_dBiy%P8RJjga7-Y@CgfnCf6L%aSIPj{WwW=Wr(L%J4h!H@$D9RaWcw z2UUnv-?P1t1wIP{_px4QxH%n|U+gw^$VICWh*P2VDvN*4wAhnsfr;#Ns)CK%KJSW_ zSq}EyN>7syfu^g#MAaWq$`l8nKHH<1d%7KZY?0vnJxTX%i2JvE zMx7nZ929zQ#MW58`uI|JM9~Ao%t$GDi5YI-ic?*gLI_7E*st`tV6@7T7afV2_GG*_ zNZ~t;$^o5F1Mq#fSQKu1%qbeblGy%lqkkat4y)_g*=d*73I)D8cCA$rZJ$abT!v=4 zI$7m4RQOgQ>;TJrq{#ufI^pWm2LeBV&PzMH7xrFflVaw8%stNMMaxU^Z>UzJ6vH*cvSGtqFzqmy6)T%ThCT5$i_P%XFmUV0YS@)1`Za4d z$rRycjT_Mi!@W+X1Pftms@au5+TZ$Y>$FNTnecEtN#)s=jX^ZH)KwGzHnx$GyhGj* z85|Y*1ch&$*BEeZ$QSip&W$g}EL5NB#AlHJNFqyI{T}t83LYp;Xw; z9ms3-ig6Y^p)cQrdK#%c0vhzE6-yJwlzOkMgUxqJ9xq7b8?SCyTGI# zGsJPuIO!?+a6$MRaBR1WBG?%@uE4v5SS+9IG6~mhJk2gRulthldtJiBy_~aOmXFnW zg+u$y^QsA0qKg3wKOoz0q$oJ{oSy=3qelx3{$;CK#V7C4nH>QiGW8>P-2J6MozS~9 zv&OF4HNG$3rp&gn%d?PBJyT7l_C6&k5mZ$rWp&8KKm+n5DJgKlLBPnlcQsmiCOUh- zrLJGgUQ?B#Q)B(HO=e>qpQfHRs3kwQ=ysSR_jWj?Kck6%;vr_+%DBR-oEwsyzJhbO-ydlQ)8n<9Y^N`y_Av< zG|UHE3e!lHxZ%b`dB|6G!S5kI<*$1m=Eo?WaC|0PAM+Vu_!+5gm5AP?hLt}jQ=qp0uF?SXv&o56b6uKUghHlM?8v41*lgX4y8!j66I6ujs} zdjhD?Y2JUiRUj}z;L!cj3+?}#g^55|x`@!9Xy}GU3|=y7pw-p-dgYBxzJv$r(6HxQ zLyB^qP5A{byRSK7T(j^srOR7M5IqlklEsj_0=gmb^YsahMa$DGsk!iJC10l&8=b$; zG)0@#&iWH;y_KxbISWH0tJ?6`X6YilbKV0(gq+*m3Gj z{j{5TnQOi3aC`qWCpF>|6ZsBZ^CYKitVJF7b7|^rq<VOP8HJTXY&_F#HW>Yj+`)eByPoDoz7BgM46o(LH%AAJsrUI(xQ35ly=vC6pvI-w8 z(c%8Vl$+AZPhdEKt&Nh=X4 z=FPVal?G?bscoU&Tc>?v83r9^8(k*%7At&bddauHIBD;ns;LRo@H~~2Wfg1aR4NTg z;LkTnA@lcumtV5$LT`A>^iN zzS4Nbe4Q+eyrt#=c-l?L8~XujPz;*tqfF;=2QOC7S;VC3q(3VS9M-9dT1A5Q*`Bv# zZsl3CAZ_8B;%dfbE!E0S~LvBLm$>85L2m}CCDoA5@QRcg7mQ|+s|hcfkqnLmJRYYZ`eThNEA z&*9t`NbVjYEd*z-kVmgRu1JR|H8RxHU$S&xU$(N3EeuvSg@|&@jH@f2$XoR=AkI%5qL$o9J zduDeHAAvG9$2B!KIuJtlq}=-nX+tvBFOYw{gh{<%O@h&jV|=48cUoQzV{}XI@jUTQlt}j}3OT@~tpgb)-P-$)+B3Whm^dspIgc)8 zmflw`0~nzJ1s2t6Bc-e^3cj?FI2aMvqhB+3C>gp)9BDEl6+#>yqA2`aJdUTYo z=A|cBaNgRykOG689E;~+<$FRE0zo^J9^H^Gk<~r2D3s94Uo!z~i1@=XU_YfnrV+rK zmCU+WFHP<6mzcrAF-d8JMk(N!7#ks#t7*)7nq;yI27||7aZ*vEBohgPzv-a-Vv<6C zV}C3wyv``qGgwKr33nVo&s<(UeUH9v)!$*7Cc4+(5`Q}vgVkiMS`-#MUhY*?DfU%b zsVQAbgK}Cq*!m#A&WQQj8@-!6R#U46 z31e2%nGuN6jSDIx7a?_)R}UkL{)1@u+D8ciqfRR;m#n!9qCQ3D(uBpQHZlc!%O0&q z07FnxEaB(CD6!pvzgXOeAx|_9;(^3r2IDlrPWT+fPpP z1Cc{+MqNSO`cIBI3Jsa?!9+?(* zad zK*@yG+L|@|FitgkKss;c6Tz)m=oG~SBOB8P`KWr6Or}JJTl!YLyQAV81HtQg{iOHx z`3(M>w2_4bV?8@IctY&K#TZ)XHk05=>`V$ z>b{f6S&L}NbL7!c)^o7lmP(^>bA;E+A}zRb7f^<1C3o4uNCR<-PCUNLeQ3M))1bhsI`g~|X0K6Vi$L5xQunj`yJcz=S-3Gn{`e7)j83ci2;8}5z6W34b-2BV z8He9|1v=RuT+W|qs zN)tPivtnQto__px;MbJ7sqO4j0p5MVhCjFLnpJuE`rSq^ZceE&&G`fZO%Q}gZEDna~5x5j^7YX1+n#=oSt>EFo7 zJsNo$Rlx&5R%pPw3?X#t*G8nqgG7B;gnn?w1pfplqp5OVq-o#|y6k_zbngqX4XarR z&JPNNp@WnKc+M_Ic@D~?vsq_0n`bnZEfmXKkqsYuH*~bmNBeG&dQ3j6q%dXtg$_bC1VY%yX030GDi#gFN9mn;#u%a#G>-wIvBUmmW z*U5WW0mP%U(gjk>F@tR?b-K(gV~Wy1&U#e^W#wa<5V0)iY-0>vNG_}DM^=QTr6SCO zcWh{gIVJ+;#Aysw5O9J-Jl$D)@a8j9C0A9qyNmr__RSZaXXsd$56V_-B+QBd$t_rT zwjyn7d7=fVK~bVHVz3o)spR99*dj;U%3^IP-R85r+S}aqG7lpf#N;3YCVE)3 zh8iqF-}4P+`QK@Qlrm9EwAhf2mUL-xcpAt3R@$TolKn8A(#lamX_<&&L8y~{8E;UQ zs+ytDPz}gbT(zw5ffcCI0(1r*G9<-IWL%o81q#+t7J-}hjZV*KfB8py%xa+F+)yS% zq%Mu(fG}l`EmBOHF7md@^IXhml#Yq`tp%Rav52hbD#uJT%`^5L0+GyioEq z`&=&dRhk>j*PAt&l#?_rO~fo1I_{rJWO}LRHzBuJ8l+HkC9P22WiN^4%YL)~L-7S+ zV?s~4vGjY;;sgoip7s_+^($ziY|>n6meqW(hb`M|uIet&>kCp1GzLj)LBXo81^z6B z34)nA%(B=eNH85Rp)G*RiJ~w__wFPQO9`9uLcC zg1k_PKb=#9xoi1cpy~>nU=n6GU6Rtz6SNRiFRYgO0~b5hUNB7Ms^ie5Y1@8R8eQ)L z3Z(4VqQe6hFV$gF4#h}gwLaX|1cQ((PBuYUOb<^`^_{9+yv+$Tw8(QZOV2rsTdk~G zq~KwsHhlPTx8J*%(IQWp875{h;6Abzm1H)Gw+MJ9ZJ3(MN}z8FR|dX6M>+?X@C-y? z8Y&FZ?e-w>lx{h)cUw{M%uG&cCk>@6#t5%BtY-WP2VN0o z(AF!A_MvviwSXy&!QqO7*)gS0!bD=2i6W32BhQtn7U#9pPx_5>e4W-?$UD1AuihuPVMW5QN%M zw3B5ZWxv|i)oZJgl>fsE+7rXC@3fa@u?Q1r)SmZ7?|c|J{tPX6g8CUpkf^1Gzlv9i z8h0uuyx?*7TmsciYp6IK-43Sp>Pv>Di!T0%4)qsl#{g~rtTD3I4TfQy#1@C{D;!bJ ztW?8NhH&`T)l=6P#hGZl^Ipem_vjM(;eqX)E0Yfc3S@(oQs2%&2piIHfkmwQ1s=OI zJ}FovHvs59{*Ji+xvtW?m#)1FxRZVL9;4JI%7WGGOf*LP^RGf5KP0d-Nu>Bs5*!!( z_n`>7&JbTz#dpX&Gr^xWzQ2sYZuWLiKDm8{1-OcxVd=zADR9^`q}2!kMkiUwdoe!; zVqQ=`alXt=qk(}rSr0nz&|mQ}zhqYLB~}z}r9SCD3_Xj3ase%o^%HTurwZD`A%VdX z{5R^I<3aGZ)OoLZ$lcy;OZOPmkryDqq&J0N2yt{ey&{BZwI5xZ>Zt*H-!UXQOPrB$s(^% zP#p`Um`yi3AX%WEc4{VDry7Dt@++musm@JfLWK$1r!hiJ7ir++D{6;)fCl!fq)u!* zrE-{HF*Q5l^$HbqJhPYvYlo4woezWN>(I9 zMXWZftgu{D(deit>b8(mQV}u&HaG%7u%e(${^FrB;K)-HH2j2!UHh=@kXF@M10Yq& zk4jNzVD17qzCu(IJF<~5nOsb{~VrQ0Fe$B zuPACSE49mvTmt<2u^@IsiM{%{U++?qO9K@=cF=PvoXLw^1_wfWdj#0IsOS*58>AxF zn}HY`VcT8BTf3!m^^Z>?FN3xc+k|aFDy_YpQ!Yg28==*^)4-b@G+Gbsr|!T?*4Z0l zVJRKOGn_byOpIs39L;GV6@vvCVsp4?c#JQ8+3wi#S{G{~ZwL&Xn0l(KAc%>W3$CnA zux_5nGm%j)w)Hyi703o9*po5jb4cYsp}^oA?FIA7tRyuOe$q%9kZlf8DY2h283fiS ztN3EK31!r>gbRt;jqviMv}yyaFhb%_LdR4R@XJqi0_xu!;Z7ZCkUxgwoObUcEn4icyn_R#j>#T#%T3Y z(TG_Xlrs+}$h`~pM|+ssdIk<~3+l|Uky6PGAK3fqsG9Byn ztXtYmCH`Zb27ZvN<^0lGvck&q3(~1k2uaf7(TtrVsb4EX9JMkqM?eKhR02WkDpR2~ z@E5p0mX93}5FGkItxbK_xy)b~dm20)j@k#lP(V~+n9+*ZveTZQ@mwPj8NvG$1)IKxf zxrC`4unp&QkgKln87+6rXO`><-VcX-7(7Omi*p+6(?RHFPgt=ySLV=Z(-hY=vgcin zY=Gq_q|22Xx%Fyh`he8N!A1Y=GQAFuMx5n{2&t#>b*$bP!> zzGml3?#r9d*WF?3{gk1sD7H@qqF5FURPBUAwZ37|{iPDwv}dsCno!I6G>0v6hX?BR zCfSo0q|at__o%?VdPg%IlhW@KJaE$+LlsxqUcT(U?iVfVWG=GM?6_Dqpe3(O#r zZxRUWS?@(J+j30U@EdnxaaESQQuj}fv;Mpq7gJm!gS@Jt>x**ZB+xOEp^0pw<(82% zYY8=N^B3T#CUZl?ukNwe&WFTi^}o~XwBsn3kEf@Sb$XPV#~HZzB$PK|kDW=(z#IxQ zhBpwK;|kVx&vAyU;^r4t#Mp>Wdq%1jSKF&3(|hftA7$#p&dAZFwkY)F%UEB+u@3uc8Rl)n63ygnoFj4w(jSjhN| zr1+%Zc~%5%hDJspIw81!j(dYd`%inJa*L`)_u=cA|IGabdK2 z9;1$9%S~K=WHL_pO_?Etjzhv;c$6~xu39u52kWiPuP$k}dS)7At%G0y=qP!jMB;9; z0&%{=kmc9#q+|TEs#@(05I3VvlAYs{*h)XoA=-e|r3a(;ErH1=W;?B3p!CnH7jTCY zBI=~lE1`+bk(4WRd{_`8$fH%Ybh6kWj0Mu0qyT=g9UA`+T6}je%nWkD6Omhz5tX!p z6O1{(Iqxto#ujHrLso2Q`AYH?f>w0w;-zAtU5Th`D0aPqOO4o|IXP}mF zQ$+((Cz4WA(oN2I>*Hjm2X*?=-P+?wN9bHGtE{WM_W6V)`(~UV#u?jbJ#_n3o=Bk-byUugS|!p z-p4-!37wYMQV8(h{ASYsmnvcR|9t@Ptx5p?iE>tOGPZa7Pc>87+St|ho9Jw8^p7N* zh^wKo?LX+w|DjjJj$0!Mz>CGsG(Mkq%_;i%ZZ_E~6>c@B{ zqojbOwgyOhy6@e>3O41rn?M)Ji9rKS&?{Q7HA+75Khu`B9pNaNE9*UnR-?)tMbmI2)&%RSRS{wlZZogbs$j6MH4Ha86mjMln= z;9!;Cb4?#y5A=*(*75#BfQ#hVWGyqB!Lp%mjW({eD8)W*RtkS}`E{dvd=c0R$ZeiqW`><=(e<|e(t5h`(pM87+2f>#zWAe5c*7@(&k4|iF7~yvp39SWd^tJ zJFLLgXA5|lv#UCS;Kn%hm=oo zf<)x)?V0NKzV)|j`{u(Vnip0tHl>(&>{$Zakhc*@>BN<#)v zzwAACXILS%T?`bdF8J%4m;9@t2Bb0KW-%?|2Uu{^>monK&)$%>V%vs-h!wMT??=Jy zf>s&9BIWCwXCpub!;E6R+M;SKptoTq*zI8TFE7vdM?#v&U?DXk)MV(f$%5UuDpE1{eC*3XEVW|B0gcJB=9u!6B!6G#*fiC%%SpqcdQi;m{R~6kmy1zxu z?ZUF`JR7;2+;T2~ZspM_xvx|u>WQt8i=9(Ylt@md1C14ks7XyTWJaFyoF&BjGP**( zGUKTMP?eG|rQ{+fYJL!bigOf-nar+jjKTtw7Rt&hr#XsRmE2%C7L|Oleqql-Z)vF^ zh6;qV0rOLE&9}EEKMo@SPn`5ues=4=xol9S!A4F#!nxAjT1dqH&k@EMHof?uNFXXc z#ohYO4pR8o37JwuCi1i`c}?Z!M)T3QptT`U$T&nIYf%3!%J{0^Vd?gTmbxcHt?at} zZqj340gJULXfqI?w;)GJFv8aEKEXx{Al;zZJ)@t#Coy^olh!KAzlHOJ)q3mO%-SDP zlWJ%L*&E~YC~Uf@7tVI?i(QEi^WJzJxx zCmSadE|YBVRye)hS9GySl5UWMvfhDZ9B(yKNO{e2fuhDPuEcfdfn=)>$6LB@pcVH! zm7vYoQm&bKu-S@e^2`~aGTcm~M6%C_le`ak6f!wON?l`gGjtZ+W{#-}Ie}LoS+-C} z)c}`0XU9^dU$-i-#08asShmojGVHA-Mz$)wq&`D-aBHN!bd%aE)g8os`qgnOloLEZ ztKISwS6SR<>6XJY>$Q^#Q_ns4L+a11T6oVz9kl+NfRkpw0BeZ=r19djV`-P~I`aml zyoUjVh3Q!l%#;m|?!aY+xc}~vi84fjPyeim4Rwpvle0}`V>>;buF16)UYr#ICB3prv_)`=GiVnf@|(p8O2p7 zWE=f=B#1H3qszVk_L6PL$K2q;?YG``o;dqEB~2R3wMlXb1ubf)BuLh8Zp$i1fHBo* zgv^3HG5x%?Fdu4j;<5x+Gtg~wE2 z(J5=j4!gXPA!p3g9(QVZc@@xfvE{MlKWD^2-RQQKmF8dU$X#ifW)ox;PVV3h7_N7X z!sr?gu@_C_BX2jZnrY=F!ZnQO^0l#Wtu-~g)J}8s1fx^OnZKdRTyUO9Gfbj7xITNq z)!D77p31C`tD{*2Mw`1ncZI30j}gt&$6L?;lTr>(p_vuA*O&g18`SLntD>?f3U7DV z(FXq@*{Zy`RNtl*@uc{rH7I+wrOURwnFHGd$SvJ)H^$``UIvCC<&(FcZr!%X0$qAq z&xG{6i8d)=qrmEzi2#dtO#9FeJx=f7W(+m+t?*K>bzq?VamIKT?t+L1FdUzO z?1X}**oE4jfI7b$r6}+Zkzw6MYMz1K29&uQwyE+@%px(}FEKt)Y4B_uK)+TlogEr$ zMF}c7o?{a^2is0J=hom~bkHSmop^L_sW-BH@|P}J-(6^A-My+(=!}+uA)^tS@(p}L zged$wU@7Uk*jC}H8Rl5Bnm3}!CA6~el;yUlN=Ct;GB-k9 zSVA@pfz}GtqGtYVpSQqsjDP!NItC&nRq=O~$$nkjGTWUX z0tT36q%Yl69VqYLoAF=!j~QY`IUa?UeKmXE>>Xv?F(27s!%9kxy18bT4F;NlE`45;#>W z7=}ie?K%44;PoH(j+P==gz96C?v0ABU5B>o3{5C2dVPc*N*iH}gT_QNoW-N4s-NA5 zJkt7(ySL|RUK603cS2>l#NP9cy364&(LJYqcU?3*(#M4ize1NHgDcIJu^uNswU1NxQ`kUahpCs4jMW-wj?*hB{s2F6rHs<6 zD!v0h@}T6Zr5CA65d~7YRhMH>okz9^=}Hm=7OJD58Tr+KE^cL~xFZqOI<5vKi zdmUnfzW?Gk{6F>>Vd8Sg-Y+r>yA5B&s02mR8!?`Fk@ae6{x_>L#5N>X^2*kGJh|JF ziSIOvV-}1%2L^?pl%=S}uj8l3&6T)7Yx>2g{FbT@jDsXR$t;&Y^9yBRWVQQ0f|Rho zD-9Z)@vjLYc#Hxq$C4`#5c^yM6vCi(MHV32^+&wX3NgdB2SH$V&8x`A1Gz7$J~o8R z`mXnwK$(C~G8|_%J%?)J*DmWm$Y)FlIwx^ZqRh_I-#Yjm8`L|^Fi>&;1dY#D$*5jmd~*RB|)i+oIWAgOmY zeK4wofvXH$btcu?gO)mzRMzESs`E|WYtfc9pPY!QjSfadBBiY+A*=nVxyP0n#(AT6 zExf3|=K}@U_%P}Z9vZu^on$cCIDog9bNgh7iGw{OVHLIy>$NMi+otKoR7m=K^w|yS z&E8z!bP%-|TRLx^60YwO{gQsv=e+jg4N@gAnXPQ?#yo7=mFg4j#x179TEAy|tfUoY z-&H>=WF5&9%Hz(fzi&(Ke8uzH`DKb|`wrJr#7kuMO7>$1AM!Lc+i_3z5ocso?G<`M zGHlxge_LqvtAd*~h=b?XHM`k9f+0QsPGozp&_ioBiE z0guu?z2tXU)bad;vheP9BxTWAWI=k@x1;HghYz=i9CgBVeV%NLN>A;)x;ykID;07S zZNg$eOB7^tCd4Vp6}z(6oPs#C1UYdKX{ic_QZY3DBZ0ySji^b^7xMi6Y1hJVm>nLz z!ze!^pHyo0xqz~CLy4@U;-%bCT<^#Skg<0y-6PP zS!ZH={+CUN1(*lvIUuTSkF+_#rFHP#9@0Fo@evav92fEUprky%4BQ~8?B^ac!+M-T z2**cyI1s~hm5;&H-+$TxMz-p5W1)ZiFvb197jJ;=ze4K&zl)RpVIopBHUQZCqs9F{ z*KUUYvJnAfY`)!hUg>mfp#-D}(Rb=|@^Q%e_Q13Dp(Xyv8uNn4%mxv`lAdWz;#s%>sG_A(mbCAY){K5!$AHaR!&1WPqF$vi36J96Zh zA!95NYN!GW3A56DsZ7_ z>n%hvk3cwfe4t%iL2Am~{2a2a7NpQZ(F0N5g`P-evB}{RjjAsk%-x5WXWX zvriSg1(-l9yoRDfS(-a(D}t;!(RX^!k%h59OQ7*6E)Q^xx- z9#f`x8ALV4kG=g9g0vmE69D_|Z43IB?u36I%m0ye{lAapf2`|Dnhx`#$X`orgHeiF zY#WMIgN04|_}mT1XYi5{^B@Tz^vS14+EQ4WIpVlxhom+gkBxuxrZ1U|=cXLr7J|RB zc!5ogg?#sz;e?sW>oqdRn~yWDKkhG{`F?8k;=n)zC6N{E-bJS2toFfo?1%M0zN9g~ zH3la~WMMgBPoLOQbRDO|z5m18W{sH({zgcTT6n<&f0<;%gK8h^!K#jCfvE`nD%LSQ zTEEPovK}2k!eWFz#n~l*F#2clFpEqppCJY+HUdbWGZ#4v9G$W5JYeu1WXAIv{2W>% zyIn-enm%DdAtq=IW;@fP#REly*0CeF$~lEW$XlQ2>b3C1P6#6Q;rzRsrE zW%nb3Pgh+x63-83~AMHGY>i%J0Q{d#JOes1G@46{CegBq@ukBYo zU%RXHgLb!g>C4r|b0LKmLrQLq@Y*WW)*Z4FufKaXFLr}I(+5Sg=59#(Z(EXL9ku%J zc&H$O#-i+&)zO|qh&XBYsX)ElMwyc}CWp?(9#Q)x98`%Ym#B}Jwe(XkGre$BZ&~`) zeme!?lxBTaJz$bt31<~+w0iIR_;;%8HalquEkD&HV~}dZX+|fz(G`UTfj*90f#8ci zxyc)nCy9c&4<=&AK49VC?W5Ng9g6vppkg~U=U-FqaX2v<*v!{!@fASO<5z;l?>>3h zVBk=x6^5=v^2yBZE}8T@f%El0@x}ig+u^Unm zCWL#F+lAf56(ou>W~(~DjG!$jg_BG&pN$b$LU{Uuz|K@jGK$#OF?I%e7PbWn8k>ak zX79~Rmj&A;Y+=NS>kcH;$q0JHi6sF=%o~(J9z3vrO3p5au3W-_5D47ek5!Xf?j!fJ zPBDJ?oi(F4Js=;8OMgXP5S#N6Foi;O?}S?|%)93Fk?z&}`bFb~0XXHDi0O#w3bSz3 z5#8f}DGLBC($^VPhgm!}db}g&V3!;WnNM()>|qgHBhF-t%~DYzu1`GervHnDy4A)~ ziHvF}F4cmNzBRyTJ$Qpy3%bV*o3&nhH2F{7r}HcnQ|7mvr}{5Wwts&|nEX#@#{cad zA>#baO8YmVxKiOi05;Un5#z!Bo;vLCbx@(-Z4EhS{_05heTeJ^*U}6PQ_eQ-=AbW7 zFBTpAeSUa5(Tooj5C#M3UMFYn*G|gM<#>G8S3f)Y6@4*x>-9q!omyj&A;c=?BD60S zQiTtPPS;DaQA$}A$^z&X7R^ReBOA3uINIa17f?^LZJQ1EtEsJw5q&(2i;al5k{O;w zG?8*-)jskh57$$eIjJK~aQW^6Vri@zI>;v2Tzt->rZPL_HzU|IhXdZ4WY`DLbwI!& z=BH0Ef9qw?Q#KLFrYF$PTk=r6Ky5-Z1dM_PF^H&Hd`(~&e_nly9WoJ{f>+Sm8Cy14Igb%o?hv96XAqX zZarYC8Mxq;e;wEC$b|!YUj6ewCT-s-&h1;@b^ZQm{2w#)zYoLzh^_J8hv9#JE-pGD z^pr&A*mV{+uRBvm{{#g1_G8dXjtKl9Fo0(c_z}w=145s(7Xz(NoEn-6ksQ{1?o|z$ zMUJ^_@ry(&tGxW&>)gGnYS_J^{i^Id@UGhZdeR7ylz`u{`|tC+Gs(3K-r_$l<;BI% ztT(syKR@VuTeg4r*&5B@jaJ`RqASlU?N2|yo1cF~E=G0@#(o&*qehL}lvtF(fZSVn zA^f%99t#}*aLPU7H!}8K*>0KGPT`|LG)p$KyGEbdfR2pD@d!B zzI~#rbzB{FFpPp8y;B9g0O}Q6B+4gfbzBHXQx3a$EOu)HPV>z6W^spwDMST62(Pb# z0}d~6vi^Y)K}9CHJ%NW{#L5x`LxUkb+BQY4;3 zn++HmuF0PCE$wDONm>Y9q%seq&W*MDoP|`UPFWx|O`^lr!8I@7EqXa26CxIEX2;!a z>BL6R6~f=1#?KI_ElUUr*T5>N)yT;rMp&kXU3evXC*%z{XsMdIVUhp(X$63dB&w9@ zyoDlVfP2*1BZ{(y7BhKOJ3uU?&{xDivCvxOEKbET;0rq!)W==NwJJar#A}DRa-;aP zn=1`9I?Jq%@(~-RaZSJg`(kB3M3K|Zp&FNEF?S5$K12fym$vAmkuCJn&rOr^@Q0KbV zH|~KXJluG6Z8p3TITr6O(!g#uzU@-T=y2fA2SOkWf;A0QK9u6_x}yKa>wa zzyu~+D!zkVX`gM!HehtKb_bo`GXtA#`Ya?CCg+r~N@~Xx zNI9T?R)OTE-p=Sjh<(|ZS*xk%kHwA49#qSfw3Gu2*}lULGO75hWsMLiu4f;}oT)Wa zvS&41hQ8PE2Skg+d)FA#z`o4M&o-#D3W_b0PBvd7QFE%T`gDH*JcUTJMZG?V9!w4F z$~?f%4amUR8a$T<$UX`K0fr)XO~h$)28fhcAq@U1qcRrhV!Ixrxg4lH@*UK$tgJ z0kb&zdyZXp#zMpix*9^Cu+*?G7Dex>j84-mxoFXEuMKIWN}13t@cNd)J%)$(E|p_9 zbgTq0idwc5G$Qd*MaYvBJtWn6PmaF#Bh zT|<--RKf;BG%+1PDQd>H)#g^vzfp{TY+>S0;7GY4qhpVdAO=T9BB6EZL&2`?kYN3& zfxm>Eb*OeybHj?vO#>rY40-_If7a0IjLfxCO+$X>Gt<&U8`so{SbW!YzKIk7UMdQ6 zz$iu*r6eZnys>V8`uyymji54n7=1YGx}*ID1k%$Vp-Qf~=Ma||v~?JIp*~+OS&-h= zZG2eue?T8Jv&o=?d_uc&QHoMCFi)cC2zK7~XtG9hr^GP&jv2a;u1LN|E1oq+1^=Vc5C22TESgvcIyfkd##Do_2(Kv zx?KQ^{?tpGOhs%)9rjcFObxAFNup=Xp8XNiLWSaQts`mr5eir=BcgEb3fU zjMc=QecGSdB91q><y;vZAYfrzIu0MtNxOw{r+(mByOk>f{S*>3CI|+()iU%oI)?P+&3U3}h#| zvwEc(7)=85DRz6KxYz+0ps?14)+@}+cHppuB9RG_Qo{tPGeLY-gTW7S6U?_iO!je= z8VKdL<&U$?6n>+_veAe0HxG{tSWXbMy}EG-q9^f-$q*NErv$%(Mtz^Z#;(RyHQ>gi zAyz!0#mnNP3Q3Sg4JZ&(V15>K-mVmo8N|JU;x33T3_d_>1e6m|o!EG#RGb_6D1o59 zrLtn_U|Mog}qi6_xKv&<2CiYE^--)a;nzo+#P6PfH<0*|I#toy;U*7`pd;T9Ax z(yMcDOe`Lyu%jI#=!X($IyFjAOO{J#Oj8M#@$8RNM~l=JPTp;BuMHT+Pzz7axgywy zB5F5^hOiFr5(0a9T-IF+|7565dpB2%HhEE58Hxi_$=x0pRI`}w%xmN1BAPh6zhU=L zwkxTcvLhwa|B;O8$~_t;{7Sl{&*LB;fI^j(>9xjB=`;r+3ob`rLtviRG|Ezo00Ds_ zT~oyYY^8@JXmX4iKQE&dMFmr^%I=lzENEFb1|BlH}PQ?6lz+> z&6xDk#}ta9<;rSzMqOkeil0&2Qd$*te854P6@IM#m7^DFoL3VJyPHA_wK^w^o4ZLp zXx;IHj`5~Xb^)&4sKJm_Cn7oKH#sd;HMzhEdTY~S2x9Us3aE}Os^T$=^aqWOL|A8a z5vc}-zOxqB5;jquDjN%H-78OGI7r!g<8ojY-Eg^#)*lOroC#VAN=-Fpx4VnDFh~vG zH5L_Q0&`mPu$SU@RSl?_MpB*N<@tpt1=zmc%UTP7zN=U&$eC!zXphrvU#ArUl8p%h zVW<^M2MJ~6+H2qDN<=r)4Qqhc{?2NG4r&RUu&Ztnh2`F*E0{ldb`*WRCP6(H%yphI zD(u~k`$uQ!^Nr+MygLUCa+LEpaJgN6=<}Xe!Ts`(`*-es{ThP41{I0TAyTPK0Tq&k znvjMLGDfASlGM8YvMD*Hw#=}CT9=qfy*b2J&9rjx=BMXK4_K)GCe-Rc@GSy}iy|dj-9g1~ zXD z{e;?qwaVJ_wi~NDlZ%Vg+z9!1M3@EW(QJYWi%yF@-5Z`W0tjcj}8yVj;0=& z51_xhCH6A0B(qW2t2{Vnza%nW5dT{3bU$egSPv3COm%$APU(EM!XCx9V<4_cW^ zGOveYoj8&YP=eDnl&SsXvVRaoQy&F5Uu}%C6Q>gfPKN5-#xLD{ySUBNhDGM2 zTfltmLmyo4R)V6W9tw378;gQK%Mgh)gX%es5Oo3&*Biz{tTT+M>zSDPqy%N0STMRc z_eyMs2z`cXX8T<`uzr7zLxFk0DBnZA2h_Av<>rz7Vgu>yXHA_VHgXFk}vzHwh4B0xA zzUYQwwRyfqHiiKB+U2dbJ}wActZk0)t2Ey3^g>nDNdK4HXzS#$JiJ3?URnDU?O4X>7-J zMo=~4sg29!G-5P|a!vW`)G<`0>5szQM8c^AMc0jyap+YPCLyT>1FPN@ARWQ-oz3}+ zhb0uGZg>pi$YOQ#5!!=EcGrH&d40%<22uNZyM0Wa0@;W8xXYz-lh$ly=!46|l2b^^ zLF|zF6I%;xgPyg%j>m&PVMTeEcdG=bd!~QADko7>XDc(-8`T8|XpA7kT-2RnIIK=s6tIL9 zTI53r5fDiT+olnuiDOB3P`3=&D>|WJYbLO5CpViLZ4p34+l3~Ax6A;O>u10J4$7a<78e=z9nS!=@Q}#sLR1LFDSJvD)s+nL(-6h!d(c}%GY|y2+AAbeg6K+^ zT1Vwj3r01xyX8lbOVD+mX&E^pSFbkGc2VrfqEQ~!snhYFy+4AlaXRU+?Az~G;dyp> zlUsb*X)y&;6}FM1YJd*IjcOEeM%l?>ZIWBS2^^B^WCWUaMNtM4jb=2p_7pKE?*_wH z+041%pi(81)At~6H9f4k%BFKFWF4!1#dGgb)(*j|Hb?3?7%geo!JI1aMlqMbvdq|; zlBEO{Ld3Bz2x^g8(+@lbn6A?+0XE2&Vj0JA4z~fALXWUjoir?!+6$Bpr<0@?aH${8 z;SgZ_pxrF#^w@QZ0wLSAs7~MAhJPmuIdi}E5M2(mWuZ*d(I3De-5Vg*=6zwKRA*rp`GOu6?U!_~c99U7sC z5O$rBJSO>*4d&w7CA$W&6!78W{@q@PL6!c7pW&DtSH}BFez`wv_ILKM8gni^iPySM zAp0Ok6Fq3hrLZ8Fw<|-O>4B=PY>=Sd;%TgA5%wBZrwkewk}y%BP0^%I);de`v*wbH~fdS>?w0Uwdd6$hY_VQRG|i4B;Dw|pWajX2p0B`7?X zj!gRl@l0ivn|I%9RR4AvjTdbf{lNA*NMsUXR#M+9+^rnQAEhu-pI3t|Nvl6GfQh~n z-J+M~mobRuolBcDwREfbr5!(FY|<_U2F(vJ0t>d?&RT7!cxi zlBlL}>+YZG6=Q!b!!i*qugfYiiLKeab7`7O_RF!ZV+ARN##rA6X0-t36~EeFOTrHo zW#fVzvE~BlQ)|`R7#Gk-o)>ShiD<~PgR_@a$TAqVd2M5^FZSZ+a3B>&!_HmzO!YqNhF>o_e$XPc^%N-(NFF&aVk&A_fl zHR_KkrHZ<{6vVdFOrg~pDw4XiOvl1&7;7D(8)3#ct}e%T<-Mh{;2V494A_i)7A$Ys z+h0t!Ouo0+@5dYYaLmL2!;6wyZknb1dRl0kA=K4IPK1XU#pg&V;#rkgI*rM%=e**l znrqLSk?7VeXW)WiIFxVYV^Fu$qp@2FT!WwqUA+4Nz#Z93%a<}yr=4G93{Udm$RILB ztX{0>8pBRC9nlK-h}wfH0ivOhx?j({WIO~ul6IpP15K@s7kgqYTNhZ@GGsEq9GgUhvuk- z!imCBrf3A>l5uMxUSPJUt|L*O}DS3t{vi0JR1m)I%RLlCz8j0`R0DJ z95SnqnIa=a_2NeR!Z@{2jIU&-3(8w9yGPUk4y6G}4iU`=QFZFI+;OXxtbGen%VW3N z(W(Z-QL%|d8AQi%dGJU5=KXC&F>2Z0My_u?0Wv;yR}CUa!e`{%1|@VP_7XlcsI z>xdgu`sZV9qTHJfjZnUZ@*wXBncH zFT$B8u1S&6D`qG+C6-M)U<~+NF+@@=U_=g2TDK^-lDpld2(}NTP#sfVB2e$9V|RfV zopd%_Or^6(;{MJxjxQ3o|M@yBOllj?I@ebZW$p&ahbccOE#j8Rni30@U}uftIj^<} zVgHHRem|p8ZfnTwPt1oZ)t4)KC+*fmFnzWlv~K4G_!7+$LYy|;pLZuO{t%oYov|G6)=_z-Wlo$=Rle}s}s_@y`wX_>o`fC;E-d{pG9e-#{7Y{uUt{;j)j`0+2;Ipln=qvSdmi(zbS5l968GTo) zT@BdT*1ox{YBs!x6eT+voh;fQY@RzCSQqe2Azn}$hm`O81LOeH+6i1FC(c@DGH!6} z!egKA>HGei^IcLH{l1*4J7IrV%O{)+mu^tu2_kaR-PXBbd{}RR=0ePly?yKJ!V9f! zS$kiu=Is|!2a6i4tAm!>eXJsthXc_hh0Ahico$6!SwXO~1K1*!tSMDSoIIvcdJUlX zOPp=QHjL;K^Fu>3S7pP+-x=|GGO6N5l})6=xGvnIxm0hYSmrgtGl^PSS4e16GN4x- z!Vo{NxP-M+4}h*(Q*ogRi)))>|gWo7okb zzN0Jhl$1DPWv)ZBff?a<;f-e`N!B@40e} z^g+^OE9h{f&hs%H9%oo{o{F))VyQBA&`H0-J(&`V2pV$}g?Z_BOL>nm z7kzxAKDRMNRM6Wqxk5(MrU(BDX(Qsb9lG3s33*4;Ti67Od+|tUn&5bA?B&;HMN6jK ziJ@EA{Io^HV?A>AVLY6UFbV7I*Ve#-W_hcG-Mz$p5s0v-5J;$o6EP1Vl}we~|8bk} z^207zZ;U?CBKgEF+?@6>_W&ul?%3z|t~{&BCyS7rGX)X>OHv1UnsrH*QQ0+8ac0lt z5t9ij&=lf<0*_v%*yDFEpX8>6N2d%D>dWtkkh99U*S! zLX=d$8iQsmw$P=PP32R?;3qODXWZaf70|QK+@h6F=d&LH8``kXq8Ea%5az%2{>nL& z?@|uSug+4Du8mt&v67*Oq)@6JBA`%8hK-xbR)uH>E-Sp=;wF~fNkAzPAv{fU8n6`x zPah&+Se5-*K!;5!DNQ{ftK7;?S@y=bYqM*mq+jgyw8oEgmoSkwHhY~2EM%gh3^zed zMn8iO;MlA&X*g3=Fb&d-1nkQ=k=w4&>1H23gWFz5aE$#+!TIvpp@1^RM5we78 zXdfJ-gHlb7iMAY|t*&h+Gkusd3L3LrS=Wm<%AhJ&6w%kq8aJQuTIMu|ow1XoU7{pY ze(y?7Ac6&07l|No_AUaI!zGM>NqM6~54Cq{dw&Nc3x`StFzsc=O>wJ=fHLQC?XQHRQ5M& zyq$17yCFyEgOd40$gB{0 z-K8t-mY|bkjGmRXC;&TV>1Vx-AVv}E{dcXQh6E4fZcr!0we_RU=N%ct0D*aX>D6&# zXK{T~e8?WS?UehB5}ZiCCPybrhcb^r8DEK*=JGqa(N^1=a-OZ}dp}Hpeyzx}SX~q% z^0?Yny>Wxp_-qfapL~X`-k;ovAL$5APVIGKE099bK)b!pU<+DFblKZX|=r>;a0&t$)HYht7tC*G*1kn@G~B6q1yt8EjmKZemjjRNC~ z=n>M8wm(WHFug&j46oD9=*~J%oI;HWo+w~PIP>D~(?LF~i{5;5?*}Q2Jv$80ZWN4Q z1zTQyB5Y5X1=T+%m9k6ZE=#Sg?9{g8vd(s|GS6^wW|L4h&m0~DbH8N$k5sMKl>W;9 zEqE*}si^S8?StrcUv{JaGA{F}7nhBO4f2X3Cr!Op)J;FbddyZk!3)-D*2&qTE8j<& zQhMeBcvXAX{PJ$7atik_U!o;5X!(Ezd=9KYA1M1ai%@2+_vfSeP8%ynNnJ6s?8FIi zQewOx{mF$0Q1I|vY>@(Zwx<9u=I0j0(^g=#cdAtE3+Y#Q{kBGe+|fJpPckwmrAzn& zR69P4v}rb#=$=L&^(jBQ$_pCUeqR6i_etn4+ja2NBY$n#&4`soTIu7`+@&6P+JVZ+ z!-cFr0ViJi#7VW9QZ$T1huC?!8;liSKp~&Bqk}T`O=$sKNyEq5P$9XXvYQ z9-m_GLQtwfMN;72&fmvgl8zlL5r4B-VX}7di#HXE=$v&X|p7DSzCn9A~b?HV=({k1{Y2C{lXEFyD zZMA(mrbwaVovYSuLcjKQF6D+5QLu2^MIo-0g`wK*^?riBM1rN-y*Fmq-2&YbIc@A_ zp;6(qJ*XNHEC>!#WzoDZXtPDY5MkE~pOoAy-)!CVn<(YOOc05gh(>L$%$}4iCv**C zY6td{}`ui%FR`BYb7>dr+2!+tVm@n?N$#Ku5K(LXulnKaduP5xvezu=j2NQ ze?v(8>8y!)J#=NqBnH#@JCHtrOEG=2c{jj~40+dAHgDBl{3n$Gx2|sc24b;aKXCG z7dssr9ouHdwrz98wr$(CZFX#9#kO(!Jo{#!>vJ=ILd|-r-WsE7S?`>cd{M~#b&J%t z;FzTu_zQ6Z4qV1IK~45K;@?<*MyRsbg#?RUck8^Ms~+gT@O->%cPth*{}-R8p{v=z z!n;Z8B-1izSRRBMfM2?KtZf7h zkrQ76w2udX_qj$?=vL~Q>7Jrf!G=|IGI**F>d6mta;8?*lE@Zwzb3gg+H!A9!xRtu{@cekS)UcSlW+XFY<(D)pez6!p6)*HgEKbu?~cx~zf zM+D3*VJ+g}3_MhraXSA&9bH1yDf$tzwTv|jY`pLf2ibIWm}Ce^YH4^44*$bgUpbP= zKZ-PlZYY;Nv%VzAa`4Ms%;zrWax|Z8q{kXe?uHQ)`AM_a~ih62#tSxSc zWVSJno5aR?l_r+H3wy#0=nvWlCKVLhxqs~)8>g+ea6uM*sea7O@#lN|HP*z1Rcv}| zNp;Hp{(F%1R!&1`N%$Zh`=HgKhMw7EFXc%LuF=_XYJ>9 zAUT+A7uV!NPOI2+YO1^;@JnUnaUp}?O8ROy^tlf4{m{E0GV=}A&?Lk4e0@n{ ztj2pP`;F=4!b|yMfcxFJ;7Z4&@M_MNy*aPb(8Acrl!EX}9^vD)DZ1)2R^#`ZNYE_%d_7cLj=pr>Ttg^R@%O@aWCCL+zn{X`x zF6E3wCE~eoZQtlH%7?D>NZ`$cB@Q^7An&CV!}YAw7o(tjX5%a?ctW$K`_a5vSbX!+ zOCFdad;W)EfA{TN)%(@qZ6mn#A#bZL zSySG4r`MOY1(pPDaak%f)C_t6x54UPt z)Yr7{X;ky9BVpcohdX}?t}nLXqJOM{mk2sMfk<&@s-^t;=54AM`wen@Jq?rFM`tmc zc?46t&>KOv`L(v(7jVd-&5&?QtPSPU7A36uAD#yjHFkS|aIag*gC7^#CZ4o2JJN`f zpT7%LvOQuH1sjX}W&}_D+G!G3Db8oZzthXL{vO>dOz>~1BpXh}M6V3a?_G=a{^Gzm zy#iXGeAunG7b;%QYT#M@tpAHRGxtJs#-Mnbcc_b><{V0}_pl86pHze9*gS2mav~2>h_MeR~J~;i! z+Vf)V_mI*w~*aMMZSpf82QxcFB$Qkxz%G+h2p~>iW zP+A`3LMLm&l%vj2;_oss1iVFSnv$gyW6Pa+`texCU#6ixv1E+Qp6i5;G`YVt|NYls z{>1!inq~z#ZQ2^zTa$P_P0Z5zwZC|$txr!#qIaPfd9yJy-$i+$D{LVRS1#|1DtYUr z`i7Snj_4AXMs=UX+nvG$}c8_BgH^zBu*Et5ZRYkA4gN3!xJC3AZLH*3zQdU)YzFGRO zCA9j7o&%~v$v#uW^x8DXqJHzC0Oo$Ctp9`!U0ED?7y1UCXB9)9b7Z_vzk6QH`T1C2 zpE;9t^-+}3r0txx5yLmv9BbrdJ6X@Ph7|0!)|D-64!D7MJ(_8Z`E(5}-7MW4NHru}}DX=Zro=T7q_ z44hbfI^jwK!}f#|k_%IZx=X{`+`&6cuzsW~?M=A}Kef!u4NrBb+JARd?#p9t@+(TK&xYqOX;EuzKu_~>k0EQ4gPDS_KB4m;dpKf z$$VqijHJTgoZ+G_Ui6RE(pKVn(&WkC?5&X*SCIJR81tu94NK1)^faFUR_|JAzaoVF zPsJ5a>pEz4lxXB@d}Y7Y^Y$-G%qk$km+Ti?+Bbg$r1|;nQ@rx_J>{3M@=y4Uk9yN& zq{JfC%8%K3-f136)a}&^@>CjUt8|X77Zq>STAtf4myJ7Wh5a`8Zc8T8CkB}>!gm4W zcSrDOmnx}EW^WPK*@n%bkqX-+wcYO!2Zz;J&yc|c_m6vNzHC^Z$GUZ;PsshGA3p0B zyCSA1d)Y6Z-g*`)dK?z?_wy;>V}@e*`j3}IBUBl}=Iw-CckHFy!J;70;{!;c{G)l| zMfzG4e%GLl`W(SapkbJA8GibEI77rCiy)<7ax^8h;8$c9T8af2tsY9@K7C7y7H<5q z>d+j|CS!fQOX|!idtKjX?G01$K5>OjJ96x%x^nAcDlNsVuUI10C=U7HGCoHu6yGk# zv#fh1ogFd$A#)<~y&D@#;i_nT7b8k!CicvgGyp`5B>PFAAkWDoeNm=}!>JJ67<(7g zZ~7c8Z64F`#{zC<`C>qU0GU!@EO?^H3)8IhIa5p^=nvWQus1qM&8)f0KI6G}Y=DL# zJZp^LsDW07O_{?*u~VTPvfLUzkL$QaS4Eq&_NSn!HOCB=(WO0>Fi!`1j}vt1mQhZ7 z6*L>0+DDm&Vb6}pbqMlbcUH6{p#o^SieAW%(%ky7appz@WA`kE%1v>ahbh|9!oc2< z-gAj^K#AocRtGEeQ;j6_?C>V7oGfnpwlilFEt=NG(%c&Ym@T!IdDt`cqFv)d=aAbp z-SfYMI5_e5-9#r7Ed;qcNK8U$rz#r-t{6XA@pw%(`-+P8lA08560sTg5v=T!`5i$C z{({yuqq0vqe_?Y3)d3(*(Iy!SvZ5)Yi`53TaP9qi2Q6&;0L(a&tk&1E(e=KhYetfF z!t|E?IeTxxz`|qh4N-6O`;@s<*>Q6gsMsi6o>7`wUGhuOOe44w*bJ*YwJ7#$e4T0o zI_zIUX9LTYwq#nk{CuSf1&CB#iuHhx7t7Wn+$>~ugEcr{N-KnA;1k->0*3uOu@f#} zjD_fg&Gs+F=nKb3;+b5{X#5{R67m(Grb2d(TqzFIDekJ7TRF?9gwD2P5TlS8DApy8_>I}kuDhI?f3zTSF!w0 zS2n6F`^C8}p2HpD9J}pm^@8g~HF}14*d*&y(i=&XXSyw3@5Td5HOeLT^6$@Yd1qVt zdZ_sD1{h<0DpQS)==>X2_38BmFm@!P;5n#gyd%BGfnQ63?-CfaxlNixHjG-na4()3 zx&XCurP!OcO>n5h7^Jk*2B(5GaSlQ9x%D|Ok#NOWgk}iZ_mLAfxehF;!Z&I1OIm`g znZ~(eLiunPz7wof7`ymc@@pcWv8&e|7AW$utuMKdQQ0R$kH;344{c5K(JuH{($B9Vn0gz zNBMRQ2;Y1WO?YI^G>PkU`BP1(rZIrPEC|*n*dL;j-K8Q)S)QxF>vuQuVDe&eC-KODF**={0u;nLtEi%> zjE-@z5>26bvcX;B!rjM%TZ>$Jz%#&H>!;s<#$4}LVraPSup!Yg+jj~v!_*n*S6_Fi z-GWwU&Ne$`^5N0ZP3gg2;cv#Tt=oX-P#ToYuJ5G{i)1|+$7m1w*_!styb|a!Fu&ZE zd<`I|z%@H;?e9T#f>Z)%=4bvUqu|KNx3LSjGN+bN2V1@ROvK4)z$d7l+=fRINZtmG z+k*4k>c@)(Wpf|&;E%v=$5S6zWUZWCz}m3|NThQz3T-WmWH&~;8*s&(!=}U27?M{9 zaybywh9>0`$b~8!vVB6z1$dp=;%196{`)8Q;N3B2g5&mRUy*0T{_7LOpBXT@qP(n9 zH4JrSCCJAQTHk0$ucI4g+5otR9}f++h-wt70+BNbTReG{;r8FOz<9;ijsw2wtRQ)Bc3@KeFs$M_B>hJg4stAKBxOjEKpR%JJ)FBb z7`3Epq;#HK%;67UMPV?VlD&0oT?4PX-@N#I7JGJej|#oWk-ep-=pFO>p7i7YJF^Z> zXrJF{foum31LgmezekLMiJ8RN9$flW!rD+*aOOcLn|uL1e_<)LEtGVs_8MIGN+D?R z-zyqFi3oq0n`qy+UBR=Pl;R^V*$eXP7!GG7fqrek(q;Bm*!~p8s~g;B88(K}Inun! zK@2_}^t3|e2XrOd9FIBAxoXyY3;H(bG20NOl)N6;I+u0>rlZg(hK&5scLyD3J;cjy zB$QNT4l9cr-0{qm*SM$6UR23G_`3inE%OA5SzFR;dyuCGMMOZC#rdx6An=70`Z~a} z{y(!JvGTx=J&QGP!8Q1p`jB)B8m2i6qjcMqda?k1#vXgAl7J$FC_K9W<8T~Wt6y-p zd%6ir_mYHngRnQ>coT%Q>c8=4_GRV38oXCW8w$+H6z=XcW{yXFURr7* zX0HHXF;K*ALSu&h{;*2dZa}X3(GG#Bhvb`C?Lnu}gq}u(c0L_{wcJKr13)q^R(P<| zcF-)?XCnwxshba^0Q6`JmSIni$cbxoJ(M^f{n3WwB1v2<61`!*xV?L%iMVcPj6 z{_hU)XDwXacElQ-Y^R^DhGD5*VK=-@NqGYppL(^-zMrF4198);s1(5bTh=0<1PP;v1LNWgrg0stM>&sJ#yhgEKS?dzV*Ex6#E>ii62CJoil7j$acS= zi_gdzviIvo*P#+)v7qwA`L2+~EZ@iQwnF8%jk#!AdS2AN^MHxA)u*{4lWSt!iL9dx zcYSDSw-b^q*u02Ub04bQYn9>{a-g}Y!P+w;KJvL;ZMph|foe&+o56YOY6J&FvCajB zLCrm1vHvcc)Y^TzIOPf=>giS!WS_80B-g(E5*qn>D~AxETf#C3$gQpVS7Anf@~jJs zUR`ie96FLeaYY1MXNV&jHUfVP2T=n2vQOAlvcx-6GD8IxEwJ=3YY<#JS6dYSM9rNX z*@Q7vb&s0uH;4#Y3!inmlI-M>d!k_#_LISFHTDnnC5i-4!Fe9GhUY@?nF>0xL^tdx zFDQrayQuET$bmqv94UESON=&q!Kj*`i z>aG^Al6KiCRbNk?LH>3EBQ2qre-M+{K$KUv#pod*wrC_0#dwr*s|#T|%Wa9TgH2pS z@Zo!uaGTc;!Vnb|T|l@Zmn-a(Q>rt=%Gxoei#~*vq} z1cPkoTd?qup!n@6yICOlRJtLYRM`@~v=U|~ko+YvaboUS$F^5GZxyO{M)gVU$q|%G z{*G4aq1gEkv2r~EEkj|OC*A4`_YPP6WlUCgb(X| zU?y5~bHMv1qemA{X~Z#NB&Chw$prc(6kIOOHV|!T`hXEPGF{|8#;k;rO6Hkd08w+t zgxcL9iqbapKU!ZAkEnE8ifLP9aRFMyg2-q4U9Gp8FSSM5K1!J#daJ7Li7e5*-}Z4e z2ku(FM;GkYhww6}E_B3LxS3{eAkt7SMOatiP*Km+S;-t;HtZ3o(9ba15Sl98MD8uD z4Yab=7RXgv!{-@V1G0ULGe8nQ2dspW(;nSDrue`q|_G zh~^)g>!V@koT}0b?U4~s`Wjy4F=syAn$0&rW_z&$g(lLAV*^xN*RE)xWLu|0#v{(c zaFK*AfB>UE6n^6NeCh1wh%S>{gZRS>MwLb#ZpY^14SB6Sg>56D_SM+eqlP^K%3Z2; zmV3Czg`tsC+=!N*P`E~v`zHYFoUKQa?qJ?*ElxS3?zL@N)$Q)D1+skg$kXSiGK-#e zx(Sm?;)nu$R>AG1TBv6ug0LYz3!3Di^x50B+8rwbGt3hIIu|LY{+cRnIaUikMiY3W zQ6T1d2di8}g=~G#hT2`Cf6LtFw@{XNmX|+Ote0|D9_YV3ea|^gku+wZp4_TWx<;cuNjc;07oXC-NCmcww%YC% z)ijrtA0clk&(`A-Htsk{ljc`2zeU78lZvecM8)2lOyUK^OJCp|u)4uZZkdx4?pm<) z$o^4*7n<}bf-ccH33mdk_G~qvZsJ$I=`FAP$ml-7DxZ*-U$MU7{fe^XDMO~?XZPS1 zI{O0plAazRJogCKz`i4T_G$2-^?{79km7@GoQS<+Ft=cGp@a?KzN6Uns8h%e1jGcg zp+^mr^Wv6lkJaL$+_i#crEs%i9Jz4>DC^{QqXg~(&%@?S*!ulwpKzrIW$B?m{X4G+ zr9i)W2H!BfPneGg9Xuk$!GOYFP!U58^^_xDqFe+-$9n+>Sa{@COwz1-4ggTIDAjZl zxd9yj`Ei63Ah;d;VMLWvNhhvoxQ12AZBMWeVk}(Tq1qh`Za9lmt~)F&Jg#2BI}kW> z;$Hp=C5NWJZ+IZ!-u_BJ5s{-o%a%=>R4?*8NY%(8m-JPyf;fD}j5=k4F_ZkJL621E zh*~f7uWzCq;cCP?ne5<{S2IlEMLe0p;nkuaF*XUmS1**$jfy%fIZadFGx9)RnQUnn zsU7pT83i7(>rm&7aKBNnObHk(_y+tYt5+;B5GgTEIuDy#GSI1I282uws9Le+mLm=% zE$z2!$&M(iaOIZ9jxDO9<`&3}uq-dTr)mYAlxN-PxKQMlT@S)7_qZo`{$fyz+b28s z=$7e;OsjIcg?;+(Tg@j{y|V7k>WQRw-nm=N3FxAw->rx1&tVaCCq{?5YB>bxQ44Of zP`*{G0nKWGaL2{I=_4una%En)S&{4CwJrlfZP?!mUm1N$SdaG26MsiMqw(dT2Q{mY z7+l#V6!b8JTI5B1wJ?a3)Xxrcf?nM&5bmq~|kWqCUZm7{1$&?7u%1O7scJtlXfHz55tNe*33a3Q)$*ov`wI&cBW1k&Rk|?WS1BbnfWM~^x!+dF1i}KPfi}=tnkCLs85{wVTM{W;a6__^65>wWYc^*Z`h@EZ4VbD;g=_V}sjeWG{(#oi{$hj%o&A-U3K z2oeDn7tjQ+5n^Bfz1N?^h^OKW*)K;4s_vcm+n3Ry=RYz?b};xAw?BShgr_~I@BUpy zjw=3N0@?rAvh8wHl02wM;@AEO$=#@)qKoCAe>M=Yq6CIaz&@~E$-bebT@(LR+>}2Q zB+ml=_;aYbxrF^BN^XCcwd@7{5CY9P{qK>+^umhn31Th7NK#R~|;l>gG;4v#iI)0&47U9retJYBPBY6hIFRGunVC8xHXsr3URyXQ~d#8j%mK5#4 za{1*R0YS19Dr{DFsK?Pq!aqMSa;8!d_yR-wI_p*zP{9ZQ%$PsSq%CSEk*@0+f-|@| z`5D!D1;4HugL;Eh>_gW-ET}uc5DWWwey41E)cD}y;}+)Rx6C?%u&|yhb{n5Sxn73% zg}>O0#kQi!NPxv#!O^E9Kg`f3*xd5WV8`(N*80mOtOdbi?(FJX+?YmkoSiT}VsrAh zKi%H!59n^RDUDtD*$a!)gVwM-9g3vv{(^RKF8MTF;|a#PSJY*jsu}d@c#AN*^4Jdk zR8&RWL znPXB|`;fFQt3ak8tV)zX5Q#c%o!Hza?0_0q?Ana0YOV?S*o!Y(ctq^hgAezJ_hMN- zLZz<|J5h2wq)Kx;qy;H~Uf#321ZAp7)5|Vl4E?cxFxRFw?kMlOC4TJOJX5Dpm4IQ- zuwjUO@7*(r@X}?n&7{>UscrndQi#}SZL^8dgXC|0ia=eMiU0$$2iJw~btHzz!H|Q7 zAuMoiYOnwk7{5s@Z|F81T5}J-;_75X;&d(M@r~hODIO$@UiZ(TV4u9Y3kzWaH}OPw z-^vDfx;gFUx7S|_FI{V2#&|Z`Qu+rXx7`}Pyt=QYwujY3xqrzz>Y-~i?b;G6KWS)b z)ZEcepA6})FflMWIYh}&?&;~4^w>FkB+&E8BIOB@L3<0sczb1kLpy7`=UT8v&ovf|j7}eK=|I9~pW3r8mx1Uu@wNBgS%|u+ zfV=W@*z6(Es}y1=;nA;4sxYHQUJ$4$u)9B8@DGw7+!}~u5zJZ5O?V4~_YMVkl3GiY z(c|;&nazzXhgjVT1krsdVS6o&zwA?icWNG#JJK5)#*W0jq)0<zn*=%Lx< zo)c$A<^M!ulh{U}d`M|5q7}55;^XT^xz)d-OiDCpPyU4sJSwwkW>Ox8J?!#g@YKLtaoW!R~&Ph`@YV8MJIC0bvqzfp8N-H6xz!V;xl z;9)rRnI^A@1Ew;PhZsJcD*qcvX3!^Y&_3^oDS=cc9{Bh~96hTCgiXivu5#nzlZGkxll;pYH{@V$rU}q@(Q3Djb5Owlx)?~J zgK8dkn{w1T)L$LU&(6kZS6^=KKTbyG5OR!l_H~NzGOGO&>`thV122#RP2`pM%cm3Em6N-z|!L(w;CZq2tjafoG*Z zpf$;Z=Tjkt+|5pHZlz3|_U$Tki!}t?;ef#F!E5;Q^@GdzGr1ghSBkKG^ei;-ac_b@%%^yQUIpB7t>z_F|_Jk}}=AOhG6Ur&HHd?MV&FPDL|oIlRUyImI?XJSK)D z4yTO0LZ~iFdwjxH5w-hTTqTZ;(XNY{yqQpqkG(2UC~j3ZU8E8uN)9RFpFoD4EvC3A zbH@ItHQOdMNb<6B-THT4p3}-8qc6cSd=OA_X)D&KhDSjlDFN}^h;fN*xHL^Lw-XOh zRlOhWNjtr^HdyoAic_xUzdkLvs%18Z&Q6RO1&;nVD}0?AyFjlcPor;bgQ!k)0)^?@ z^iG6ag}$JZ<*VD)PTXFlzOcL{zVal+Rpsq4ODojpqLS*qjmVEG+w_uFfr!3=yPHp{GSVs6)#iM#1lYqLm0EL7x)R^S{Xv)$_tpo+>Dn^CGa%Z&p~l z!IX5re1k)HB$-9oyfTw)pWb))O5>U3tjcOOZ;*0_$*8iXq$eE>3BKBrD7QT{(P^xy zB8st)7?*|*3HK{|c|4*R)vzVdnyKTh_~VHEp5~GDqE06^M@d@CjUBa?03>#8ee1br zmnaPexPN{)af~e();!8OmAjO;uz?}`c-RHsFd66i@g=>)icbiKmG*QvXZg%zRPU|n zO1{!=eB#*`tY2&svfm<~qQi@IbpfQF-Id$WdfKE{I!F^8iJWmJhtX!ILlu@*cb<$+ zrkRyTOY9#QEDuW6wozL#R+3Tee-}`J`OkkJDxtXguoJ7*6S(7Y>8vVxC=xKY6D?9k zQ76zqTEM!`DX^qc#d>5Ojg8dme~_h$fMDi1x0r{6zLyu$sPIUPibNc$Q#Vkr0Jp z&3{-IE&!>o0vxcA*x_=PtF1-WdeOBWh`Qz|x(`Oq(@v+{O;^6Zu;KA~20l2gKm_jb zV6AQUDZEnDog{2FZn~947?_B?mTOg7pZ8jJ_Ldh6%U7W8TY5!I85BDR6*~lEmLdCT zZHfLaLJj~n44^HsMfQI?6tbhuEHUqcUiq^p)7Mkw97a+oukCxQB$S_lzagGbh?n3^ zY|&L#uptg^SgeKym6{66)0MfrnLEzLUDpiZ@Nh#<;&WP&)i|A-Fh^aAo~e`))rb$< zYA<0os~we8?Aj=vw3>EZod;H4;t|JpQl6K@D4qUcW)s8}bUzekuqAz56dN$GWyQ9)J>G2I6k4Bzsj&U`GIZsg5G!9H$dUn4(YSw;# z_J7578eLdawMpe`R#iHkk-fQ84*mTuJiAt+E|fRa)=2{;DZeU}^ZVFSAYE{xm!u4N zzvx#=wJkcaroY35izrb%&z0atnv5t3WGNe8u`_y*zb)?Kr`=f^od~1FDPIOw)ah5a z1Haq}ELdQ293|$>28gaCuxh8tBUOhvys-gsQ3Bz1V_pL#20lS}U@ajxgOd} z_JrNLEPP%?TEfgq3>0rXasPPP0?ns!xMyLFek$8l^nGFe#r~L(gUVEYIb3u8E6Q*UL-P&5PJ&x2Gpn zE-<@`IBxzQ@Jw~1IbUr=orD<`u}T3cLd=6)8%o3--Ho+LznIiIgs*$iUW)G zhQ{&{f1s!CU^sDqz%dV!93c21)b|(b3GzZV@3_{2XNQ7bLAwJP2CH6SyMyWm#$LI- zWBo$w?hw`j><8t%;aoo9o=09BKzi*Fydbf7i1JFU>+%d5udJlj|3h_vf~UZK<~wD* z{kKV^Km;&0z+*#e*v*UC0_QN8C$IF8nzvgU7YNMeAHWYa2~eKa=$HI>#eBRc3wk%o zznw4a_9A63Gd%(y{ot;hy83+v5GA-2219KyeqJ1kq3;A!bqm1QZ>`u7+4b=U%e$Rv zq6@k0tbbD7=-MjOH|@+cm-V9{`bCg0aU45VYE5XWwuS}sU#Z-0S=Qo?*MEKTz>oL| zA^O6Q-03TX|AZQS!dBi|r^oFM5`QA%+ZbAR$1J4ylqMaLn@0_i7$BX8`-o7vWbg$3M~wd6P zMh-yXKHsn@w^lohD*m9uvHS0L4)`6q2z!?KUB^LmXRix;!S$2P0= z)Urv{lQt{OvYAnlR=KiTanGMD8_Zn{AaU)#Aj6{!^4rl6f0+jlKDEQ<{k3AdkV=6$m~WpRTqYD z=brU-c3@AoI7`Ao-V+|&JIs_Ohb9PE3rO@G;EARn@8dwjcpX?_Q~c<%6A?`$Wz%1! z6Jq7+2y^9f{z($}K)td6$A7&hwwAtdq!w824?&_5uQ$l}nO|!Y;>)2&)seaVvY2G* z;r!9|(0f*-e??~b4wh}TvOPPWW)p6rt!4*U;{>tzo97jSO>6iXg%my;Lb~AQJuGwjWZdG|=Rtr}M z!JyHOD`!O{1yjq-dNrNH=b(0rF&P@U?W&c<^b@(_-AG93Q5Bo5KAmy3GCmX#1jMaG zwCaJ}b`htrc7yU=t-e7=vb-*^_g>_bLOxKY14rtRO5wMB2P^SS2@v?sHB-T-E|t+Y1c)PxU%h$j?b6-miWz- zDdUjM^+H|k^uKYqa7ymR`Rc748KQB-9gFa) zcy?)rpOio&4$SBKXHUF$%`VuDnjJk?73tRINca=tHh|485YP0}H_A1PBjsrPrp*dh za+?0s5dCkjyb~XyaJOXU2<~T6IIvzKsx`xS^I2YA6D}w{fAfkQ2Jy#}Q7hQ$NdpWI zs`zVw9?(K7VH?_{8Tu?Gzg@{ES13tBEU->2rwu0EW-;3=>sKM_u~~(!#FV|-Chh^_+KWH6t_P(v0$Y}@;JpWRACYe+}>2d2H3(9Vno(*RPf((AQ13` zl1zy&iD_!S5a<^Y*i&;DvZ|pKt*{46^S@+fue$;$0eC(S$GJ^jZZFsW-e+&uuZ9v| zQyZ(}N)2hP#KYjkWJa;Oou%hL5?)-Z6lr`Y%^0x8<|Rg&zB=S9MqoT_4$5|gRCBqg zb5FYib?g1Q-NW@P+>@Pftd4G&(Qq}!9#a50ixW50^tvM(=@oMi;TU_J+N5%w(?Q*U+Wfr7L%!^hn$q!P8RuuqE~?Vbw4(Ysv(?9J{UUittc z{{Jl7(H8F77$Im3aBBV6U*Z1_Noj=B{M#sCs8Q?0R2hKPhSIe|TGhiM9(ZyF_67AB zvEhv&IG}J0cD2LE?ceN!ZNU=)F(J+P5V~@#S!?ojrkY8>_lA zMAa^ifH)SEiyS4ki%G_Vttf;US{vtMqa_dc7j9`lUK8jGPl|iLW)M`)w);3&U|3Gu zE&2(*_p%3}{y#Pq$qbkGw&h4)`}UnI2Xb8JZ{FkQelR-$-hH$E-EG5H`8E*w&JftB zTiZ6YU4XekQy2WM3(YN`8(psJ#og{T;T@QpfbS{6NZghgFEDqg>G}kA7D&hTH@JAgqu{Gbu4Z^YKRZw9(0hPaX#B@2s$Y{&v}%gUrjRA47EnQ}du zMpG_8rhrH`?@nDNnQY>UTZZB})+U4$Adb--7D#}z07*jBAgnS08K1wE?%+PiG*Hst zqa_^0jp8l``V1;h^Qc%=3$ajlX6zjrz#qWOIMco(@a3TcfJ2n=QK0{e16}fC<;io|tyU8_0Y@oIZ{jfn-B;T5a4O%d#R46!X#Y`&bsv`AaJXBFR z#g>#MV?b@-zj5VO-K}6qU#a8nZ>g2i^7Qh>XDGV(njpV)%vZT$Bfnew&4D^LUxUS? zkP%InZpy*9Fs9E!?9T;8hA8|z1!ZHAFd_5?p{vm_@2b0m8gTDUSVx{_#r1+1dma{} z>N!pZ`T_1Rqpau_YGAbLM3qjv$l-Eli_dhJRv`|*0t4CM@?6sUADj|l?xzr&b10JX zK9mP>h06M9W&>{1LHJ3vWhej2?A3uJXTEA>4Oy^)P)7q?gg{+ZtaD4~Y?Z*V!p8I! zSmWjR4n+!c^tuaY$J(FL2`*WR6TZnjtDXF_IvsSU$YkZ?+8Jy=+>@A23Tkm?9FL^+ zUD9#wtoBmQ!A)EbD53a&tHd_)i_b%8S)DrW2CEx9kHXj@f%AS*2%b&q zxlhCNAKWYu^XUW5vZ$d(y2-qAt-V=iMQ^}_NO*z;b8s>N2W5og?~qVoq{$#(XA<~Q zWX9zCeKVX2xZi|!i;tY0k{+C}W()F5Gu_y^rStW66Lw zbly8Bi;n2Mq2oy`+^TlbeKbwE+RL7`Wm|vi|Il;5V3>Q_*o63?gohtSvIPwf>yoih z>-voRhoo=R<`Szz3a*SCcRO1p7 zn|z2amEw(AN$f(;p~@$=p`&dIpLxazSfW6#Y14={rHet6!rZZ$nroH!vbL2s<(y&I zkijf|-L%GFn#*g@@OB^1Ya`82KPzr?UDT*S(6)x+p_Hm=(@`B?M*AFHoor6`&s8Lm zGO{AsVpG2+woa?9vJ9RMv+dr&%dpuG6!$2wnSBARz)Hd2gTUJ!b+!6d^boXq;Cl<| zrev`EzU#+rgzB90+tO9ayO~#UD-TBREmc_TM4(R$@2vy*aGGkFMVM2?v0VeN5Gu5L z`ycHBGjnzgwFU^t^!fkB70-hIzuJZWZ@xX?|5^?iWaU*v{M-sq%jn-X zv>r+O|4sY>MHY#t%K#yPE*C+ACK5!67wI<$5kE%Gl{t=Ku_r3f6765ntrC?)mu`uv zi8PV~DWIpc*gjWkQPply?XtSkTYc=inI_Gc=syYjx|iMQd7*vTa{6|s#8b^e$BX$!8zT$$zHC+vz$dO zf2-UmnNBfdt>n-M#YR`aJ?JD4a}i6TCpw06ClOQ0qx_}eP|zv|w3{DQs6po_j6tV5 zApMUFV_xggT`0fbP+Cijw7FkG!(_6K4W}qGC0ZF+PJ4gW(~>Kg(5)J}Ts#7+f@!dpVB6 zP?u2uu4bDE|FQ-63*UAonGpb1B2vIUHQFoqJHy@#+eE3VXSbX-dO@{Yid-EmTFP^4 zk4*$&5tG^gmS-VU3z^}WEVYy(xx!j}^w?85nXZnl2(j28yK(PUi_VC_s}GiZmWj=w zmV_wGr*ABIWqNQD#5?PGs&g*EG7$76HI!T2G1}leonkK0TfSf5#LK%hJcGXY$cSB}`LCsZW zhMiy8Nbp;${ak3UTWBEr@7h{IQY^o;DF3IUN=ady^BY=rjZwgsM9Jtm>j9~BOk@Do z-WV~hnnP@Vw(&zEFxOOC$qBusoMhMt(3EkCFCNF5E?dCr^;f5E?8#xAJZwQI774q7 zOrzAG;?G%HiXtGFS4V(ghD);~BULx=pL7|4FY>f?YM-c7o~#pOm9`_##+t6pd*{6pr1mjTXJC4 z;leL%I=DiuUZ)Dk85YwMiDTEY_HGX#mMukp-rv-T$!r{#8qHGmhSJv5x3t)jlBkMP zz`gKkSJh+E8p81r(i%W(u6(7pBbn)(44^%ViZF%93Uy+tx$I>!ML6lmGP?itWYsa3k{Q?Xsf+wDQScTkWHusytPlKvh)rU&W|bxP zDQ7Yi6MlG`Z5WTs!8#raS~_%>h{BQOza(EuoEKrnU;(BQJQsm^pMG9sX6fNGz!v+TPyWOJSm9gYH-cM(rCJR*}`NgT`Up>7$)`46Tg_ai5Cnt}S-OgyBgcvc|hA!x(MMMEf>@>LHNpQ)l2|Y>S&fwI>o&L1uQt*TGRpZ979G zSoUR~4Ceh&rSkx@aV|R9tf%sTjY>D0Z2FdzL~SrkADIMTPW-m3a94Urm^`9CMo#uO z{OuNZa7}8uczBa~Cjo^_6D10Ie%Wl8v18)K!hn`9E!;~U=e4)Lm?0{H3%Mu4HW49G zpuSX7O~me-0^M&EM9aipPra=_4(V1Mg3zp3M0IHa_Xwg5iEu(>ygY}hFbCQ%E#ej_ zpg}yWck#cC*3T$W$rXCS?;)Yn=2Cud8MyVt$;?@!ib?P{oe@lCLD)vrV38HU-{ATL z|4C+>inO>(XZ{7J)a9R&W8PN`!4x);8jn^ACe}XC<_a^;6GFVVUNjm0!$-}3Qt70CWDt&rnb=@m(%B3|K3IVNSE##YGO-kreVW%pt$ zi%D#1clMY`)rQ9yqbelbUU6xohEat_7RDx{+t*;^78dS2KXh*-?fe=rSaX9IO25MN z2umb}KdHv1uVhQQgY>EWod++vZa)O$C|+qI+Twm<#dK0A`8uMZSQ@UxPP%P|Gw*V& z#pj||#*tpdR^MURcStmR9WtgDAFt9Ic3b?6nFlPb;r_S`0aJ_VV|`*jKM`(9&SH)ijDb~8AidLH^ll=6Wp zJCwe(_ve0fJ^U%ihPd+i&(8rV7U{SR7_6HOqXm9_c>J?}yC<@7;4Q9%bfi<2FeVT# zI?#h9T4CV96FAV{?kWTAx>tM-z)#m<@g*!p_U2K*!n@fC!=~qrT)#@csP?*Yk$-vb zCMr2@E6U`?blux>U4nW6em*?!1-e$(uQvM-$&`6)DkvXphqZKX1Lj%f9XQmI6;O3M zkuG#Ks4*{PVej1xinH(3cUy3Lq4mWhTM&FoDy1Q`c-$c2;2ipQV`YyZP`T?(E6c{4 z@F^gtqIh#t@Y|Jg0UYlA)>_EWkhLe>2yZigP(V3c_e#}d+Q!<}fDyclt(H3m^}}9R zk!1)3ZazGA_G9=aoj$m*(%p8k>>V8sdY5aa;!>VJj-Ghw609;thw^4y&x6=KFMihq}rK#na>D z9oWJ2>9)#|-!w?YZe2JrqDEMkA~U?V=!TU(|G0kM`o&JbmQt2uEkyvvm5I>)x~f^| zfxn_X@W3F;Lqg;kHr~1xvML7_5e}Nxh0C4a$U5_g+`%Y%a&UEn+Okvn1vjGE#FZtH z+VnVY!@RisW}ns5nfVcrBiZ^Q08Dv1=8V>FFP>+16Y@lqLt(5jZH!>q4&~qX%kz58 z?*x1?N25;i+>X;{eYeZ@83-UM9#2@oTp{wRviNf3ZijvX0x)@QnJMbllJvQgR<9=N zawfE&58JYnp$I6@cIc2kbEo{aqWYZo>}}H%l{D!lmNp^_KD!qpiGB6#MFo6!tU?aR z9Tv!4!EFB^<#W+4DwnRrGrurK9)>w=$MOSn_NPAoIzc~l!aUf3)e+j`zRE*o_=L8W zf?Ql`6TG&`5Rcv8_xo{GxRO`!Fd%tr z9qhYWhWQ=abcSTv9p1*;t`RLBFrtL8IP`N&U*t;Vw1|4_99Kw1v`Hi^6?VfwKw$1_ zP@LqZoT2Mmjb!OjiJWj`mvqyY4w!6YQ$*gUyYX<}z(_rC2iZ|DEC#3t;ty`;Br-6a z`KJtbkAikb{<7W!(nrJ0ArD#^^(MfyL7KB5V*-U}jqR%cpjMEJGY!A327=T7AKKnA zxU#U#8t#tSaVICXZKq?~wr$(C)v;}-bApa-+qS#p;|LFi^>mTs7BbY7B#p~8# z7G$;#iMn|fKufEPa7FeGr2HK~0LH~9Mgcq&mAj<;WQhDCX)!Q6imQz@F=ca^(cH7L zJzLqN!u2oQHHS!?otYh(ElvscS<-DzJx}UvUpBRc#A7@0axlr%utkcvoKQ|2n(6jX z!pbHsTKzXDJf4i|ANduWW8U}`oK|F(J~9jL%ayJP^OKCH4z$|SC8>WStl~Q;@^_lC zSJ;djHbfV?sVBPBPcO#}yyGh09qLs~8!o;!Eo2SBnqb-aRe~R5WxIAn`W6mXc-gq3 zZ?&l68QMC~D@P0GonQX4nRZ{!52bi9Dn9zg5Z4vFJD0yfsbW;&7DAbGUS>d~j9TJ? zmyJA*kaCF@=pfe9`|@c}{Cy}=pW-;tjYq6FKyNCsJI(yda+mc8jnXsO&XY!Q8d_?~ ziVRMFH^CZ+#r-GKd>X0wD7;O$qCt4G_=t-~c-^4zyiMMKxreu$^3XObO)nA(2^nQz znEd&lo?&reH(Q)aq)Tq8@D?ria6@uTN? zS4Lyl3ah!5b>@bT;HO9qZ__15LoW!{9mB!)Hul7MN9X3N_aR)(=j93Bx3j?>XC?C^ zXW=xLF~`;Vfl4u0rbDRBoAGUWp62th38z042Ucv^Oo9wHGFbqW7}Mo#Ax^}Pw5!=k z)L_1NUdmOQSr*5>#X2Eim+3e|qQbgXyX#S9tpL1zQ%62&zHH}k>tSQ%>CzPp0{a4 z%NFd_CLj-HIhGqXi!Oc6re=T zgr~mBkOjQA>-VpL!;cAv%+uPRr_PnLc9YnM@N1#3$G`Ias-0PljUmXb_NCADm0_^b zC(QV(j5dl0!HL6jRzX`$&R@rc_;+m0{vxhfqY($JqVWv8#a+FQ6NvW9M|*%+J_qz2 zTr^>!E0Eqd(+l;jo8bqO8f2pMyC{NNQQ?;r1oMs;*kg~IvBV9kz&lrCTsj0!InfmN zj|@gIHuoqaE4xs|h}H=Xaj~5BFde_n52An;)%g$ACO&VuwPi)c-VNS59`^!#?yNWq zOjePpB|6|5^R$5(og9>$+>4ArelF~7UF0zOG{{RSGjyqWeT0V-H#W&>FJTDWAzpaN z;7iZOqOySA`t%Q^O{`QeOG)^nqq(>&?Z`fq6%(=M3qI3ufzp|+-ZkwQB8TGJR^xE| zwB>=fGgxWMq_VQ3$^uK7CXn(q5fJyi6z7Q7W}t1h`PNX>JHRR znm!~t&;GmdPN;MvYQ65i%lv9EzC9}{&^yoIEz%2rZd>ZEtt-aL{J~C7XaPsN5D@fY zY(vty8`b4P@&4>GJK{Jc2fwAbgVR~AaMi0V8wR}i!GrU)1cVaQVxG?$;P|Jtza>d| z&-TWBc{l0qbulm~#yq6^vy%pZxQ`CQ7k2FL&vHx_+#YLfwH*suNtjbNSTFthLDcBa zLM(v`uO02G(Qr_dJ7c%dOP(bLdTYKkVb1O|gh@@3S7@doOPpdH&ad`)@M9=m)Elm3 z_X_C*A2xQwnFtP*VGz5Z0m;)tiTf~R8kwz-=MYZH&%c_fVVS6V2pfis*-9sCi)k%l z+k0;$PS#=2E{86}T-V^~TO0A^5C*T1$poyFhvwKV~Yj*w-&O&YbwNhJ6k@d*(q_`OyU`+NUuXTEJXXtN+!YN{`FqeS{1a@o%r{szQ#IWMTLh()J2dElUWRWsK?bVS0< zk-c4SqrhZtTusO+rVe#WT_YDVhBnrp!KlONpRi~FHzttAc{R1~!vmXcBuF^LyLZcZ zW)(Gms2J9!;xgKj5-Agsl9g;X_Qag(NJ4q|+SFIq5P`ZZ+Yi?De^I4Gf|<;w^qktNujZqvL2!H*udb~5i*|E6 zdwy;R9*)N2Sq_>tP4!4ETfl&wA`v@hGBl!9MP)I=FauN_wPXCurif zRUE9mz+XnJHK)us(Cl7hBhKZD_+$vOvPA+UP%LZ=WYL4u3fO%t7y||u09)~z7Wzb1- zz0v=w{He7QSpG?`%F7unE3*@v(vMzzRYc+Cjl5|t?v)G6m(?%3R~^aJXq7MVJF@)8 z^ea#;1`c|9ya|_ZH8LAcgAC}B^u1z$?z#e*lS|UyFv&;Sla_^IpN?fR8TUIwuS;Bs zjGdPQro(X9Ci!3A$YD*GuFhXa=FPI#bAXs!T6B--p82P2n88be&(p>z-}ms)&&rja zEn65f_?lh3C-jB)f5t4o3oIxYzWfWbkpE-M600)xRU7{QFRlNbm_^0d!O`5-=Km}O zXaCFUG-WBpFli@E(s1PcC)bj?lq~^4QXDCw9W8MbX4YX=%S^|sUk&Jc`^ILoqsmEgOPBafaKFG@ni&|>@WOVs79;lGpitm z7&P|>rxleGWG_{?WI)Gmvp_7w5lDJw_2pm-*r3FI$S(_yT8dDHs7x^;BD=zim&R$E z^8^p0a}VOU4U!mAyG|uv8)xc+eJ%$wmFi3CBrJ$-B=%)EjTvZ=AC%eTSNq;Ntgg9= zOcVMbyAY({5d~2xN%idDA^`hx!OZkjwKvX+QaMv z$3hYX6&h5J+?CqIrae%nJWtqV#GAC`Cu)!FRQC!!L1Wn*X5=h%Ck6I`qBvK=N(t|+ zdRR15z%0k5czG_v5}Ign9rfN{&IfdN?G9V}&cQG9^~hZ7=-H}Az#=-D+4RXwsYq)$ z-?QXkUN@xABiZLb$MExoK1F_lbYfCxA823YC>oiFKQWV-@kan2OBEbEA z?Ag@c8Mee$_YLK~434&Vfsc8Rt2BA>EV64~0WSM{@G48~@5?#nrM(Cx(-y;~dbBD~ zBt;zWar5U)qA~@ivz6Z2b%nO!+SGZOl7Egk6xC{s)dHoqaq%`b$+{!Nbz})f)A#K| z6xkyk-((!YtG7W8?2%mUpb_iYO_MnNFz@uOi!??*Dz>SCmB#y#J!s0%eX#Z za*~ix%0AX-f?tNDI1v9Gm{tC#V0JY&p!D(LX?zUQlHwrY4D6~ai)b@WPuB)b%4o$~ zETT^-lL&>&I$m{Ftl28#F5{S~J7Kwltkgp9*RT{OChQ$V)j`^l+&HfhmnR4b((pmXpo)zf1!@lk3Wkg!Rrk;nk`3JLexxbVhMDv%KLZ0fPYDlgmLG> z;c#}vu+sX;fxQx~H2$k_<{MU=%>yJzRvsy+jOb#zS0a3Km**T#^j?)NGECIQ)x^J3 zdv(Sa)^rlQ)>!ONh$uswsdAbzU;ApVyhE4V6WT;}s>2J3LK*`+^?u`lN@Os_1yvWi zg9gSYG1-9vB^co`rW8?6^ZjM70l+E(ZQ@QCb^V-FmYt zIj0(uCDvL(j&FWnp^V$T?F{EaJdn_}A_mGtBFA;fqMHw>jRk}_V)-m{x_>zu5grou z=aN}YA>`xsiw0{3z@_9~Fuzku>V?`QL-0*pXQ&xBwja08t^Ys(K{9h2r1z|HV^+c_ z-msPE!T{|4DB=+z$=4T}rx|C?xF_IuEZ0d8RXPtTmg z65oLq()H%(>b*S!Y>IgG447wII~Ima-qAlrmXx1*UtbZ z4Ywt&x!UZ)q?ug8tXxQZ0|FPWaFpx7#nyQ3zu74CW~@lEA8)XO!zOUKY!lbPGd|Cl z!&a2CeVK@Yd3^cgzgq1L2*W#=J46}ArqoTYkuDMszKa7KG6#?k>iog22t#qw?xYo_ zhdxOIec+{l86h>tc#wBad<$se_NBN|GfZN!eGz$x`Fw*ddBq5_QwyZlqi89aX~VD~YEKCmi!J?$LUxLDts^sW{3*2r^&&d=Si!>> z_EU;RKF@>(B~gt8N9D!+N&3>HqDGpMBJDecSYcRgos2SYOENO9MQ!Wiv$b%Kh}*9k zq5y7hmk2FSaNt2Qbk|bQIJRbO{GKz_3n#tRu37&+X0=hP01~=3P>WawgTubVI$T3b zIRA$zvX0ddOTy5P5Yo-98@0w535G>`Ed)G{PW&}Sgb?ZOs|3Fr7Wuh8*)@f-6fxo% zMnPRk^11X;=btb%CB!Y+*d0?c-SfBZjv+I>XfXq|(~q({0L;D+l90$Y=xyRV=tQud zy;n~Gni5S0b6W2hICyw*vZ_BO$L~DY^QG|}ne5DSBkQ~|oNoIU--a~o+D>=WLOt5J z{!YuStdG^<-Zvc)=z=Ai42g`wI5l3{Y*NL)u+s|CkZ23Fs&k>uEqOaXfl)}YI{_%+R3WNh45%^5^rs2`W- z&2l4=(OS_l05VkdwbUniZKT#yd3w~mqtj@cUKEiC4zTH4^x>Og(Hgz;z(;qY+<5Evedml!@VI1RP%8qM(9cFmkp6nuDXA4S|t@L-Z zQpiUD=am6=dx&SLxK@}$|Hx`Hg#tE;7-MCoOR0=-xhg-v=C10m6N|k()UxRe+(6_| zlhv)Sv|lm{Rx+j$2OPHPRK0*~S%P_on6nrl51Da4TzuTOY^dCQv!7`|m^z|HUzUSTX{PF}zRMjWVSW#LS2paGmK!rVpEj@m7>qTD#s z<@B(Jc{Fc*)Fpn*4`ja>0%caYLxt}pN*?c|tKhP?&nK_k+str2_O^?!uY&Wxy9>ld z5FeUP#X(gBd=7jf?3l0C zX3;>B&CdZbjp)9GD@JCL5003_q99`C%ZRwY7KnCGjo_q zj{;)k?UPyGB;NFlOZ(1PgunGt<~CHSaN>VOvGI0M0#HW~V`C4}lu9G0Vty?_gll&EUe zc1jSKund7m?<8C;N^gzG_{8+69AOX@OmdNmk!zayrc4zr+ca~fWC`49*QttjV4Z3I znu{^JpE3t!MeYoj2@S7!t5)wVuDdnk4XtWeYWF)gw8Ye$*gbLAk~|z-aBs|3mI93^ z3jJ6W_wrl17@R-C|NC=AnWFe-S!c=u*4yFqwrys?_yot=(I!i1*N4d@_QPvt`Qg;D z?aaZ{xovqSkid7B#_>oyVOw?ZoIso{KF@PF$-D5whk5r~wGdggF#5`rbOJ(tE`5vn z2(t7ujKmw~3(J&kmjPyfZ~izAf{lqyf+QIea4fqp{+vMBJ}^|NPFdbdV&1eViF7@Pa376-tIh9~ zwwn98OqL%v?UB!v)Dy=0t=!zR$8qv`;`w2J?Jm3r&mHPl;+@Afa%H5ZjP=->4*IxI zmB#2!-h4dh!wo7O8s8c0xgRf-`nxv3bNe`=akw=x1b?&@;$BKPI zW@QY##~^Hr-e8kS&9LCEc2la0mZdPZKc7VjyIA21`0UDEd-j(Yf2b0|A4$9)hw7s7 zk*umw&%=dhcd2fr$s_^l1Kve-&54mhG7iwQvcxK36_{ARs|{~mB3!s%z|F#(82XDW zU7C)KX#G=&bU}khDV?-D{c7pDv?&`CSFmSXhD%F>Uf%*HXAXL!aM@VfZUa0Ze;BG! zdhUdoi6Io@G@QKk><*TY98grxu$;_TppvrG7$%^G+c2i2Nmy^q9jmUoW20+GY%*kB zq8_KJ;?vgK#f{Vi@)w8=>S$k#-y>i1O2EGQ3)+OLq<(jyT}n1I*@BJBfOtWHbpwIS zZCwanb|HoEeSeXAFLy7i#NfGXN%e(e(GT+3qH)R(otN$>tVs-R>xz`CV#2qd`Z0aw z^m5;FF_i)2{md-o4D_H($H|s7C0t0_w#8$(qjd`AXe@P7?V77Rez#v;SINQsQ22NA zp%Vr>f)jDp1o5IIHJ8|?g_wb}#^$RG5Ng4tNH%Dgp|ZtapqS?8I!r0@;k#q?Hw@)! zIbj1w^e%)Oa(*USdjpx^4aFL4b_^Ovs;us;=>=d7L)mi~nTH%ywIh+qPGiFr5E}vW zPJ^vY+0eENSI~yui;*k=_a$7v-^_$F{hQRt$T1QnWHqm1?pgU3b{Xk5Jlgj#9Gm^& z&CpRRgjN$I?vNBm7dJLY<5+SsL+kk@HmKmNRQ`&LNpWFXHl4fu_JN7@QPA%k@10+g zs3_l6NsFO?YG#lcW@$V6>*SIUnc_2KG3>+&rboCV9J&>i_!}cE0Q0_>+N7kh2J_48+aO#h%iX`kgLb@DTQ&nlT-H773Md_LXM>{QQ^p)8R|^ygf_~|D zyAa4?FIUhbiWO-ci@haRw%o@nLDD5{X4IOa9piHlBjy7{3rla+D9Bx9`Y<@o=vIk`=Fxkz1Lk(D5$N2*->Uw2rFl;;`(^6wFpBQnC zLXH_))TKO;X63sFk#OiPrc_g@CVp>XNdxzmf#)>8o*9l`!R;(O^nMmX^^k5Bgl_y>#k{JMC9~R}T6d?Y&f{Dn30~ z5t_SbtTOZ4zeA8P{iJEVb+-0Z(9ZfWF&fWc88MOFm4*1IjHo3;mMo+YL-;V*s&R`4 zL{hj5lBP?kA2*^Y^Xy>6h{Dud?3)%UF^)H(oE|HbN4qWeeiHJzzK;%uW%$hZZYqB= zNFSRAXK%OwmRSmxe}K&@LlV*o-k?rI>1XMC&sb!)ccK?n(o$8gh*G(3OE69JTZYNL zRR$D{Qi;$?1w7RI{&Hgo75Dd7rwk28#blJWr#D50YpfN?WUfg?43{rs+9 zWe{hzP8nB&**KKLe1r`4IF?EjfIXcp>!yDsv)4^7V++30cG4?3)-2-w`Kn3G}l?D^4p3h^9wcE9_X z@*g`mPRC1ue?KYGO`-{b6=|=eXd7-K3jl|*%94irqA{bHh~}uI{t68l9puQk&;s>p zA3HGK<-a;D(`1=$SNUoSw3+a23e__$RYqe`^orH&$%C$IZ%Hz5tTPr5!z#iRqr*OO zv+oLef`o|?dp6p_yS(NLrH*D3DMEev`YegdHQ2{~YBT$23tQj?NoQ`h2ARo3Y1TI? z>FwZ3_J1M=L!ZzEH#bRM6_YZ3Ub%l265}wq6S!NY0T4d z=;U*)3_*txZ^UE&=3*Vzd@1K%5ALZ1M@llV9A!tNSlJkT`zuY%E60Ce&c-KYI|=-7 zH>aHUDHSs|mCSrSb7P)X1!{EGrw(XxG*eO;7nPf(s3a$|v52C?OCc;;CuDQ)P^X4i9$Vqsb~^k-mMHekCD=fCGQ&f*aXW?NyF zbB*J2E#S#yUOTZ+<*hIOeyTi(E~dhbiOWg0ATRQA9>2SsY7auuNdDVjz+Ds5P$p;X zXy~x!f8v5(UBR(=vfce)LzQHSUr8=%elC|c=rj`*dS<4m5>tk8BHoYEpFerB%sYB< z;?jo`uGW|bjIuhFpr9=$3RfdU<8>|iFc-UF#^mTEZsT#{cj(yZP?5LzA&i`^#*9k# zh@(=fXbn%YLr}6R6I#FT>tkr0kia}U=Al%9TGUuvd72p1nyEW_#gk$f;*effmgL^- zpZLC>$l%lV?>agN%JsQ@K%({m$Lp%gd0dC%U9W87en{Kd(!W&x{BEFcN zdw+e=zTKr>c=AKTQL{;bk6!A23{W`3OH}%>bp`L8X}Uh8W&-tLnaVDF=e1W){xREViLA&U(wE0aoCe%3@hun!P<| zV8W7M?5GBt=m_OGrm_z?>V7G%XAr#_(z>@h!#w)&_|Wwrn-9y)nMiCt5f&n7OvTt0lcZXTgpo|Qr@3+(=DkBsGD=G z3wb_p(fF2U{0Wb5w->5aXcOB^xrn8EjM*n=cT}kv8|UXq5-qM=&hgqR#-+pTuQ`;0gW1dZXVMavS&z zX*c{`ixU>h^`h_1aqgAW@@Ms$J3_?#XbQhpgZQ}~XrUj?63?C8l(!c`rx$L;0e;WR zQ{C&Z08%r74C_v-jNpA&erzqmJ7#-h=eDL^fp9X?Sf}z^3jFlQ#k6=BIu9L@Z7>9_1%*E`f%Cq1 zLPi$E9!)uQyA9%TlQP12i0T8r9qK#t?EUG@$-3v1mh#TQ<}IW>FogOo)w5PCI>H5R zN4vv51-Hi)@p3cTeEwvg{$oB^nrp2u8)2R6F8Kt7z8qm!PzeL`_JpTVsK}>ka#L_o zu7*VENK~sah$$>Kc%AnmvDG|GX=BKbgOKM}NFVWS+{>hB^*{iP!$bzdS4Zk0J8q=9w2t`-%^m?Eoc z)!B%^DgN~vVbw|5& zZL{yNgt%}TAB3+)bZI}iB3QKWT55uJ?Pz9HusU-Xs9T+njBR&8+=z+o`0^^nT{~R~ zm2LaM_z`OudrIN8a4+pOaqsQ5agWuuV~Sm$h<&JE2p0&W`wgKW7@wSJa}D|CtX zjV~^+B!-)*XUo`43v~-d$}?Nq^M38`LTc-!Ejv?>UKj_lU47T?qnk;6H@XzPm`o&4 z!o?WII+efX_%*;N&~74Xnb+^VPVT_ir|W zK5mRYl6zI3YH6Nm>E^CgDXuXqhdk>Om6~y2J{J_gb=HfcUs>>{&;dW@}z-rtHzb&lDajJO-(B|xX9EoO3|=`79HtN;>XPVG;Q zLWc)o?an1kA2E-V45m{46#md@mFVB^BRjDV$jsoKRU@$z(o>b-MgW0~hjBp>#{NFE zJGWs;-(QOyA6 zqhC(0$C{N@aP0tKKGH8R;{x^?knFKC?krx)M)XNs3MFd>$JxI2stMG=vZO_b2p&G zi~kXR1lyx&g?YBZFq!5vNK!^uNw_Gk!3g#7Pa#q=O3mdx>bGydX#Qi_70%;7i>GD& z@5`=c=1z2iw$^s~POAD2Hs&^_|E5_;R@78n6+!(-i6n`Ft`>kX$5$8Y#i%vLHxFzZ zW2c3dD$|dXJaH;MUeUqwr)itP+#PaxA$wUW;hha_OiVw3yxY9%Y9acb&X|WVZ!wX> z<4L>Oc4q6_0L$8sit+2L5S_}Nrq0p&|BG3lp*So zxxYrJrM)|090P962%}Q6>9CFFxQrG!b~e#-mn1r&ns^!Ev_{xCVu`XMzqUZ{!t$#W z4G7sP=%y zcXN`5#>c0&ts!%hHs$Gd%}2lEin?N#SCCSU26u&*&z9&CYEzuNni#EQBzbf+fsC`- zRq6nR35ljp+VD}DsaWTD zfX|S!))m?Lu3-jWh4JFCSI$~t%$)E@?sI}{5pTDR+CpH640svdiZaKq0>i<$KZMaG zcia}M?u%B7YXvD37Fnp{^W-VlVnD%=%tfuCD*|4FDGmS9?Kja&^M_Ds63U_62o?4t z%=*2{NLOV*e#+_tZARkeP7gBUk z9}=A2l|u5s6ngv9LfCr%RxSpSW6jma;}KUR!e_*^LJfmW@=H{QO4;U?3I(!V27__3 z)2_dAglH5XUjsk-bdY-5KQ0#2Q3z6y*Mu4o2j&@T&!)unT@>y!=^5za#Ar&sd-$khJVTQ4Q$L{Rh-a9}~Qt zhR`29Z9r8lKZIk+$TtYQRct%y!B%gFK{%}75uu+Y>LZ+vrLva4eApt);QXJE?tmmb zQ2i1V;DP@~NdH%Dp~U|T($f0oHectIqvOAZAe1B(QTP!*Lq^p(4=%pz@6NK_ zUhj8+UY<2qyP$1;@@TxUu4Rb^LT`$4|2bot=I9=-SBD8(u<>%3_j3Ark`+2vW5ncS z^H+OmfUk6^9Rs5M8U6r$Es+a2f3UJ|K_k&Kp|3Ixcx{VHniZ# z@~3#z$eY9ql1qamE<3>Z328?IR)1_%_7c zh9l)X(nMqQ>5J1V<%jYq@yL;cltY3qEA*E&qE4d8iDMipdUPAsa$y?{Y%?`~YmDCH z)f=9?+N+vYvYms-!@fGji=@WOgl1#{^H_2A8{>74HGl(1$rlQb<4Yd`1o$K)*#({o?zm)m z4by%j(Z2{^Fe+2(6{!IVx@n>mn<4DKv=x$@E z`1L5~VC!OTWb8ovPfd@AvD25b$LQ-%6LYJ7DSVogEEQ*eq4G#-&WNIpC<@8fNPvtd zCU>wJN!nE+##z+Tq2yBuOlk(n`tvC)G-pXer~n{ zXk2pU5M44QMT8E=&b*Hf|Ak5B65LZKo~jlU%^{G-Rv-4uQxt`%qC8p1BdE&P!2uLD z90~S>+``4m&g{4TSzAG6oU{Lq9=-tsw(gC3OHG$DA1wk4GhkTGw+5!XO@gy5G9Sq4 zAjZ^~j3YZHs)>fgeTbIYzRF9s*KSL9<>v!S5fGQBK%Kj%C{f4v;Uc+w_+Z;0Rgt43 zSQ4Tig8r#2aqLu4q)HQLRBQ7>_D?N#nDqHHqctkRZ@+WE(C>MlD3OJB) zPW!7d6f+ASQc|)A$fzsm$^&Gf=XvdfA_wlpgS{IT#;J;wkk?q@8Wx8yAGp(QwBU;q zIfPtMpZ|nb3=$mVU5T3J&F;^oY6!&8jf$J(66oe@0n1z{q#@L-kwi|MDZ< zK%V4s+TnS*_CI+JqmrNj%$7$2JRI)Gmjx6bNc3U1jRai~RFfI?<-<{8$i0Kdk;$23 zD0Z0YdcIeh|ZJ*I2`V+CV}P)#Be-&Nyt)wgc|B=>O>O zgRw|L1cH3~=JVg;!tnnAE^G{qt%ThSjqRMiWbpse%*ygeg7PDJXVyqgq?HB->k+7x z21|0nqJ0qna~KjAbY{o3+WJ}WdKc5Px=KK>+G|077Zr7*Gla>(c&7e=w@+6WD0`oV zA11JibSOCuA%UAfhEUnafCv|x4q_LSSJ9o4MK-v=v4#?E_qbTJfEw8)5b7(58K1g70 z`Zz!Qr{Jf81?Iu**UB9R`F_Nh`n7&1Qpwtn!{GNDOu+6=21O-F=1_cH6?Y{;Q7XRxX>tDq64=(%46~3g-j?UKq zF47oK(f(2@V)*}x zP4?}@`V3sm{*Fe+spG!ga}~?pZ3-<|qK{EhbUtwL>@oSuec5p7KKb!}i6{Ggt-l2m z0z;!Zt{CWQs;MuT7T}7#t;uUE>FD_|owe-T7jvG0Lp$(e)3cEVd$N8%2f*FD-m3-o zpj9EhuDrS0tl5`aEVJq&l&p!>yjtdAgJ=V-E0{&lFx^cBm0=B=T)`z+g7Ci?@kH!SY>nF#$>i7bIw_h4(@DMzh$y3)HgKP>( z`{?alHi%D;Bo&6i3LVKpL||GBQq^$|I_q;!O~bKjhnxTyL#Nwb&-S#$+Gii72wmdfOXpHKl!z!ux3_1*s@Zt z($i-MF6-f5x&e1wCFF_&cs5f#Lc_@zvUb&lv$%9^EnW$ydWNxH;0J#UprL){L=fVQ zhOx0oD^c>^D2f6163-QU>J}|6>Pw&IlXIgy7WZRDR-3a2v|tS8uDdwN#sxztc-uIbO4~8<`RX{Q-6uX5Kf5R z2EiI4AJtD-2r&eM0|EbD4u3Z=T;}khCJ(+ z&BZ%0F^;_xiSgGY-z%&J!c1QcUX9sJAZHiM?6<@QS{VfzZ6>}#D*Z5NylE-}5N=J+ zol{e>wBDRrcx-3Wvb6Z#sGsdmEu7I$<@Q9`0VY{o$Ry*kH?o_aozuj>kY&PP+L1~f ztBRLcb7kWSbg>W@{MuCTl?gYG1^0u#|6mm#(V5lmuh8fa`oCk9|NYSD-&y5fbRuqT zXZ3H#K$oh!9hNHKlLtpfT|@VVpG{n`gjjF1IvEi~g9DnqJdr$JTX9)D8?jHsBZW=< zvb=)|uL!+JdUV>M2^`W43m;?TIDuS-3uqUu$O#7u$Ci}o;M~eNb_J=|O{Q*-DS7d0 zCg#lBw&$_yviqUzllw#Xo2H#eKqNm)E6T!rIDDB^L}**aLR)g%BVpjqIwX$4g%6}(FN)6 zj!VeZ6XDJNwXxZB@<>n$s}h-|eF#?ya2>m+@n?AXFj99m*PRrNT8SkUv{Icq6SFB5 z@FfKnO-m*DD_) z0o{#_Htn_ZibRQTVQU|`+UV%{llXL)XrtD2TYFHWlBl{pT_!Tj#>_lAQ-#y&6qp?f zyyk8k4OL~VJWWRoh>y+8MjFLt%SbGYGAYc2=iSJnAa5Y`Q)v{3iZ`YsCMv*DWpHaV zPVc91>h^&iB9zcRuBlwzT` zQ~)&tr%-7MILUvSd^2;A^)jQ-)F`%B4$%ez=Bes%xJb_Q)Drm^nVGV%o*VKB?ZipgU#s2DqP-#5aQpHjPyl{5v2=F0EWfW{T znkTRT%`-=aX+7>>xnXiox+Puuf9gI87b8%V1EH_*y@{Jmw>aBMyXqQ(7HAI1g(dm;>0DLQXKvAH$INyJ@xap40f^|`hKslG4-;GVo6ko zJwkZK4&goweMqqaKl#nYw+-4|95*s^rhFZ8DwH?TvuZGN5z>3nru z3x~j0j6zgAm4^0RAZS0c<#Au%W$N{JeSP0QectNYkJ}jPDV#Z!BS8pwgpSb(5<#Dc zxbau?z?eveR5K4~n`m=!O7o#>q?6lcxj*fu~bL!Z0UmrM@A$XE(L{;}?67 zT*Ud~M7TOeN9puIrJsZ*NV@hSsKSr4`9(buXF2o@DhalWLV*?`|T!Ye)(J< zRNU~$NQFC$(U)c&m0LS%_8G!;rOpwdf{}O$OeF+*#cU^>Na#>nNUrkQaB)em@-w-Q zNq_3JPT@m{zUY`E8WQ~hX>{ce3H4DfCG7+$glKBCDa_7X$e1#p3to}QBbf7nk!Auj zX#M|qd#5fRD-+V;^sQ5w*Ld#&i=!MCa);z&#^s>ce z9vHKO8ZG%k(YP$4SfpC$+-Gyd(G<`xZp1%mi9Zmls3H9A-ej&|4_`gYjE}-fni!s) zqY>MJ1;utQnj7vYxbsDUX*L&kMH@#Qljt>BuK@k20fwXJ2>7Sw&YTm-pYvCKAati z{YUeM-_Qs!F9k^pz@kKh9p?7asPHgrpg+<;TrnKzCXf=*JAX-(NLOYJ??|V1+_zC} zE3fa+00uo^ovKnVxZoi7aPO&C4uoTsQF{#VmZ@7^pr~89cs=3#8>^5J@#Q0jxl8R4 zE>pRkNGiaB3DE|;OY>$*mtkdZSubv$8pRDvj_=>$m+r3AcrDHsd@$sW2Ew#_Jz@F) z66O2oJt7K#k%Zp{rJiWFR#Qk+<9L-yE@2^TBXYX`1L+$6V z03O!X0L(Rj4{MiSzIYSiuQ)(B49qL|ei+Nmry&)n61tEceMQG&FkkK6j-;aO> zpdD<*?O!ym-ZgmN<58AiJaDIr#R+x& z8h4twGR6efbn0SWA#LMOBn@V;+CcAjC-(wMz|Q>GdC%*`X#eBEwOO6%|4^zg!)Kl^`#HL{ z_pwdQ(hQKXTg)ld($$Oy$&zboHrl^Z4Jy!1SUllR>3ZlLAJ2+f6D0zD4?fuF)HXJ+ zgCFM;-G-@SQRp?X&@;Y0YRXK8<4<4b*v9~jFX{`nS=@v(nASq;u0^Z=lzinFGShrm znE%pjSdY~MO#7nY7vA6LZZz_OQw>WEr(Qxb6|0VumIj+vGItNF3*ckD|w zLyW&nnF0g@-AG*^W_YzXdZb`(*Eyp-z~y=U>^z5D z<}mn?BxzL_Yto|bzp4bg2wFrm^d4hY7W$Mp&3j;VHxYmE{2b=r`e3T*u*ImG97POY zBu`m`1q_v4j&_w3`;bL(xWqR{4Pd0;vQG9nOcq+?dzzdMQtd>t{clhw7WpUJZ~mnB*(C*l;2hc?lo{Tuj7Xk3Nr&7m=}u)^u3@tVXr3kFhl z2Ucei)}7t>^&#*dT>=9*r7rQ`lVkE957@zS#^!1Pu8!Q63@<+$_=)?hERRhHTjhfNhaFHdarX@ zZRLnwmu*~f@hWvHtqEXAL_(DW zsBcWL-p!;4?iu*GbOdZH$N!eJ9-+Z3Zs$(U6q#Y7up7utY+A)15Rt0!%IX_1h=@=qA2E37g)f)1adXh=qOdf8vyh-q zC?<_lzbIEY2%B`+X=9yqLKo{I@>DbDNT1l3ez2t3{fqDvP6?O6Xcrrg^qxeR$nhwa z81)ZJ?vI3l@8uLEo5u|-Bkr(LEFpqq1jRwvXC!(IW5fc1&4gMx zM~3&An31S|IO@&&-N@Mf)03*Rtb4r0rfV1gpHAdrX zG$Wglx5g4lTSn5z+ZW`^OzNYuD`*a5Qx}WXn^#Rs>zID*O9+G-V=5$GW4!p;UUGy> zUSBcB zLU5<%U!t7+r;ALANi<0|GagGs7iLmUhSlOKCT>tt-)D^3t(u~;)~4r$pBF@sjE^o< z?zF^n+ukRB4XI~IzE9Q&Sx`(2+fm}EsrRV0_=yoIsMi>^CJ}3TA(vpsEw5~}HU<6C zpHt5zV!l?@O(twTYUp?j6KhwHHuiiU>+HVHdy74Z-8R==ZR_OGW#*0dq5hs=ysxfv zkNS?C{yPuXUnP?g6Q=Uy8Nz1T0(azZ9)fVK(1M8j-cn=0BTflufwBk-Ul&pAuGf#T zg~HY6FupSM6(Qcemn>H|A3*WGak*e0?ttj%hy|6O(|V4z85_ zfv|Sn!qWG|2mvwo@0#3cigkuv29Y$l8P|y8!#=@6k?;`b1e2U>n1~JlTiwivQb?1? zz6CN_6tiRjKb7yN+4rTS{!;TT3|K@NSO#TM<2Ta9`YXx9e|9BR2l=Yt13)heV|EnS_$|CXjH2ssMq$t{DS6^nN^wN-w6wf|W=9QC z(7Xyf*JQE>ZnFDwc;h}T6T9V`+XHZQ`=tD%wEV+(eMP;`Y$x{&IYS&Rl;5%CcZ9sL zw@z76PjD)ZX`x0QasQj1ak0|?F%ot}L-!nV)$`*0$X?#{9e4v@`UxK4P7qK8aWw|}2CHQ7bbk6@x0wCd?zKh#ZZTi~xhnqeG1LBk95dBi%$)6w z?95ah)YPOz{~z-I|7Gh&HFPvkHPF5hfGI+RkP@hO3r5+&Ttl==gD69EEQ6MTsM|`1 zkB}h9S)9yKWP4j$Ieb1r{VuZS-K|F4YwP$|>b_(9UKpO5=1Hm4K@i2RjhS4`^Zn+& zU;Iwj1p0rF2dsSQ3WJO$kLrvoG`dkU!8AIuSUYMrE{dv6yH9;mTN0%%%92#|`l?P& znztKRcV?;PqU^b+3X)k`IqAx6X{sqYcK8n+w^UVpH?uM$;lk;bCQCZ-rApzUQ{kSc zt<}k#%$2#?8)n!vh7iL12-prU!kRLe*fiQ@OI=e2^Qm?x7m)M>2tDj}WM7z;t*hEb zWT3E${#;j}K@0ff>KQn=P{uexeXSqSH?SeOiIgEvWxXk+l40) z8NplQD0IU`51tk%jN8IjEs!6I^@uu^V3^(dZ^wqplCJ_G9HK)ru*7_En3512j&2;Z z$Nb`!tTG}?Cce!I!dIG>r;cm%^wo;=Ugj6z#zu(OMIV^hs=Z0FtIet{qEvKj&GKz! z(^D*~g^(za%8`|ljKn2;kfBKZzyzGvJ)_XT(nF3SdEs7Lw8p0$y5^_-mhn^k|k^)rBjBt<;av$&<9<)-;6j%|$fwkE~ zr_zpQC)J9toKRy!uF8W<@5{q%oIy%BCmTQa%G@H#kwfYH0?rslm6+wgj0dAnu$iL* z=7z_DQg$vpD@`ReO>9Fg6%I2E##aVL7&=c&&$wJNssYR;;*t65A|kEZbOb=v#Jb-V zGL3RlL1{Zken{6N_e?ywBP6i^3q9e;sQLY29Q47YP==Yy3WS~&5-R6PeK#!$mFr6? z4$w|X96>ohi=;cJRCW$d8tR#5R_AqJi_)&%MyN)>d`f{s#UNwrPf~)nNLFS(9Y>Es zbe#NPSWM2j1IrCNF!BWe5THWOVlXaM1jwJz9 zCamC?)MMLe+Ubw<+|!?c)C`poP2ql+tP#b7UMteVUTtj+LkjBidW7c@t%56I(B4lg zHL4B~#09L2p7;~RHNPup{Lc8aZc&SMg?aNNAorB90PvM7EcYgR)+PeHf?jPxXb5O< zXfQqT*x&T%>Eluv@w;?|K9=Xc5vwrULVC9F*YJgP;b#x~^w2M+)U7XY27O|` z)q~>|QH{M~wgVPFEfI4IS}*0`K2PVPv|n;{1SL$7$%s}`=UP%~+y4xbgGZL_wqLG+Pq^;p?` z)!P~`fBLkDw@s3}V-os6%exZzoEO-84cPnq-edZl3P8Yza3uPsBMMc-{&$vNXPdQ# zXRq#8g|eWw>e0ASyY_pef;)ialEe=9Lo`zi=Z&-ef8(4ngFXSj-G+ z+aAMO5?yV@Oj`0tK+{stMZLXSlEo&ST<4t-MH{q@_Z)pkZlvQsT7X(@rveKhJ$_vG zz&yHFHD*X1D~Y(3bz=h!`M1p+%+E}G0jB*?ZofRnnhr_zs-Y64Eq`E^)>_jU*H1$ufMJiDOkz(K`MX6!seEMuQTO}~3NQAJ0MNPT%V%|LoW#@J10NPVfotv@oH;`2cO2QXHCy#vLr(RZJ5J?;mXs_V2vjx7skbsyOxiXqXq;h3glm zb!gRQl{5C~fe4-^u_@UML2mXR3TYN6etudb{{0jtU1}3xdc(n}z4|at`BPGuI53CP zr_=*s=x8XJz5MIML$~*?GY@RcedE5PpKJAGk&<>bXm%G#M9)^k@FJU8{rxo-W~H!F6s!iSVem=Ku;UQc6;}9FwG7$} z__<{$I%4|f4U{S9OA1y2W`IzC)p+fLA$U`W4~?m+G5Yw{pIxRqjFMc+6JSas`#@@unS~~FSUacXmsPwvHW*s?iu0JJb z@@Wj1ogMn(pml~ehh)H~-(L?w-W=?ARmUmdOo?jCBcZqOjEFYcN{~spnZZEoNtyr$A*9 zwHlQgp=!~&0h1M{^canCjXE4~!num)tzEP_cCXHiM`s%|i9*j1cwfElq+4DlD=8WS z^{{Wf;?W+{>JApwWr({NPNaAbbGuEcd>-hu(7sn?2sh2Vmeul5jmYGZc#cCC7Z_!P zES1J1P0Glj+-A1In8~#&Oq~hchF6ZL@Qsr}_7H7`)gjf;&*KdH6YF6%>&!grWF@S$ zPKVsW-w^}2%<%ozT0>^v5qr54G)9o8#b5?!T{wzQqvpSzU^ktZQ23|B9Fqj6Q>9vG z*|bVgoMDWiIh+XyvRuiwc}r>|IFqJ*X!PskmU5Hw;q8n;bKpsS)Ce`NakkPRyYHZ(yD19fs?}!^X6vUsf%1=#2H*P@*C#9jEM3wpHzPQ+ z;SJ+s!tWSgy{@IR&s@Kv{4&kkVQOs2EM3A~Ud~!w4^k+t`N0Ejnq^{cM>>ifxl>AN z>&Q%KAiK(UbfDm}Cb$|FGJ0F~^$)4{h7!9adJiLxcl^G_wMcfJvAaLV&eNq^ zfup|mJ-tSKw?6}&cH-FQ!p z1g;iGWTb2a>S_?Vhsbycu1>XBOaf0^p%t0^?*;QIK$ei`1RN8-Z=`%oT^y7y(Qa~uy8e-zXH&a- zF|Xzlx^gnDgJjUEB(hmlorX=DHa8c(fb*e6h*<45mNu*(zYKt4mm>@RD%71KGyjld z(}ctKT3a!806lb7!u~6Wk%3$Y+A4BBR4WBt$A*koe%m(7M^SnpOYrb^OZ$!bU_O34 zi~Mi~6<~h%njQuFnV26GTBo}<-BDhFcuFgKDZXn)wjBSc+%cEc#n_7o+srU2cRQY> z3TFtu)%ozw?^^;{?W4#i@E53Tna;I;Kt$df@xon5`Z{cy&0xx{e;xk*-8ZfUx4CKU zv<$wW(H=+|KU;ATHh^K7zs3E~xR5wwI7?XU@0sK1O3G1J-ss7j`r=5JjmuJ)t(kyH z>S$a>;I-``ZJQf~dJ(dmtpTd4#ddJ7XVj?*UN{@Hfg(P01%Xxz0mUDP99a!x462D@ z@|jX|+5(IeB^vdlFd9$WLiUzKgy>Bt{CFO!2;2z(0YwO(sR=`9XU^3Cklj#p3-($w z0cdjEL)#+h_OE?%XmFId^agNJqfcpQ9*SOAsi0fRo(ZhBu<}T)bZA}SX|Ho7h=p8J zc$KkF1anmwtEAv>RZRPRBT7*FQ9CDy?HfjFhAB!8k^PHd{NaC=7bteof6i~fj0pay zj)(fq6fVV4<|1G)<=#a8ImaQt{2PAv3$Q>fo+)usp5F#*K`7`R!oD$Sd5GL1mCHcJ zc-q)C1ndfX@pQ1%>$zwopJ_OeN;vf{^Wr-)zRyYz8S`nwufARvckJ(CJD-f9!<56V&R8yZYzavV^DL(Q+Y| z@toeayxWOoCtA;ykf7ucZj3&#NZ_x2E(0qaRVf1b(HkSy)Rq~9~s#OgLyzBB*QD9n(uAQK1WMdMDOj| zh@O@=WKGnim2HeS_gfg(0PYca-5=j1 zA_%hYC?eY5Lj**6rYXL_i#AEWQpfv+h6OzR7(B3kLOg|Ze|va-VNT}{xnG$??$C$3Er>Z*i?c{i8ORr zYiN6Pci+_2uC!jSj=wantkya({rx-Fn+!*^-<&^xQT{`lKks|Xclzbu|H#w7_O1sQ zoma>K`F(7ggUT5^6=9ze+S=!J9qHaHyT(22O^da}9n*CEsEwKa9EO@(D5+I$e#X=C zy?X7ktJP6h;|>b}f&aO&Rjm220woVGatiIY(drMosDtS3|G823<^Xh0O zly&%*NIckm4{$AA%^{QmKkpP=II(x~ZuKZD366-kODk0iD&~@$xC=lVLv%BtF(^=3 zcX4JwTwE3uB3W%Bgw{K|NVx5tT@D;r3$DpV$zQLiTrOUVr|JZuj0c-DibEsKwoX4-GdXYEBx z{Er$>6)BeYa{W+<^Zcrn%gfa^_7zrDR&}ro+{li^h-^s;0jd>QmrFIvFnG%c`JIYH z3(NWyl3a02P#$dCSX6B+S^TzM0lZb7R!6ZKmOsT3FWlWc=F^sWXTI2a1s(1WAYt%b}Y`D;6|+T9|Kif(Mv=iz48&v z|JHxRg_c?kGSQ=rNotu2=ygCb0u~ai>f!e@hBuZJHTco^v8W)yG06idqHN=3B?-Kj zGn$^1$_;(7%seTSC)(0QF?nR_U3!&68bBia(-GPKBl@wP=+Z68Xx6^6b;k?6)N(&d}Ag_-k(!59zOmk8VXInO0}5N0rvz zhJNNW{9L_V#^ZX&!@LfIQYsQ~VqJ@27*xGH+ofL$nN$X(Pz6XeCtm~)yJBn{@}TJ; zF4g(7%%>I5oqsT<$^}d8|3>W#e?E-v%qy3%jR+GN^hfVQj5o4hUR{2txd4F!X*KvF zXEsDwq(Wp`r;XlAZ-m8G2&Aygr@*$QdO6IWVz3~odXiAXg4A+tIi%(l>jWT(lZ1uE zpzrU}*UE8Rn80iM&@1PZ41KW%XPRi_EmNTcNQVkLE^O^pGVb<#<*N*u%>7ji1%WB1 z^_nD(ufz$4&p7n|!St}Mq3{diy^jZoQG8_x?O@XAga-T$7ztS}#$PA2C-(VHhWUZ} z3GynJIEc*9&pbO@Fgb~B>U)b8*gBDJI_s~xbGW;$kgN|=OH^A745%8Kui$Ze5#2)F z7tJ~GuN$gnEe~tRv5gq(qA~6ghy5uWx@;+U5-_JDH` zqIp>>gu;0LxAlw?+rW-ewH;?U&{^1yhx?R3Cjge9FFSFVko_qh%Ab_g8Wg1sgNJ)= zOv0@P4Is_rYQolWc+qOoo*sD93{?P#z{M!$EJNX}s6TZBSY$<9=CWlY$#%8r>^*0< zT6b_|aaMJ<%S;#wd}8T$qIbzRJ2;m2SBU?T?J90pdzG^ExQ2R8V|ud5P&w!f-5oqf zfSs9m>18b{4d^<^88E1OZbyu?g&zpfiEkOFjP&9+TE^!Pst-kYZ@J#e^I_!5&%cbw@UhG#w*mvig%;-%FM?eHe!MP?fsxU%AW6C zl$k?UDh(Z$Ti>9ab!QwMUBtG1mhk?w-DD()T6imxTe@iWCxoe|i6jfET}2n*O!1zU z`YRD5F~upSUQq%nH{Q;@g5u9%tcl!{I8V>as44{P{KwJL3+X{wK&{TCjk_pSpZ3Ad z4803ekNCr1J`pCv6>f&%lqU&d?;7fw(L?X;NoTB?H-n9h$%h6p9s#O0L2{-s(W&F8 z*5N8OMsSuq{_f^G;+9}g33)sx$9+yZvz)lYm=q?xoVT5r+t8;K+WaB!lahtw15O6B zoOqL0EoYbWq|sO1uJdD;p63x8O@7#87nBQCFw_JW;@>3rww#bJkfWmt-P&kM$d-+f zQ-aZYs^HpqMcfMqXl#KP>6+-4$Oul*MJhGouFwL;S(?Ea^sB_?5!#|^H6k-;ZV_5V z1WY=tzhIoGjN>dtXVB#$yoi5iFszbviLn?5uK(tgw-v=>&_?1jMl~*6K#CT{Jpe-% z&7s^xrhvwGYC02qijp6pD*C4?gd&nhO(&7Z+==+7mvkyS6UreYju<75(j@jq_B((X z*&q(nq&|pn2?^xXAVr!UaUX#lK^XBWLcACL6VGXIC93<2UQn0vgeWZ<78x`0JtBG( zWF&e-c!aD7)~q(hcgT$i3+SeMA0qz=t2kiu~BhX+u<|C?(Oxb_UFz9R{5;LrD4 z^Wl7;0L8a%j;w+p2~oHe*f|(B7_|_&5QY$Y;I9dy39<>22?|G4G^7|3ECm1&B`GCw zh9G02A1=z@%bkb&`1HH`$dPFCvPx#Pt$no>DT$!z)* zcDi(SJyN?a&CMrbt0l6LG}M}3no^ETLZ$G9Q*nydf)!50 zHO@r3#FjnU3n2yzGdPK19qJ_{t5I+xZo*2*V8+E0LbfQK5x|Mz z9r{Nk?64dM5K6y0lww3gK}qaU2u5a0RxpC5q1sSdq-AW2{|V}d+aifa3Nn7L(~}cl z7^4`6XT+>i^+f0y!x&4-iuLHqidf`qZS($JqNW&JAR1yec(J!@qfKyPypnL$8mZx1rsL)>|R z1X%Z!n-9qL$lU1<_;KDq6y$-eI>VX2#|7O25+D#d-En71tAhvedYU3SZEa6r#hC>X zO#2j>=flA<9^rZtBYr)S(%Lq@#|;;mIR25m8Bf}tCVhP%>ZQ=q;qjev(qu}y_DrfB zGVWeC&W=gv7%yMa2=PrNd6$>zW2Jw$rrouU_JE<5)dI0?UF6%dZB4Atx(lYObm^A$3R?gM9;M_QSTq9>qM3NyeHejz% z>w8TEj&eg{>E8T7*n#naYv(82t_!ZH&Rfo zlJUpxgyDH6NQ6{Fer*xgB0R~b8BaOJJZmnt7aP7jVQqP_b~yLPnL4Pqnm*~dbj64t z;k*uc-0;P&r9R5fvA>CvWdgNKIv5)3@C%JRICRDIFrPG5udxD0t1(V)wE%+IZG?}*b ztz{m_eU-&!|D9J07S>ySJH4IgPb4vL+>ljvW6?b1dK=zdquqmBsu>EQts@*}AQ1TG zPjwx+(<|~1hw}12FmfQ8^?7B;=0A-nb(o>4*eW>h#ck7nY?(!WdTnPVQAQL7j5iVQ zZ=bB6pXr1Zcdz|PaeTf3ZhyyUv!f9fJxn1`RZq#IZr4Kd8T{uTH_a|tZLj0gnX8}Y zPUn;&|HQfN&Ji}rM=$1*K5aWk>(uiwF)D5lPlwBCK z1F~|Zt~qWW{CwrUK6aD9J_+Iv5t(}jz@D%WnfoWl9y{9`oT0}rL(ph7xx3!a{*|jc zk|&mSO8S?38l!ol{cYwhQkxb>Op{fdxfkyIs(kYAs^%vj?-6t}p0Sk3iwPrR(kH%S zqet>~yymt{_*B0Zl3rht^6_@97X)W#R!zkS?=H#$Ye}D;f0}8*@5u1|?s33e9z;3wZvp|bG#}e>Km#Jn5fmPkAF#G>sl@&| zL56T^0jm~7+InS;_Z0;oL`yCDWmq-8`DwY0j2O2lZa0SZ~U`3OOeN%$`Qf{~xcWnMN0&##~ z*aI5%C80f_Ylw0PWAlY&eVD#W+JnLGK^OML743jAG|Zk)l(r`f z_I(30iFVEpY1b}^qX6_%E(E;JILhvdPt=2A_7fyOLrffT2ov-}^M09U3_1jI`EsN@ zZW&_tB&`652u_hQ9=0toyO@lIcdWF|hT1F-zZApxM@d};H9 zCWr5bH4%iyOK(Q%WBG>F@5#1w0#i8eOl_%z7Ci4NSML5nJCph5@pl%cvI>xFbg}ly zER4a#4<;R{0U$5)0Af6@DgIEld_j3;_JH{Nx4pLyNZ&pZ6PAn^x#LgGU%H+n<0{6< z*X$y5FxhZV$K5_oV&+a!Dh4zjq<+(QhTr>X4itdfF<>m-tvgD9*R+xGvDzc3Ne%bs z5p`^%BrlvouE^_RXAMIkgGcOh#vz9DA%e5-QXA0(6QdO@drQ31tC4TX= zo%t&Z%RZkQ&RX1jWpwAcQ596$agrZExDsSRW+hmAOexn0Q!o2LfojL$-2;=qw19N| z>@B2$J-@F+3D_0t%ziVatvoXD%=Oc*l~Cn~u>T%?N^tjtl9uD)oU?$8mlM*j-u3(|z-+yg}N+{6x&25H_QKsi+UmH<0sBxP~%`>|c3{8F^5-w`n*v ze4JkTHmWHWy?cVaOw@mc^trcA%7MEOH=xd?};S^8yWzrL}LUp2Aqh8?m@WqM|; zb)%zR2H%KT0mwacP3Kyy`FoJ=TfkL0GZ!?~qqsn2vNHuk1dKfbK*vFosGLSZNaFO|^FDezM7Tu(o1 z5m?#4O~yp)8L;(#StGGgSm!YucCvkm5JAX@p`SQdJ3pQXnad{-Pg(m z>hEI=HJccwmD0w_q`#;dwP6aum)-=!t`#xbyG=cGuCoQC_JNBM->%}Bcd1BKj}zM_ zxA|CJcU^9Fcs?&*+gX4ZnCgiK8mwRq+TY4;Yqe0j0B$lJVbia^y{S81g@oF(T~?QF zH_`Duy-O%*CK>)ZulyNp<^2bFl(n2}Mx;EKVJ4a4I${Y%fZy$$WNnw;yY}o@L&sC* zMx{fFRQdvDaYA$_GNH#P$WO;IIyRHn#|P?tGY!vu9KMO*!_0O|2BwP2=XPNQ|1`@b zfkupBoc4-;U@_^3D-X;>ruu9)pLL0P@yYhGnL?1_1XB$;A<&K9S#db6#9iXQ7t~?s7iww912bfUs9ck8qMG6T+Qb|%S2)4^G(<+ zU?85tC5smsmuRDB`J>IHO1!sM7C--_jgU|i02!Oqf2I@*|E(#-|3U1;|5_UV(%U>; z|Enx&RWFs71hM#J3aOZcJ1KX;!RaDIdxFqYF;b1`B$3J)5t7@sa3oR5G5@*q8M%%P z#<6?=@uwWNZ&9MXTUjjfaqYF2@3jg9_Y6G%b)uNiK}aVry-^qDAw>%?-T9w(> zVUl6DkOZqk_DoYTIa7!|K{R$~ItQC$vWlnPp$aotV* zL0ax8H$rKzq~R&Ue;BP&oW{q9-Y(hHgQxgYdca?X#%rlG-BC9yCs82>8{0aJlc;1} z!shymejx?|92#ALu^K=nH#HdAbGaO%D!%Nz-;mNEnac$~SvKbaPmyJ*A57k)C#XL- zowjekDmqMqW_edtr@>*hT(0tyX2%!cO13zTmM+A$y+HGLnuaxV6a1Wo)YrnyHNKx` z%lL|pg?9R*WpJU^GQjEregpYfN4Vhl2j@?KSP(%K!-zzp1Cj{oJSuX%7{#-4-p(H% z2}&pCW#rKInf(JDdCR(TfXe8uQ*L6_O|%P z&kkF(t?@p?jzAmn#^8lm2z#7S&O#peZI&pQ!tf*+B=6+`lj01tlN!?Gq3;^#&|z3$ z+zG!ATqTB45L)G?`ouA2YDz^R3^QSwk;n`&>S@iwrk=#F2Z#TtJd+*wI*_Y8!*>Bk#uL0!Rg!$YChuNjoEvzdL~{~K zujoI*Ypty5+~PF9fJ|c!+p+oT3KdZ?khQAHY?3YIQ=d7ZT{rzjp}2~EZB1y~YgX{t zHrRI-=#H7_29xsA;!&%)Lx*H(a~lEY`hwU7=jz(>ity4lEr8%Is{Q%;G{whynuYF@ zbJ&{DMeLy8=DT)0%>eV(MeNrOe`6W>@+yT5rnZP`h3k5R` zIf$V>v6HfBE>~8IWrc%r_iCQ(?mM)JJ3kVRqE4DAyHSQ;{uktuJ6%$nyE)mJT#lf2 zg1pu=CI+EB;rzbu?Ha?Y*LgBMf}&QQhRZr0T6Ju!Y4V=mW>GfVojTWmzSKZ@`2NUJ zff_kp4*JPMAK$`3y`QU6RKJBroYkp2Q+#>l7JcD(FIvj0H}Dcb;g&19m79yzwD^}C zdtaKCO{im4kQtRwPI__M?T@A3@-utVtl@d{?7C+<*SYOl9O3CanjPhB(^ccLBcfbx zgDnjmRctAp@Qsw&f%{j*inV+e3cJ&?QW54BSQRWWi_ImdgiZ#N!u)kWPl zrxsHQaawEaif-@wgqGUFmpMu!%wk+V{VU|N zzOF_19;vY;3(3J(Cg~5jkUzinAmF}m>>rE>UwrOQ%rYw+s7-WGArJrsf{mH-*(#08 zq>+d#dXpxusihT9nH*`LgB)X(y2;j%rPGLy5EZRyAHAbkLk*ZrfxFcKD{z|YvOu}l zJAWiS`oS2ff$ypar+_`#ZrWRxLrIkXV0e|ILR2-%_mRQd{+8&I!^4@8Zqnnss9@nCwdqTEDnJ{~DYj=jw0wf5lZDQU3UAfBywOd0KHUr*5w-BoX5jVSs<~u-(}o9)9b< zjEB-Kf1x<699z%GoLhKV-L?dvzLEarPm=a%Hiz17$hw+K=aFBhxTgZOxVO@GCBMWd zQ%&mWyE%@hEXmVdNmJ*u2H=&MM9eq)Cl0aO zjF?tnP@A73J@3Q5C1DznE|aNr%lga=r2iSg6T?W1bb-` z?W4|>=VEI;^=|Y{E=?M(g{x;`Su)=|sZLtZoZOKx+sc_{hIHOIpNHQjZcd(;B~>1O zd9FNawO%T0`ze(*Hz+M3vX)%T=zyum>P@skO+`hRKzV70=%adUDX;J6*sP+S-NVip zx?U97W53JI;W&`W)auPkr|VEe?S4U_M!%RXVd%JL!JrSJcf(wyiqJe;ZFZ&?WCkA^wpmy?b*W0u@dW~e{q zr8U@-^Vkah2m|IQH`tT(NL{0oV<7YQD+S2VXrjjzhHZtqx=a2<(b zv!Y3*gUYsd6k{vSX@x`_}e^RnBzmb`Nz3yR5tMhWX9*vNHb`8J6ZwAT)?v^mI zh<0lFjKBD)uStUM;O#t5q+J+UAUBOChO^*L{7@cpE)7LN^%jaFsoy7n(V}d(&e`KN zJ?l^KEBNGH4FK)lmZt? zTaLEN5CYH8&{KcRUQi?Nr<~7RvFAMoruGWvkV@fa()i^UgL4M3Q<#1B_(*HlW#@!G)HRxupO)SgLTF zGgYgdXz{^F$=&|jjzGqlN;7a?C|1i2<)>5tyFJpA5v>+C_z3}i_Ac+_Esv+|%=H6&WIG&@9^06SQ0;1vS|_o=R=WTk?ulzr8p~52 z-K&j_->Km^q`3CTHwDtuCME{;A>+3D1RveFD=gk2k#=e6LZD7jBdk*uj@K#hRS-D9 zWUC7lGo-yxsJlm1cv>n4C9If=UaTu;0VX&8eEX6+P~`g>XX8p_uGkO>{y=( zarNz1n#d_?QvQ)i;gO6){FuxLNsnC{Mv<5-;az&thJ5i+ZrVN`D8jF@uQD?q_6J4%APq}m<_AL zw0(+VaKas9(O0pgBCeC~3BRIrj&`SYo;5HOwo+p0)3pu?=6Uxs>JBucfdS7R*wqSr6zjHf2l(UDsaZo&oCvGL zuAcht{GGkj4%axL+%eG@hrjlZiPL47o$Pqvb(X?sWmlb>X>^`gx=7&@TGcYoINCQ> zS|fUc>G7?|rFh_UOhaQVL#5%fzRc@yXfNMs*vysXTSDTO;TKT#Bh#(!+gIn0;=Ay0 z={4Eg?GG}vy|eK4Y6DoBl>+2lZ)9|g<@Rsfe++O#d!c=zKfKN>jQ{mr@&9CY+WvP3 zI8!SPNqOHQtrp<<9eAFULi3 z<-Hk)iKOjhWWCSXKa<^L)~7Q!dq`F*++`kXCOYkp-#fRTpYK1Hy{o>kd-7ja_~Lu& ziV4OOk3sBgWz;2(w2@bQwZbYEeFF(qMkDW|Ob(3-mJZ(f%IrMXLzgOTR&NE)TlPnF zJ-Nap2&?itO57EM_}I_5)(?lyq~{bM7m&5))1iD@zCK$D*Jbz%HCU z#^)!Jw2vChw(w>Yl;nG-!5xfPXvai+_YXmV6?`>9mC-V@c*tuirE;MUIJ=!dD5zd_ zN<<3IX(Zg$b*)oLqOg`V!nir@Jf<=5rL~lPtFP6`Y{hE;`!2dQ2&PUi#?B*4gGMWa zCgBg;=j8(o&oyIs=Epito~9zZ9Dld%h1V;bFLCW1D?w=1^b3JHL0E`CPc-rGNRmJ` zoNa28ti{Z=w@WwlBb|(}Wu--ghf}1)hSTgXu*VjRkfV!{ghL4Ua(>1^6tEZ#&?aeR zL2P7CEy%VB6)&8yYbG+8{N14hSZD2QzAePwT(REy?dyKF{de!zoD>D=#86XZA07Q| zDUzG*3}3d7IyN|B@Qf_<9YtD_d9k4q+)C_KE3;SHcTMPT=}ny?F9wxfH_9#&9~zZ+ zK@yyy<U?%mijx|Vx$u(VFAP_CK_yh~Z)nd|LI6>#bct-+P+xrCFKE?S zLH43pBgVHTWnDKl(uKH)O|jxJht|Ax8>C?D+TH4^pl+)(w2 zTGx%(({&<($lw`O zQDoyBBWAoVO=V9e=yMn$4vmB;(kp9K3#S(+4}CZL`SFaEy1{MMecn^H+NRtK-Y(mJ z=gg-kbgWAOKZD2=HmD*4yl1-}BNIK%Cy?j0oPZ&C1MJu&J$2daMWO8lQL(;G6AvuIh*O^sqAn zw9>c*B*1WQE=F+JY9_)~JydY{%{wQ(Kg>$rF27IC6`jm9I1c5-JSc^Kv&`f|61h|S z((0RC+jRy7K%z5?V;0+_64n|Q$tEj3qTtsH;$_>Pqq^jCAZhEGa3-^@)XqXr4g;`e zZRukjrgonc>TW|T82h;2qhb&R@{-B=UhyY9Z(zR*H&7mrGLlAW*YabjhZCu#6w3dM zwmeM6hzcv-=>YT`W7&)J#;MVqV&M>SI9>y$ow2JME7|N}cAb8zB3TLguGk!Tfm-#% zlzChN>*8;(wZ^TeZ_%(2<<>q0kogV~B0id}5gLWcS~d{QUolTW@7*4S>;!yD#Q3@| z3)!5`td=O^ufsx5!i+V@@n}_34`?R|}K(?eY0aO)@kt z5MVP9W2C@~{jOB&XH)t-|1wkh>qqV0PptUbxp#7>KLWC@wO^r2Rn=LdqKA(ZI6zf< zV05<7{`aUiWV{z|m?AJbL!+aDsxj~_KBo+isgf>kS8u5oW2dTNy9qu0_0lPv(Or;a z$|2Rdjo=&CtwG1f)w_YORo8!pU}^UUDPP19dBnByrM&_~0H$ZEfH^MJA8fIG3S`3B zh8}_V525Tv1Z&l4Y99}85pwsmGX~2KHo}j90jocgWlS0Hpaj5|mtWplv)E!>u3&tZ zeW&!?E}$hkdks8TZlk>}FW*7iXm=+k|2Ehxz8ilq$Um#TFfUtfd}bAUi)CH!d1hVe z;qmlj->Pm5)+1*GTPaY!#29-f+*EzQ{^KOvMX}X2|4B@!{f`^3R{zr{p}3W)gQ=c{ zsoVd544VHdGC6<-JiHK?qOn1EFfCvXyTQzo41yetSk z=xq{rXSxJ%FbVy~M>>i={CpwOGY7<*FmZ9we%$dqet$IGo&EiL2c;m0Bq)rqK<|Ds zS6>b(Xvav?rD#}kP7PP1RZrnz6v(^QN$PM^wU-%%FYJE)#*BX-}quMy%k@o?c zue>311icn}oMxIR;q^KboPxzzZBJcz-@Gm6egGQrayUmizGq7cbfBPp_Gt=Gq_reJ zcG&_pWtP13Q)?7fk$9BuB=et>Tmd ztB^?BVl1aqi#r!U+VsPlpA|b1mb+FlLPrO!egVKgW{HxzIDg8fH1toTmz0w={tl`_ z(105=d3@Hr(t#^T3DTp1>K51xN$v2oY1~pfsz<5|`toN?h`ghIJpmq&mHi?g_l%s? z+?8|JnZrpxTEwVfPDKVN?!a^@N~u{8e-1CICeMV*cNE>3nZl}y_A{eDRTNTaw%<$5KLYZdnlY$MbtP= ze?pkmHlqx*UK8KdjwsvUSAai8&nSEbl84CN7Q4=4Wt?CYNv2U+A2;g+n|9`+DL1PgPa! zsw3DQ=-01yi2rpk_&?L*&Hu;Rp@NaU%}@54k(i#9;g5yk-@=c|xjmvX()VV;Wz(t3 zSbImqAb=@GTaMCf5&(3i(mK-m+}&K;>IMnq`ex1QWk2bQm+u&8BS${l*$(LEuQ>)_ zp-%$FFJ3QOw8stUwIVw4aKQM~3(pL9oS!YC<1OCrRyV*NnvD1zgB=oQBth(T9Or$l zU9-NOCgXC!D26&uo8mZzjQ}eO@WtKyvzHw(Rw`-dp~MI9O)1LCw$iozcWhE*dIu|x zM)@nYt&ZSg#iZ1ucV$Ky3}Phu07pssK%YEf<@tl4xpLTID4fv=j)|1RwA%~tAPLTL z!aNKSsYMw&i<2M7Xi3=lNf5(9T3Wtl5duECbIQ6jlu@T!pAz=+5fovdVLIov=?dd4 zOXCmyv0_^#<3kr4ikRN{uh>9Ckv)q4MBE(5)s2dC$W$WJdC^q^of0Tykoxj8osQhW zmoTXXYG@0{t;`Di*~k$W)F(-Sg6WoU*USF`WmXWatMwPln` zgB7P|8F?xOoIw}{xMnE^x$cvWg-1!32)%Iu7H-#h@?jY+@?G$t$#6!zeDF!A!38|3 z$XpiG``5=tRk4yNBi6)xV0WU6A`VS4l^Pe?{Qmox@Ovva0mW`c<*T^+*LNy(D}4GYZXMuSxX$?_CGK zvV>_RJ|Ra$@wlz}7mSSZ{H_AaNQg_E-)`tITghHXe6TQKI6}(W$P)(LSiv?w+-V5| z-zf5ZvMBk-vb2zF4fU$Fj3fDq(ki-*D1LO>ki7DmQgv`m9gIO4sh}S^nutDW`UZ4w ze&uUDnG8HBf*3-mg_R9+X6Zg5!N5L&P}_%uA9g{(AEeP5D8wXPEfQp?b9;6-&AgBT zQvS)PtL!ol1_rDas6uk?L1=9ySIgg#pmhobu1Na`Lw4ch(G?M>w+O;|_j=|556#pg z6-C1AHVD-tF38oP2WUyZtPFlnuWR3O_)n>_E6cQIep?DO)CiZt+#4d z>@*T-T(mPR82~m0=!`cqZ&g8}s%*)8g6M_r&SYjGyNEN>J~=($&|(+#M4_2+OolR; zpkJM8`k|#--y&LGP@qg^ii!7XLL!&OelbYm;T6{b z#8dc}H~)oq7(+^zu`8#!CmC#?vaPPWNW~VX{T4d!1!edKo4M#Zb^!JyFP`CJSFWhyZo-ZkRt)fP8ivl5wKIDbjQWPy=%Bo!0 z&=)zPK#_=-cld!y+n^OK5h|2-ldpfK(AY5` z)?EBp3m$%6sQ&LMW}5%65261$d;ab4iJP{X=Yt#Sww-Gems)R-CQkrJWGf)=JA)4G z!}q1|m4i#raVueYim|d?j_njrAKrt*x83>eLN-uA`~~(nGI)P^F)@7~`T04#Z2c=s ze?3_AMRz4Av~4YXm_E272;4-zh-b~F&iRcEi+DemWmitUOKE-{oYb`7l4*k1G(OnU zQiR#T=?n$16D!V)sp$R?68sr#DU4UJ}fJ9E#u%d#%h160Yu$llz zJrhG9|GW6|gi4Zj5pS0?;MLQz!ILC!mDBVZ3o@6mhC)IOLav`7cVUCQ%BKcF7v^53 z68NTeXTi+}qAZ}Wi^YSj3(dyqV1(hwyvfA$L&fOKkJ^M?FW>bN?y7L{`IIgEg|B^S zs2kGdU=56a8f}Urbj*IrbA$Nd`#238vKxi^F2;Uc+CJQ}Ry|HuQ(*HIRoVF}oNSBO zO+j7|?=~poiMZ{paS4^GiN&O(8E2|yEe{)? z$KD)mn0d=1>dHIx6IKeA%QJ?JY7h7CZloK^-_MXY86Sv&@#}*N=`Dn{6p;bc8}aS$ z!d~a3{}}Gdou`p|emFRjKVFspdm$oIOS2S$|%%pVELJ2VsO(_G_51VXHxWdlVV$3Vs#I9LW-h@afZPRyBU32Qt zQf#%7yrGlYDs`Y3P>2RLOLM*}nZ%={rY32wup?d@LO%-37ZJrXMkAu)tHut(2?;Co z5ri`wDOELS( zHnax@G81!WMouNeI(YOr>Q+>e3hCv#tlwz{;ciY)pfB%qAK41<8P zOkme0gd^UMp4skMQLWqOoX8{g#(8Zf#_B$$L~(f^grP=p7NH~PZ1kaTX2va+z&_{J z2%UA0QfUDyn6|&EHZvB1TZ5j%{Cb0E-@NZ`L(KIu>MRW!dG}G8#{+vi;U-eAX@(_| zvaRM&v(L{`kXnqI1I0sg$oWP)2%O}a&LWFK4XPYcwAwINz7ac%u6gVQ$BGbDL9v+A z^KI~yfdhZdb}VomeU0`nO-o!~nUTGAK|jw!n1fnU_%$KE zn-JgSj#D~6w4HIEQmG|_BDYv;p6TR3R8bjLn8sj%U{sr)d^k8)n9M4j!EZ@(?M6m8Cu4sdE&+8lYs_0VZvI$)V&B{}ra z1r(vo0CF0dsX^J+SkwNU2&Ir;QBEhW1q#8}I?DP_y+ogb_ zNUlCnV_}FxK-QVoJ&?DE2wslm@i&OFGt9HV028ARbZ>m+1RCK+!i|d@DCgd8-H-8o z7I5#v2ppXjX-4?sE;liZ*R#j~^g~Q#+tqPgb-}Pfr#ao4p4L@<@mm0$gd5nl(rlER zvrG|AS?m<6KUrq1Lj7N|LFYj%p5$i9x$X)YkmO~TNGG*c{w7uqG4>>{PY>MIVSyuW zZfy~uq(=L$v^oT!P^}(FYEzr#4LJaFn~uZ35Ye{0Lv1R7m-; z2m#vqc~XB`PqSi+CS%n=0K4fxM|%=0?Q&jI*`MN^b%S6c%&bp^j$a!JEQi^>0n@EKKSW3~2@#=0+Ct)GS7CX33Jl06oE!XvOu7 zLP_h1!gaP3(k`d1C=%mZK2Y+y=T__c+LN=sDvmozPg_T54-<)NcR{2s`RSo4Ktb;B zxzSnm9uL+KWMPvy0k4sqS_byXN6&gY3WIA~PwD!kzb*tzKr$O0L1$;8E74bE^S0&B zE(Zm=n{g#TqVQDG_NUo{h`p?F7v?f>4wB!nV7#_>Xo9!0=cA*fu!gFN{A=EHNo|!8 zuDSiR$Kzgpal;tM&d+^Nb+c~U!@0-5piMsR#VZzFUG^Wxzr->480pFWcX-spr)dme1;r-Z$ab|8lA z{I)2JH{`?#@C%-i2-F(vpSc06>djvXAGV=J-u$U&TTj0ip3wChq^kj38`La(ndv># zvKU&$$c&(P3!24teJ;@?0Q?u3S?M)Oy~+S(gfya!-V{a+$dS5>aW~|88NJ^gCNVv! zp}t%1#Rq$$16Beg1I?SbbKmfwrj$0O5ZXpCXJj9pY7S7YQQp^AgR?|l5+?(~)s zCQ=SI-(2|Dzz6%nqO(#p9)3Ii{(mnedOd+HxxW6#oAq3& zvaN`@jQmBTAt{jLPXs9PVH4;*fEQXq11=tMIYh>g1Q>$1yP%@bQ9)Ba)gV zyWTwYkeg{*Jbx->vKBn?Q0f(m&MLU|Hq%|I_`K0hNfeQG8UdZ(?tcAamA>{k-mriE z^X=*dwgcjYE&$u#F}j(Nd-bQ1*^Fy=QQCh!t;b@KK zA5UuO>?WG5nOZuP_eRR=M^%V^eQ@ptS7nBi8xx63xVDoj!`iHDAablU zF`TiY0fV+>l#WrD%t@E`O06z!)0gcUth-a^spg3k9L6V1gQlcelb=;wELY{yH?p){ z7A+E5JIl>G8fx|6R@C7|3u>xw+ioPpG4$9d;|nxf^-skRhS2&)0If6?L0DNgE0wf^ z66#uu?zMHobrt?~l0x$TcXeGtzV?5DuUWC{>vl zHcIHKla!|^bL7pGkakoq0}M`Qwqnd!T8mJyrL}V&FQYDRYU|gw;sk#HQ@Y;SgfrH; zB}z1XkX1ms-u1NW+Hz=BtW{AB$A!=-v!^!3sIod3xU&GNZ-MXo;Xf{GvJpf(z$KCD zJiSOPQkT_kAEmbmJ|Gi`$oBQfy5z+_ticNU$=n;sm%Nhk2>IgUL)fk!!8oh7C>C=Z zT)tTukjtnXBgk=Wa>^swE-z2AVlA(kp2IkX=AV>iBb?Q%Md*VQ2OZcF80u29$PkoF zg-U#->_+bU!Hq$2FS2tS;hgHUK2*%BV_b?nS}xKpmCm3w#E*Jj287Ss@`izyDDXq# zBAd%3F!$@S<{7SAGCg1jw$RioR5)&PkPE;pJ$hQP!I#VksPQ^|C!{02${;bzskkYx ztE8tXTX!vRbZDA2tr&^>foou5Mx9*nS5qTQ8kOsre>Blxh*azYcu1z?6ta)oVK1wk z>$KxJfK0$Sq0uyEo*Y#*PJT`uGWV^Q9cefzI*5hu!e)|vZf5mzmZ>wg*qip&HDNxk zUSIeRBT-IrT-SBFF+7dNliVq>7;PTbd-7WZA zX@oUfr6g$K2b0e#{ZUynN+C;YFUwt4_yQhKz)Z?SXcSJK*#~jf`a>S!8APe=?9M!Y ziXV~vQ9YT))i%uPEz_(^Npso;c-)BOnJE;$Fn7_B%K=k-{vg?w{8h~rcw--QzulQw zHnARIYsPq&4I-g%?mc)(QJT|`+6GXns8*oab!KyQEh-j2r1<;G2@b?GITN; zko~~;z>B>72d#jf40SrT+#ZbpPyF^%$h=?SG#ls?iM#x?pLcJ9m(GKi{tfE5TN<=z z-{p32vbLN5D>Ag2;d?oI$`F?B3z=l#tM<4B2rScFLLs;JPsXpfF-9q`_k@}(!K|;~ z!+V&z27;VVAAKMNAl(dtcCoo}qIQ9E#09gt2G($ZBC&ny4dEz`X=OLSL9B~+RuOd< z`T)JNv{km!UnT$zpf5b1RdciiJbz?>v~ryTvry-QYhSWs;r`ACPt#ux#;CyDJSjL) z+%s2kCo)0i_{ZfphrT$Ud}>F`ReJrtmZbY#(`$9*ek6`~s;$B&`Vc*a_DPqsJbQ2&bKe^yho9_XM)+;)xl`mZOJQ?2ZfiT=FH|~UrU?}1wq`zUxnO9KrSf?%W@rhYk0HFw{gM;1I*)79YmeI zvDjqjH_NfNt+>FPc@@3|>r5!_qu zz2Un*XW3t~Pup*?cz=D4SO2QYE$JPOX$&Y%e(lc{sKj&V4L90FgZXp&(3tz)@7AbA znUDKSMsDm0scG6*XrabJ`lB*hUewT;GM{K2@$E69EWKxyVC(Zx_EpS@YB98!NX&P90 zlxoD?UtVA}nJyge&K%r;3Tr0%YTbbvEZ0J9VJlVRTcHid`(hcbr=EtE3QfI1^hDjTW>%`T(>xY0bUR?l|>BXz8kNT$1^dUqyd=l5worRAqsS* z2qq|o3^p*qej||Wxq=`{C~S9)cH4)$sytW@Nn4g4q3Bopq#AZc7Ai)%&urP(Gf(Fa#rLuMd5tQ?d^f@^~8f%p@quOa*h7fWo^On~mrYIJyKB&J) zO&rkh&`DjZE8MFp%>rVCg4{|8iEHjcu-LQo{1dy7(Ck46nhPdi&9TLyyAa_-aX$~< zgJ?s4RK>pOlTCFuAoplcm}Y=7z1FMcIzu<%x&{aY3;I-rr{Jq@tRR~uwoz;sX3`?5 zrRU&mfSn^0JPDX2)9TFnn9J#ZVJcSd$N0WYwBzKpDSi&YnkV9| zIv_off?R_m5$6=ADP8Zm{jr*g$XM-lX4{<6gQLmJD`Egm&DNVgj~TTQ6z+aWcWi$H zn4q%Sewk>kv^xr*b4UK7i7B5a`t-qiUAVj!LycMcB5kQj`P8NXygfd7G{C<-gHJ=O z*5N6t$KV(xJ#m(({(1i2v7lFHUgYo_}-3O4t<%(MvCa;l(!Gel}Cmkqx%jEG0A!Vh}enDED7z0c~w}{~Vj9 z5a&yYe{`YY|7cG5^WPks#Q%YaH2MKgJDD09*%AHoOW4K0$i~6c+UnohQ0%k}6911j zwB_ATLz&~VS4NbRVni>~lA5E%f`KO%0*4?|kVY2q&CJPi^ zWTOwGyve-%d|q|N>+Sssasz(H&Mk(J7+_O2d>1SJ_Um;e@h6N*>}{k(3JEVH-0sFm>k?;ZJo7;+ay6|>8t$W zS<2}s(R>^f=V8Qu2-uHDoe~j5i7-`jO7YL=W1WjC#ww}k5X8h*Z`Z)jvYCNz>l3#L z_hTNq?~qPXdPoJFhy+SBt&?|%qF!QjHejX#1A>S5_=KroDh4p_Z zjNI!*wtFco_z4PCzyjhEgJ+ls&I)TFfe7$(tV)&_re{mFvu@aH-2kCr1Aw?aqWD7~ z^0PNSK(J4#nT+nn#wJ}}?;pTDo+}_lKsvz%nS3}EE}^0@qx^hh%66ih`H7dDQ|Wl< zFS(2{X1ym)}@zIRzz;#2T2 z8K|G!c8z>A;vUhdP9nr>uo*hljc%$rF#`nx>_ootm-*q^l^-@e9l57`q+zG2dI$1& zG2O?(U0!%IWw^=dNH3VO2H}tvbuFQ$6Y6BSRCLM8s@jWX(Va$=S9C}F%6 zj3`n_Ku2p{V(FtbvS*1Gpjwu%?5CR}=VF7MrV6!urhIMV*C|P3eUC%8chXt|alVoO z=idy4OroM~?*#^s$+p6}y~+c%vW%Hq<4^L)jc>SH26ht0tP%;5=3Z+WkI&34nIe#C zm2^alP=;8F7CUV{_212AA6oI_L*w=0wOb+jla_ZQE|c~p1^4>paWa(sd$K<`@4XQO zsv$%V4TB6lE_3gJ3QvQGFi-o4GEegeS9f~Wp+0wGV3he3sb~CSmw~is`f$>cywME` z`waYKar6)5SH}AAW1FmR(=uX_UbPxt-7iF%j(6gW>5ub`p2dnDj4Gq&`4^)F^~%`S zF5nD9Sx<-~uiP~HEr3jGKD^55ktFKvxT59c`*WEF3<9*}USoFgXIu-gyB zh9}R)1O|^JQP{veBY1cLqnTWZ>UufzMFk^Yi1YIMgKXeJ2ktP8>OJz)_-Hc1`-|hp zbc(DZxB$e1ZpWZV+BrZ7bRBjW~2d$2rFyf&i5{#GOdOOkL{>r`C#k|&K1 z>WPdy*EC7Wf$v`325p}x$Dq$6q@CkfKoSNlMZp^tP38pPc(O^ZFY5;r7Bw164V0F@ zv7WMZ7I*!@oiJ>~3^3b+R`)4|42+C#1>W)P?SITb8=<4?6b|uBLyL7~$NBr)#m8xt zRP(ZK9HLcJq}Ln<-Yn&K9mF8hw$wc+@XDWjZ8KQWp)I5i}BOM)z{1GC8y8vioG113wEq+A{O?`5^1twj+nc~Qv@d$ z+YcR;5;GtcQ%vyB;fsS9#ghP|Q~b1ELQAFK>Eo%|aQ_VHWe!=56G?C!pos5#lea&dUa!`3G6?l;>Gh681%x{Fd|n22&pdbC^Or_h1s;#z;J`RJr>-B_g7RI{-Or7jZiG1b|qKmv5OOscSaE2#%2Y#)pmNeHMk@*gQHDYC-_8 zvXEE*hy->^P|?n{o1jy&+Zf>k%OBRJ#V*OcI|n#gd_Z?(`KGtT0-6s}aUt5o4_8LG zU}{RGAgtO4bMF{!96JAgw#mLknI4be?LlZ-<HY zPvzD9$2<_3|8DjDqc{C~fc{tQ6)H(8BJ#ssiTeaf)BQ#oXy#(#GCVLw9^~hzSC&@* z>2S#*X_scGS(Tog2s$uvRfPTe<(*(OZKXdTmZ)r@Y+a1I{`t7f_IESQ|DL70<#kK zX)d4vRG3K~VTsntPVgh+1C&2Kx`aY|;TW9?qeM_-=J##Fsrvf}9wy}|-ZAAWeZAZG3?|#n$cISHgN?n}$esv@vKH zUCC}U)gXDnX2USYW=Lb^Yx+GMd<`h2@udky8PX92bKxR>A|9Z1ZYCbYdpq^;Rjk;4`ofDzu7_`ct$-PqRP zB_5UsSOW=e(~u?2&(8p`H{Zt893;s~hLKjl<5@wPfKrSL%8Ok4MLG#{d&Jdl+!`N)zcjS$hmB!Hr8rqlsKr7dDJ0WKGB_?%Tw*-SVi@zyjtINQ&uF#pnIp z)MQU8XK^~&u@?429}Z6QMeE3{WzK59RFVWNzsr=r3O(=u4JO6#i=zaF9@U6u@(~wc zVzuJCl*Q;;m6p@e(rUQirn7oBAAk_+%UDP3=#G($^ycO_cKNt!sWKv*5&r_yt{0ql zE`cY5yuFegnAC!?IC3Cfo`OFV63dTdPV92$ijl!X1PHFX_@|E#nce-R^ZHWVx~WZL zPxmYCsusLPmJFw4OP%?;O??g(p_R_otquoq1U?MV-**@l61!krD<4L{=f2`cr%+bP zP21s;6mnw0^j3d0gEga5?JdRKdSwX~1n(@`O6g`oS<4&Vqd3yz(F;5DwVW;dNhlD+ zo5DDIiNP=%aV`ryblueGJq=JtNBFW)yM_pWrj-t#2$Zc&G*&UqZ9x$a>c`0lViZ>3 zf%)y4Lj6a3AorFEIlPA;V+nDkfH5|TPhXmBcCyli01lq=CjxD)mJC*=Pk+@4Ja=!T z&h$J=xEX{c;4v_-iDQ9Mx4P=v#*FdNvDd7;S|5GNXdXiednQiHt4!)8PRKIg)_cooo)BT8MErZlGBqvi`+67r&CFD z%%b5H^L#ieJU7{_5qh%GRLLLbRKg+I?5n7$&b8QRR%><7T5E2uDpPekYh2&e6@Mv5 zyBFBvN2|-#r(S|b>Xf|}BYCi$aHxbth2MJ9WjJr_D+8N^sNIK{#IS}45sJ8Ng}jT1 zrmS6PalO&%Ef&ROFAHQeVCOs-p-o@EvqN1%T+%doW~Hv|)_qv5jIT^62{zo{aO%62Oa2IOBky0w*p6MfDvb78dq z#-^7a5F{O-ICdw}X3LOT+aM}Dpj)YkQ1xPv1ICh3==0f5WT0})YFHR64xJmam2k0| zGrSf6ZJc~rWuRz~vwT9i5~tXa+HNNUgAv;uh1hXmSl`SLvvV(FwSc%eyEDcYQJA!I zvBUqHVsm1*kOHZtz%dnqm20j|V9=ILM?Ao)MNW^l3EvHglXIr6~n8B+evoMoTzg2j!*p`xU%{<9oefMPH*5BppO;)X4 zS{Ppmm8XC9Zlt16YJ9Jfb)UX3eWp!t5GdCXbvHw$NO`$vk-2(LOhLYi+H?^?fxAf7 z#qc*+>vUNP*})Yt6?(E(TKV&?2AG%3AQAq{FTG<>c|nyHgYShgD&xA@Yr*1HBU8_C zmGvqkVPhV_%%vUchi22`1W5O6ReJT6cYxg|*n+SMo4Cn8EN`D+h3FFy0S0IuVuMI} zH}C?_Wate{N=C$qWf>NCKVfuYoWpA_RTuBV$ij8k$zZ!1_2L%gW08}}tGzFRU^WX| ze^hKEE*(+>`h2t(?qB*TP1Rje&DR!`7=_=0VPPxL zE3>(!!A*d}sVmS42s`5u=S5qDPnV>SxbujfOsq1Vmz;7_^Lsc@euRac)}7y5fS0RC zc-jRpHY}OE7siaqd&3Aw;eqP4R$OGOqV!EJE4c)wqplzf9g=vm>6s+N9+&W<>Rl!I zGj@{q&yul&i+)$_sg-C=juS`G(PKda)n}s-7^$l=@Kb;MMLqF&UI*DyWOX`ppKHFs z2Hqygc$asA*Qj)}kSy^Zuf5(AuCi`>5HfHeBz3vhB0XYXPQl25qum9C=#ph~`q1Ya z9Dl*@#a>1%WiT~M<=u`{82J<%jJ`$mGfR9t9ygdQfs_x&kqttubn`=Z0p?Y{F?#~W z=PuhbafxI`)tkg@{%BEE0n3bkNG14K=TnRH!56c+`(d+=_{vJVQt>*Qi%qCor4}N$S>`X zw=*5kn4NLxazolduKe%^+0)D3Fu9jwKV-;#GG~SZIVdxTqsy(th@4Qbe&$ABU~n> zwcLnmM22F&fgTAa^dO|P>TZsTB2h32@)af)^#b^aekwn!->h0Q$*<{D#X!>DNEC#Lkw^0R zvNt86T?@9P`!Z}4@pS)Q7Od^QQ{+|5XS}X|Kh!~*n6ye};QIx#POz}lB^>g2xO2Wp z-#$!f56d(fB4zHqbtx1wEKimtoykWM++PPcv!1n|M#i(~Nh)PdILvlvds4`&kHy_w ztlLpfT1!G{Km0{;JoS`|OuZOm^}?vlSooGknr^lioj}73wk`!Y-lFcw zCSKe`n8l-^4O^@n(#x(L2GT{F#e1y5b5_h4R`O{XyX-I0ZhK|og{dYs%$WKEz@IW^ z{p?}21y{+Ps6(@$*5!;Oof2*A^?b4$sOI9sM$|AO&pZZ98_}ChGJ#S-3HVih!lCES zN{nvf2i<1|TE2C-b-z+in+(O5fCu(fYP3;g92S;oI>IS)I?NcbmI&s9QvQi3WC}W( zbe^Hqyk0DLm`+NW50%2Je){0h=gK^{32=gwVlS&BcW^5wMsp@xLOU{~h7|TPP+?>e zu`xzb)|T_%GB)%LCQ4j89~a_>%{}d*6Y;+OH#2d z2P{&t{pRZ+aV+^dyWlbHKuj>~Qh=EuXISz=|4|KtPyK|0q!354`&rZE7R1r})|6FY z2&jMjp@2C+$~{nqF_radS%=9~s^lWPfE z;-;f1+QuN5!%esN$IK_+zDJ)h)q9Lr>#)bF<|@LxEM~3# z_c9}iWvXXIJBpvIXm=@Ro|U>GfHK4P=Qo6uef6x!Q*|rd(A@Ie(I?D1ZYKI?lM)}E zMce+_`4Aw*9z;Z16}V5*5;8NKec)h-gcI6(UXh2g`%aK8$euv(W+)P=H%=={5ol`g2Dz7$;p0Uf_vsXK|&bUmSKL*aOncJb&H#m(SWy{`ES3EY( zxpbYf8r$9`uD#3Hbe(}Ju47j`md>HmH>%Y)_>CXVm7Z_nDRAg3P5#_iVf9@IRGUPj zvD8?YEetKO)Rno$?a|j)3R&UUR=lb8Gqj?lHGAo*2N+tx+HDxRdn<`;D7yX5Z!k5c zmK}e4N2A|JZGMaBtmLy-!+-SlW(rvbSnqNT1%@)Q?%0OpjgR@g8spb@7jGPSXywh>pwcXZ}>l1_i?iJoHs%59WgVyY)0|ES3z>OFI`{`oH0?@Uh>v1 zQD#riZR<`sVdr)DsT$xAFq5*-BlhPJFtvDu4FV6G#jWIs{y5#yEv^M3d}F<^5AQ~P z?>R@*rn21(AK`zNcQ zL0Bb*+=9Z=?Hlh3R?Hy2+50Q-0g!tANXWYx7;ZVG4Kl`Km5}=N-H)GOjC7+{*_P3(zQ1}D4sh-R?)24UC}9D0u+`I7oZ;4}Hr z(=UHs>y}iqH>ngbYK}6Svc?!dPAD~1Shtuspzmi7p(6pDrRp~T-x5F7_L-3Ba2i#I z94kveY9h|2@F0gs5K{%87=~O5As2@pclLxsq9&Q{O%3Zg|; z+JgtSLDVvBpYqpMw;Uu2+t{fQWrdH8|DYu=-{`-r1EXJvzqxMbEU^xYQ7V>6TY9Kh zZ~*8zSpa zCR!M)dx+%LYhE%dml1mh6Sg2zI(<}Sv!cM7?*{!3o*)8L_yY|(s;y=f=(lmw_cjWl{#42o7&{l<) zJfD|P+WH%UD_}t=+9Qu2ij^&8Ef2<{gkz2ln(SpACU9X_AghBgbjJS-*`ij+aD* zU7~zFM@nf;Ej&S?pHp-x-AgcVc;@e>z=03aolt(L8MvOTI82*D7g*OpidcMElG|`B zZ4qKUsIptHjvT=ToXF@67xQOcIHtRX|Bas0Y0}g#nzw8THnnvtB*d(8^EK;~z9lW* zm0t*YI(9atGU}j=SmK_X>7kZ7zFi$Sxzq|~#rU&jd$+yM*%g{kJS&T&Q~c=P8_2vT z)UrB2{P9o&0dT!5BGhv!ezzrA6T0Vp?34wjm`lA^26|%_UEQS% zUj0{aueo#Xs@3+Lqd0-d^$jXR?t9d|d*uByrnFC|&Z6S@MK}ifM}pg6?M; zL~1;`DU~Oin!wQZW?P5665Rsj`658swyDQhZ?c_^7&lvdY`Ek-XXkF`{(_WaW{V`v zt6$5+ygk&B(o=2*Gn-P7>V{oX0Gp8ed}~+KbW`VajiBwB9nvDa`uiO=C})g($x$ll znb`opJjmnutl!rCQo^04bluDg#p>ITQW;vgAYmg#-i~w`#W}|0WIs%T?i=~H_5L(k zWChax8^tU4Z>v4Yt~D9^Q1XxoAgvvyFHeGs1NAPazpMMRr`O?8UVo0t@V{HBhWr?a zIWd2N*87tGa%vG)ddJ9-cEu=0Pq%GoA0F3HwrEjcaZD;U6ff|G{sRef> zOXBM!i%jU{nxbMu2|4-dw+{wF&WK4EHRiKA?ILTo#w|Wz!;7^xS&j91MhZ>}5f`O} z*Ev>^UBO+p3{SIg2UrcaUl8h*8=I^P*Hx7aETxWT$8`f*stW}>%jEb~y1&1a1J+m~ z7HAUF`CrwLC%~K()DA?e=Z*R^6#&AuypYjW;l{=IN3CDnviDv z8xaI-G4zUiMFctOQHJd*RYzCO9MXgBOxToTlPOMEHu;D4oYQ@$W+X2T)a*hSrnT!> zyOQjg*?zh6;cwX4L9ORT6h-Vz$rEKs6Xg*RZoL#7ffeOBjQMI?t90f;v`4}0#2L?- zwC=~bY#jF8wC(iblgYU?L{%%Ub~+UL>>|>W5-N&UA`J$QB`V*Rj5ZqZN{^(NtdyH> z0rl4U$22*^@10t-CCaW`dY2Vx!>oq#oqDxhEom!3PAa~N5YEmR#zL*x*F2$bLo%Mu z69O(U3Y}>Ifztkg8~OSp*9|4t4UOY!k1ogQuCAT3?mX8juCXqa{e#}@TwAO>uro}ssJ>NPNn&;FFZe*yB62)gn>6ZqSVGtIPT`O0 zNKL3<4|vvQ)~%^*P-kTFKrjle_}ie>3g7&m;RzIaxKk8*$mDvGSyA2J_*N{K4U5m| z*#qarT8>GOCB)*yl8WuwAvLDdfkPH1#dmiB;yn0AeS zaZeUrj6+@zR6hZ?`dNvUaU9GN{!X5A(Wvt?nj=~pux0Z|x6*e-yP)4Gdt~nDzrl1< z&b4fz)B&S|SZf2&FRxf%%7A9x?la|Z;<|7^E1o$?70c#l&GZpGjq4jTFf*D`rf)u)^EA&9SQHO0 zjdazPWV&6!xcGmVQ*+B)n$c>D1vpG7!#*1+V4O-)bbFN zCdDdF>@THrYoA<*=*bq6G5@bhgX}Pw{ zF+z%}U^3oBO#fp>NxHz(Q)tbIkPVQ@`&Bn#EH_0Kcu@Y?N4{hO=cASb zwHffLe#Z}a)3S#H$z#$_O4T+S0EmLsuvZ5RtA1D4S6a92Cd^7Ok8*Q^R@4K)V_+ZX zzd=(r!M~v&iq#I=s;~M!M(q^|q78zo9W(9(T(X!v_qL-gqI#&*0b)AWoHbB8=+Kd) z{Q;uI$J+2|Bk=2NbvlB#KUB2DIqfk+6FARYxP&^P>f7}_F+0`l66O1h*t6!6N1S`o zK3MC3Y?*j$TQ+h};uT`ZTOE|%p}MrxIMU)W4MPKO^bC9r+(@^6K>zc>?TsU(HHr4; z&mH^!>T>6Q_b)}!+}h5{SmC!ON6OsV-08mqXpH5iEfD3=xLMQ9GuWENr509%Hp}!l z0tA7D`%UuYtjwF3_~)cO8UIPyax#Lmx*B}^34p~9pk&98@3JUfJ0|{ z{op?Jdc6D`mHl&Rb`l4FCS=sbhf@oE@YkIv^sl+@BZwUU?ypOyVp>_M2N zfui0?eMFKuq>*MNEpSz7;a}vq;jBO|2;iy0B*A;!iJS2uxwE_|N&sTsl?;MK!}k~n z0A}&>mIt^pjyn28AxId9G~~2h6?pF0L7wxRD^Q}iRp0JLH%rH7XOy>YTDn!{1>TFX z`{69ai9_rKY~SW^gkU|eElDeYW?SD`+tsVsYALcp1S+Q68{?$ z85tdLv9k&j!>cF81SAQ`;OmR|3%|*x=0X>hZg{?iGM3;#WXNe9b}lBd-~_3iDcQr5)3&ZNte0Onc9xDM4m>7wP_@KNAL)Nvt9)Fs@x+oYkgM(9`Q*+or#>5`< z$0gK-<(A%Ts6cQ)!IHjFPaN@brs@*?ga*90F%7dadYe1jQ)9@Y258ieg`j^kf!#n< zBX;D2wOxK9u~xma#^x*f8Iz?)_8MBWi3hx$RrqlJ3FW4$>LOv!NZI++1K`Ht`SdnCoqpl&6EI~{GsiCRIjBYu9vjsS;r zWL~I?1uN3x-pM+Vy-;|=@S?25*20~31RCPf#q2%aOl^}$CT^DtVI@HTr@C8U00A(< ztbnD>(_}dMk|^nR@kvNpD)O}y)Jy!3jz=3(w3$$Y2$!b{0ZdEQQiVpSv4Rp8fr7hi zz#*azZau%)wG@;|yNqZB5JxHUxmbM#Q`DS^Ho9daP@^i|ZaL3GjgU#7+1rzeTaQy) zf())oqbwj5Kn0TfGAQSg_^t7b-I9bUk2EA0xV$UM12e7NvdKm?L$0Ypd~#zZEJNj- zgq#{@-U&QX0ln*7u3Ezb58hnW*;!7~(qkeLD?d4i8fPo2y66^L+Ok}(ppnrnl5OH! z7qtD;`lOm@P{Nk94R>QRr^ zM>b%qw%C|ERN(Q}<=Z6C&Nh|#g-^IPh)aT5l?aIZHR6sXDcUVB ze>RCv^*r)L^6WF4I0zah1y3_(JY@mIP7I{`w1skJD{wH3eqK~jdthY1TZ+(F+Uq08 zbd*~RZ#)Zmg;|23ec`~M7X6Hp_EtMxZ7LMz9a?egpq&y2Y9A~S23sn+_{7{`#meFU zL~>hVllh~$twa%>gPi^C{b?xgyktp|D2-EC!mT%GCzxDcf5WR*d?2_}$mcB1zBTBW zk$=8o1dTgTBZy-fi4cACWJ_EM8;!7I1y`EBJmW6o7sNs}mwWsQp(01?Fb(BX3yM1c zZUQTxw&6@&T>NTQPIQ@&QZFVFski(sLTluB8_MnW2Y0`|&0Ld;Jl1yTc z5W(Sv^mQN$$bWKKpSwNh{F{kD`^K?R{qzXkg>*; zA3avGjpdNMUrp*#)o}CaJD)#CZ{_))OA9*o3&T>l3 zu6%$4s#!=^SAvn@@pDiaJT6O6a6XJ~-5fRtA&wToGGC~W%vy=b{7sZ@AS-U#3Iui) zPj)~mF*7R0tX_%d8^M?OFw!yGH>nNQ!w%)NtgPbl!i+5*E8DfRUV)EpQb}&>uj904 zHsp!#BETZ#LBFr}iEXcI5ab!3S9v}II8 zCQfvhB%IG;pe^`7rPx|QxjGqY`2mA|X~crnx{Gh2+{-486qxFSH2R{>(LRm-=&k!5 zgbwmR&uu^Koglcd{my<+e+#3th70u!7Kx$kNZnnYOm@o@Ym7i6#G)xR8b7O#)SW{8 zS>D_!Db8mj8EZuPX5iO-Pz`fA!QLa(k69rKS8fgT<$RNgh;a)ViybGLOqZ^RobKrbPEQE2nEy#1`QNjHLOBy^UA6wyMEv~)(RmdBOvek#LvrZTDH zjM=ByL7fTqYFDqV>fm`04+TYEEfE(3CUWG4QJZ44sDXxsu_S@L8(DfajJAoP8B@72 z{%&ru1dY-BkkAT$6btgn0jkX>?)3^fFP1FS=(Q@GWzI?BmRqL&DmpG*Q`8$1XZKqa zIz*PNZ@4T$Czj?d#ks?(FzZh8+})iq8x=X=Hqi*g0ih34ocze87>#Jdn{z;MV-!0c(xlL+;?R=};|c8C*i zF?x#PyyZ|WZq_4u=1$QBfhXygVlH35`&&o%YR=$9q>rdJd`Ya0`inbbV=ZEDIoeiV z_KDi3@;|_3#5R2_%jg(itmJ_42Jxjo0rG*3Q{%DB?I>i9IfEUMrfzHcgdPiwkK@#MV{2|0 zR@twt$FN1^1FdS3#s>t9+fC=U@nrY<)Pp9E8qa)@eELo5`n45Lcp^EiLeWvGDl8|o zf{d5K?G-N>+!1i;me~dm&BX|U3sLkwz!2>q|5}>Zf}Xl8Oz~$pp_*#E@z@qqZ@gt} zPiJFqVID{pBaYf}%FI2%=40j(rIL!>GimE3#15UFf#@DeD*5>UZWZ6^HA8841X&tI z&7;QX2>3_Q71Na$k?5`*G8UP%CwvQX z^t*v<0xj7}VFWgtJWR0%nBg!!7wc0lB_lNS*V138_p`dg$n4{`KK!jerr5|}w7m2_ zS>c1Zw(Hfy3+pTos5GOj#r0h?@z*`b7!sAT>gc+!ZbXX#4| zXAs09_@o!06B8t2lV~VKd_iKy8TeugkkwCP-IN#j_5r(uD6>SjU3_}c5}-KLPp<_o z(LvHx)u5l2n~{2?M6nvfHGT|7ANv9FmDm;nYf;B{i~gbFIp=yOGdg9JgX=V-K<8A$;kZeX$dWiNKW~lUEHaL`U3$7icdju$ z0KL)o+MP7=4iNv~NeTN1U-WjWM+`b84DkrIL)Hz5{7$DNw^gKtOeI~5db|}ET!-DC zr83SGCeiO4;zdO(czBAkV_fGo10xfW!R*gPnHfW2C%}LrrvcAxZOg4|!zBnK=v}2G zM%}7jhG9RdH92{Ev?wmqQh)bP%(ocUtRWLI6>mRa;TS$1_*(PyDA`CW{Xx_JV*AHC zq{uS`@C*j8_mbDWy10-c90Z|Dx8w%rt6y$U%?iQ%@O8W#b3yLm6w>V8GHR7Izwz2jP{o#X3`_<8@ zl$4Ek#_6F5zh#J7w2E#%2>;uJo-=y|S znL?Dqb-Zkpk!O=q)Ygj_JfU&Ok~Ng|hT$e#8b0zvQWrZw@+Uh&vaq8NMGiYdazMKP z>MXK`8RT|fL5=H&g!=5PDP9y~{GZbBVMVIFQt)j>rgw9c3);D7*}`yZ&dp7;N1PVW zbsQ5;F{NA5ir6~uq-(ZK(tD`gQd!1m?m*NvpLE!D)%Bi{7w8t=5makagdf<;0{w_y zlXE)meH{#epw}9R(=lMxOhKUs4idptzt$mLnbWewTP29toZ($3jK-P3mo8?@A@||( z^VC_xs?HNEoiU({bMnN`oKxW&0PI(Gl=#Q0f2h%WlcF=6cVlmy=FQi2EfKo(OIGRf zj8?|^e8JU5;LG&L@b}O2=-fLRWufkmZwQ62?h{`AP`RZvv?fkts2oVzGNH8^9B)-e z2QQqTQ61Wkg*TNhJ829oJi}uw+uqFJL(WgeB*nGN50BB%HGIPm#)sOZG9duSGl7&z z%qFYDHpT1H#;c|-#xAKD+N_-s>&igEn-_^fZ<*|NxKz&TQ|CumYFFn6SZV-gdsu1& zXFFJG0%u!TYX&Hh{?w&$fRb`2FIyv&tar`@pU^rxz2imi)H+Z)`ZS)&G+!8l-=zC5HBlnn z&OIA@D;!b%ya8Q)S1xpp971KF5*g_q0=nJ5J4Nt50QU#9`kh$3*@r=}l95&)-lK47 zde*GKH3pPWT6?)i;Azu6oc^n)nm?v5H@N7XyL;?Y+m}__!8^VM1GXE)=TBW8Pq~km z^y*)c{THQgs*%cp$^Rq)6{-0C{@NZsQLm8-0rco8iyujap9u1IU$eNMX2-tXdiP1a z55~{V;g>()!y%VIn=O8YBLfy$o1_RZ7gk|JyApWa9r4L=OP(S^u+oqHyB03xoahrv~?bTs=Vm|If6R|K02M|EvIh36zHV{}1-q zSczX2QxxfYMaMI`n?-T}4y+_NglGf=YREwmAq>)7LsdE)Ktiw_3B|LXm7b*;l};g9 zu?X*Z>1ByffoO)Cxnc>+^9=TE_pH0(!iUkNPh7==(YEJy+LQ5dXOs8m;~Loycna;# z{H^N3?L1;Ti~0sRyU8$>LZ(};wYB@{`>OEre0xG?yt+iP`XtV2{_=)S_uiKMG3B%Kskuf8m|<5e?gONpApskPRrYU2HQRSpJx2lLxDtYta8x8j+%8F#XWUk9>+om>UVvMCRB zj+gV+yCBFzIiD&T0GtyS-!*^%+7VljWLuay)FGjRB$siLO4Y6}{9Hp_+u8j*%2_hS zyAG~`XAP4XYXUhhFQsX;g2Q(zTdI_L;7Zi8tufSOgMgA)*U+DPwtId`!MTPhn}CrZ zhlvfVP7B0^3>T14IaVA}o-sF--g)R)gcwKiY|U+SfFY=GDOUXI zVnF9aR&8UkleWg(BeT{@sBx^~Tn|+GLV(kxpUcuAb>yi^QXFIKDEx5Px~V3wKzp~g zsN3`o)V7G-_&(jVzFjd3{Guj$DT~K64^C12b%|_&cNJu0J4%`-R5ZyFAvrVwTzGtV zst6o?Bw;lnr;;lmLTi?96!J%R6(PV18dLRVN3L_`9J)YZBjx$CyJ*<*#i@+aQuG3? zA}Ga!3P`_KvfIkb0GYna7FlYJuYy>7%ePn+Q4f9&&@s#q}_- zpD2C!I6YbQI$X7n`U0J)3{tk;=uwu&5<0-?s&s^suqI5gG$Vp+7=lUR&fp;Qq>hXH zG!g>>w=Iuvs*3P3x)@DRQ`-8n7`H%L`$XBUzDeo_hSoQf-=?h5F~(5JwrFRs0P8J& z?A!x#>)5taQLh>uE7X1z>>(&E20L}nukixEt6mh6`45!wT(EVN!rnnM>ytrOv@-6W zI&Wi_5`xn8b_sDg5;Ad#2!{3KWOC)a#fydWpZ}_hPoOxBqxq$`@BS8A{C~$=W&byG zIR8Tohlu|F4jWV}|B|JYk-lxj)Do(Q7fR&HH7G3r7O2bACSoI)tXo6=fb(7;>ae8R zZQ7--cT1X^atubj`#Oz;^0<}=p9@}}W%|Y+270(4k|2p-qcb#~n#{7l{)Z;D)7bm< z?||43e2X5=ur7H{CEFHOIk2J*sCGH{)Xhs;Q&W&qwQAZ!E^(s5p8Dnylv1Jlv)HSkV#ZPj3n_hks!URf&8N+)V+BtMS`B&V32 zl?1Uw|479h%A18Y94VtfZRaxk%{_E}@F^n44V!@?qtkH&wGD-UD0>33x}p{+j`a=a z5uMMTv;BMz4~w|w!dbs2$P9eNYL@iV0hj*Eu^{|@qoNxqDpc2`92*X0@Ywx~!sGUk zXPa1rJw1qBZ+Ce>e z3rabqM&;+?<`Hjfemg=VAH@B->L;k(B7s`{i9S>)z#qfRa9Vn4)u=WSU_lnwq<}8$ z5t_6%_?F^IiWN7xRbzfv8R~lvJb_1QL>8OH?sX`qwWvbdMOG_vM176Bj_PY!_Zu!TXFMeYssa$|4bSUz>DD~vUntj;fFAN zb&6R=ttkEUIi`K_9xN$(7`pvJ@2dI!Y7-$sjmU%`DX|8RB~XMk>VrLmCsN*h_2G1! zGx3fT=H9)~?CcJU-d}?+_)OJ-zMFInh?W1KPnotoJTJe|PWJ|SrbX!!#Y;0Gd$!Ho zp{;v+dcm@8)_nqXuMhph)p)le_?8}YqWQi=L?iO`k*K3Ngm(d(gXxK0QB#_xlS*Jw z_Q~|~6;7-W%VBhKkw_b)QW2{$z_}zl#9!|jWN`O4G5MrrXu{M3@i;@Lw~LPW2HXY) z9NrC&CgCT>V-yCOMj$;mGY#A{`st&5x-z(-Yt}cMfbWw?oCl^NIC4xnQdmQI0Ouau zbvUAb|F7xCgoT1?^*4-+1opqul>gmi>HnlDbpI{E^vlKh6&0TwkTnu2;^6~HOH2ML z@V_Wk%Nl0z1DX~B@qdyF4vb$(tU9kuTv-41{3HB4a5cSXDkQ}2ONHI2XLKInJ@CB? z{4IT;pr(rWlz=pdD|ELqpDXShgQQ*FlXIEua_d752@1>Z0gnp zcb4pbEa@>$gGwz*`@mQAIDH&Zr#%S4;{4Nc{N|Cf%+q+5^ww(5Qnj`Nbsr_gRI77M;=G1KB&Ez+eY1fIe=KA^RN{yy={jrszk_YCCTP5 z#b*)3j+i6xoe@&hSP7L&dXX~zT^5UE;NYK+f1N=95rT-Jgq2u%$|MAzSm^>iJ!cTM z2MkT^7LT70CsM6G3BP#UjJ!X6kE|)j?nt2KJdJ*H|6A@kTl&h$TK5LjAxt8wk=aUT@`^-oVupT~%d!m=RbM(n; zPhG~IE`lcO_xf_sD0^=8jsrpIGT;)t@@$M&-wGj)Tj$8lybgW)Og^4Kf%lPLkoFyH zxByRUhP2^h(~-_yt~kKMzFsE~A8IXYZIUnL92y$+j%1mUo0)-|JIA=qi>%&#ydvIH z`i+McLRYrdfuK2?K73E5pFl-4|2K+bdx%iKdGyy*E=9z!EeaobDJ4+U3_Y5JnE44@ zm#rwC{j|cL4vO^KdrY!$JTsx^)&h+`D!+Y%a{WLdcZH7R-%6Xvw8bc$KRI%uGu{dm zt4(CzYFs~a2--XWsq9$V(nok;l8lK#kcx^R%pz2FQYydrG{kN*rGXC%rz&*jT=n0n zJzSj>UycHpsZK#(UTi}Vn6eZvzI6Eg!TX{E?+go1&Qld`*KUqhwL02GQtvvr!hfu_ z`%F3|14r8preWZeSkAKZ?XnmQLXSz5wK4&-FdUQL)84F4yi+5UL+>m0qjlQ36iV4k z7(7FwP~)cbRq9K2Slda=-;fjO?*ioZ3k*%8lABwv!Lz!9^o_detR;rVrAHIkOb0BMb0qS*Q>nh zPS;Q$pUBfzvDrI>?o2U(e*mRL)<74f_Cn`=CLU=-8q@2xP4XO+ML75=8zbqubX(og zZ!9|6S>Np~1oJQ42@p7Zv(G$Tfh9Ykyw6+%!0&bsJRlw|_V%c^TWx_b=J?GEL0iz0 zsZUWpq4(Ndt-_@(guy%<^{`+0N&|KuWXfc^1?ugQF2^|7E~tPLs%>Rn(e%fdQWTnM z3O9zqMRG0n*;Wc>Rz6WOOl5i$(lp651R7IZB)RbwGR6O*cISOasssrKsgj+89%dDh zjlQv)RPoWTWw`s+wWqEt^}?nE&`zMe;3kB(h}QWA&B1XOFOc>fQ6~4oLQo!LOKT~E zvf(wHzQF(E2669-b`pMPtoQ#Vgy#RK9{#r>tNXv#;7I=(>6DO&GGREg;1bxBcc6(u zmZrFjBr%OTrQywK=?aYf#fS!nXr9LZ3_1tOqz#xPE_l>>s=l_}OhB#SMq#OxQhia%Ct%M@3ocUz%gsgC?IshBffnj-P}2@8FdZ=TMU0t7(|Cg`?l(@#SUqH)_SXf5b-^}^FS3~+*4(>g430E97MI`nf9s^|pU z7K)l9F2iokT!f$CJcnQqrYd9VwQ+|$w2a^ke^ay0qbZ zR3kJS4V1(@P{Y)lu=#t2>M%W>y88Qm9uJ|ehIv4=BY@SP$A4a=0MFgeH*L)2L{SHq zOpuk#g!GplgS8!&1+YHms}KJSo=4}zAFgD@`TG-jj3qPVBC_iO3FIL12VW$7Ztiqr zxR0OjvvJIq`pwVQ8AkU#*>$8KE%xCfSC=sGPs_XX8t++m4Z_iarz=l6`S-1KvxJN{ zA^6IwzxW6i*o$OTh3$ipt%L~cbQw->o8)noLqPkwZC2iOkz7AF0YL_#skf*Aw`8Fj?ytTEHIDkIu`54&eOC~%qkBGWZR4SQ6U8+CMji_459Y)MwJr?}TI`+e zCx>2r{tBfzB8)fd=0AiZ;T(c&-E+0i5@p~~`A964t;tYT(XsE#{NHh<0C z%^H7p-WmRq^PTzRj>%~Qm%GpG!HO8{f{JZn3-rDWWZ=XH30>l+qBwFQCP&`6^8t3h zV|?Wi6}&Tg_J)(K$URw_H*s>(s7Ceq=bOV%c z79*7{$X=vzc8a!P?g2}^;oW4;TcGIa_q8F2wd6BEHxFM>C^Xt6nl^`1D7LihGlIH- zsI~0V&wQ=wCH!Q0%_UYfZB|wK%Hy&-a9Y`bR$xf- zv?hRG1Rz`>Z;?T)RiX~6Z{&)WuGS{_#bLfo{OPtIL+A_eA8{^l3`xQLP21x_{jY}A z|C0uo;r}(jzYNE38-#}6Sykj3*19|?OdPDn%$JOxN+@m(4jb?Z6n4hgQM|^+g|UxzICIgwcU6<=Q0AvYcqa8IV1Qb>>WGQ7CiT0xYVi6JfyZkRK%3`LiM*WK|d_H zt3%9hzYQF4^ywlf94NuVc|wSHim1SCaOlsDQJBedem?|pvg55URunJ2Pu(=rxOM52OKf51Ear&=lzFj4L3S1TqVjn8(-21>n5P?Et5jU*wl3ty^n97ZRoY!vT`g@yL& zlk*BjV7P~`k-G*OAdW5RS_2%g#f=lwk4DdHXAoX)FCA4_d}Z-? z9u@0R3>|MxDB}2D8$$1zj;nIV-bHz2pjz)Ox8uh(5?eAFJgzugJe&j#RQ@)0ldhhT zQJjUHX>U0MUa)?`7#NbKqJu&-&V1WJ_CIwRe%PK!SX;VHfBoFl|Hl9nN_y4H^5{Qq zcjhftTH*zuMs=yeGKn-o%gzM`#B6Qh%g%sR8Nv5^O+TP6VVqRMBcw>qP3@cR_73H1bUffIV)5MyX(W}L z=nVMFiJp4PrmmK}4TdFsSHuGI)=THh-Bp<6i(7=iEo$rFEzuSZ*Y`njAJt=>MaCzx zet@M)wC(d;Fd~TvgAmCW=u`j`96yT$PH#5Os8>JiitHo12`)aUiCdkf2 z9^x8$Dn5FiElm`i!-Z(8+?V}fr@+e>;Rfp+@jvRZ2J&Rx|7&$8eo?Uh|E$j#|C@TK zXeweU!+p;*(5)LIuxJSlN#f;A{z?C%L#IVxg=e*;9d}H?KRkG)pH9cw$jsQ;m-$1Y z+%pV-&@4f%cpS*vk7`?7e9T)%)jWGu!q*pJ?8fF~o9p=QF^rEp~ut2Otmcm1^M>coHp)Z*@PH}&Gn6V=x= zM5`4>fu$IK8oosuZ2dQg3$zVD%W+m}??NNYp7S-2f%-fEqk}|BS)RlllL=}e7z67Y# z;^8Lg-J>4C{g`5?(mY;|t}`o0)uX3^%d4x45W~%agk1gfffwV91p)_0lwD++ZcSE- z>}Wd};dBKQ3vq=z_1KN9+DR~=3!M*24CvB6E1E@8kX!e6}!nye@Jsj(e zNW!c-3U>s9(~JUA!dTo;*)?OCINj}dE}sdMC|ME{h&iID?Lfi%4xjdSFI41b#%>=~ zZAeds$lm6$1-Kmnl%{b%Sgb8Ux8-dSe?vw9b`io8PC0|!_mRUBlwwy9|B;k~RVK=t zp(QkXrCZ24v)fCcRN&TDxIqsp?>g4p1^J$J{tL2oz{-EnQKS!$?@-n^B6g+yBk=Oe zNnoOlSu(`3C2Ny8`Wy|30GCoIM3!9Q7+fxmfhvqoOvy1DFZBzU0l=nrKg)W@o&FDVy8E*VHL>a7wm08&CmX+k;M;Kcn|j$S6}Aj zD_Im1n*)*n45mL6u)7%o_6zk_>H~Jh+UwjpESeE7LB9_H!gmyNg8K{P#Fc87@F^!e z&L zMqPM%n`v6K|8={Ai22wL)aEXwxZ6ydI;H#XCV`T_nuzNhjJj5{#au{QgPZRBUK?3= zxk2D6D4Kx(k><)i{D^syni(5R?OcR5GrSYy#O+vlxVZrB)rjyWUrHiXn_Eowits_Ki2MD>uClJ z&~NJ3HCk@?-$vs2Y&r(hB10d;&v?h)M#LQyn<&?@huA)nj-1k6um-59nTn|Zh!*wR zZTQ6~T0FJ*Gci~=jr8F~K_R%U_QCBKiXAPN=ubWiS1)cL?NjVN0Tnw6kD2Uko#NYq zlMjUb*HAT17q_cMR#i$L^2ots(B>*IPG|QQ_57@-&4L6)ZJ$$Y5yCbVG=4BBMzZLh zmjp^nBu9)Hs6T5=Gt{z0i|t}T-pI{OVHyF@B?Shpj42sPY9As{M?I%@8HG9|-O%~O zy0z9>QV8BQY^;ij-TX=!dtr0iLHvjbqRm1NV^z#5RB|TIn##xyF!$^&E&me)*=SF3 zt7suSNET<N4KIH30m7oa^e7ebsXt!jG~L=wGA`lQ3|8r` zN65q*BjD-XU%?U_Cjm{WcKhLP=@3c_LctCh0=so^^Y{08y_H@qokmPZ$EAnC$e!z8 zGAgUbm);&u3OWtK??}Z1C%@-B{QJx)UzItEz4g36&EKPc)J}UHnXtWZpD3o{<5Q_B zQ(`JZAgXZT2nS@mJjDkXu_+_QYrznNKPF89aRZ7OHC}Z5X&}642&2|Ue&QCNV+?A| z(@zs2ZV+!M93J;JiY)eyLMnYZe-`a}O!|bnUG$BhTFYgtd?Cs6O%%?6K`RO+KY#D< zDcqx2ld^|h=k|K5d(re2GC3lRvUH0Xm{^LujnDA7w>)>{u!1e*)oW-1eMGPEeNG}U z4jW+;MjtI+v!D-Z1QPHDVay1jZ$Q*Q5Vro)%7oo&_RWA$Yv!&1x=1g$o zohuU^5}!8s$D50c_%X;k294|r)hu6xMLWwYCf&5{|KjbPf-B*>b>HsTHaoVRj&0kv z?Q}F_+qP}nwr!_l?7ZK%)~>zlRIPJy)>*llRk@l~|9a+cjAxATIEHvkd#2>-=kXViPL|uKk;*CjQ5Gise6b<3F4O(i&K5 zB%mOH$~zO-pKXPWXycMWC=ym;u{VT~GRJkTfkBftCa%ak>D~RjGt2*9pOAee+)-GbtI z+jDrgHV^^Td9k||dNglEg|>;-{cO0JvYbt-v{1>pv)inlz3C{Dum1k2dM71zmUiRz zLFzT}8!Kq#<)z>#y07dg=DG2ccSf_L&{T=0dK3UOa|Y{qw$^L8KZ@r46lcD=st%8V zRCgYu&X4d;{k7KelOr`!`frR3=7=vO;rI~AHf9+KQ$?6vp}J~-;(M`7s-avKfL$DY z$efG|mg_6h=j(o$!0GXQC$&9{qC3`wB1I1}cIDPaHNZn@SVT%@&uas{>B0HWVX z{%%dyJ)o_F(q+dj;ExR;e}RF$-ME-Z3-bX)hL`pHIePa>bZngsqUzSi`?x9pgv$}72h*&)(e~%T0>R=L!ZoC&(hvq%j--9~iSBMri0Nt%8Fhbw z`fFvz4qoXtS0PmluUgpK07q&;6L2QYSWf{v-!h#;if+P~+REJD$t0PPJfV?_9&~)` zfAes_T6|aJQl!AvELC<5VNaj0k0xGr&-KI+K$x1^FNk^%gM4g;2Me8(JA3pEM@XlG z7QbMg{(+;iOtL_mrQ$Iny?`u*SfyGqT#tyAv8MA2<+n)0gXHNyT1)8t$5>mUbb^XY z6zzZ%wg5D4{!iE!0zqQQ3CHe>xyMW2{p$;Pp49YA(mTy#t9}Qrd0Hj#KLEO#-Wgd6 z>;yXHMnmO+GY1dhi*e5qLrdxLoy^D;-%P{e_JfP3U)dGc3W3NJ9PJG#t@iO~Ph9+p zWtBE@^jc#O)4FzC_?;joAu7Oqvn3e`e9WZBM!(D@z~W4ZKa2$%G!TRQS?6qGt$wY> zWAF%2GdKiB4Kxxtk+$`Vw#2!GW*s+-+eKzY66cz^ML#srFI4A;%s5XrXqYjGn@nC- zJF!bSxIUXcbc<|@?8V@ysvh4^!HB&e35HM4I6J(dilCU2a=V12W2a_Yq;255z~Kki z@Vq`^Vu@~l@)c2S8#o*wWOwxh{5^L13!@UMHsgULMiTPIN$|4}R-Xi*Q-}*J0e(f9 znIhj7Lz1f4R-6B@!^F8BebaMoraJpXMuM!;tHhPZmI#0@J>4EDp6K=?5X_m9n~J7z zOm)P!rXVH?-NnB>0Zo!2K)mGZ{O&hd!; z4+imZN^mQDV-WHG7zVNaTh2Pa%fodQgwH4#@+M(Bvl9|?Gcj{041{C>$QU_#wr18A zjFF(GhhO*+Na}ZDb-lJ9h~B4kBaWPWbnwnqw7n>4~j(&(XHAClVb5(79|Om+fAfs*}Olh9B~j$I_d!j=NS4 z6DRBb(KD*Hr;&g3?7G5kyoi8PRGFE60Pl{G%-2OnckBCTzpgNH|018}owVdO?JB^Q zvnk8Ys#*zwRxrNX&?6HVMY2q$SBhSX+OfRe>^979c`2?QMg5E%qBNI#(jnSBy=&Av z7^pRqF~k3J&U$tgwQA&4czLz_Qu;v&;;7T(Cdk=GST4DO{QYQC#>V~fTZg|tsva%O;291dmi2ak+@n*PyD0x_X zgNT#NeI8ReRue*u;R2|$@leNy2$A?W&eu3HtGSVc`9(gAqPA}j6q{)ip4gXnjy@7X zut9`+bzdQShMo#?SuMw=kuYUAFD!_Yo~l1mwC{A z>UC4NrI2pS&n*94Rj-+;Il&uyGES=&J@c+PZ-;8Ds9h&B$}-S_8PR5Fbd?N%+5IjQ z-JOxVyw}vvY_Hl!zw}wR2`jdHJ`%=P7&loAGul^LV zb8!vB(rO#`fyH~004Hr|fu3x6B!Sxl41<;$VlLm=TQ4oL3&96wLX_}POT>`IF-e9P zCz3f|DFTl)dqgM=vqi}|zk|c9=br}Lo#1Adr@wQuw|D=N6_~n(Z%Gs9KJ0}x!18}k z0_brO3WLRq7BfC%unX%ipB;tv-dY~1iaZ_>*N5Aml6^`m#Tq{U*nrCB7Qbb2izsf_ zXM1KFrtoNeq6KumVQ>sownxtr&=jbo#k5nL#$}~mGq{GxX3dmZhva9=TnzL5O8m9q zBY`^hBX100EkU2t3L;<(LL@0?!SG$T+(_0-vW3&fzsoK;cvWzW3Za0nr`#|LTGMcedHt{!|m4W-aI}Y_S8Eq7A1-*lUwLiUe*k>)uQxYE!&z6*0OYRO!-@!=MlV3l>#vh zT-`Fi;jTcIcJm*&3)(fyseCCaq+7Q77u<0)sg^?|=MK`P>ughmk<`of!Z6`fIF?si z+_LOWO%%{68l_JDDgaom6-NH27^W~}gnjl|f8PYFB0p1JZf!5ZjF_rU0FmeLw+z5)CLd_0 zCiq*&5MuDKC@R7{T&uEb*{J!ZBGjkWMRl?ifH&#?ybdHHUw{WF=@2 z*awa-fE@c?-07fE>q$b@Aq{)Z2mpY22)0N^~#cbcRgXn*tyeQ zq>ZIAJ8b9J{Yn9mr_Np)y@xxX+%azFTrGOgT1)69EBGCm6c43~=>83K*+@ExYjJbu zVYXyCUjmF_IxrGCFbqz^=yB`PbCGE$STf=@a7rQONfB?{u-E&*05kDt^-?MHP|Mp) zgva8-7g5GKrgSt-Sv4^cJGj8VFWx`$LK^|lEn~)l1H|Hn8U?g)(8Ws zL6S5)y3Uyxp|G_=jeIcnc9zB=9GtChWGIbm)t;q~Dj#TE7*L~iCF!^GSuQ$Ou3vpd z-F5FE=Hga9TDS?MW$A9UQWzF3F*1i;w#($~9`T;a84)mHC?y=G?+CWfBZ$Uk7Uj~9 z7ct1R2I-^6`g$UuBYv|L$3kV6A{v`ny5JE1L%z#Yt`EnC=`j+|ZxhlGrHsy`n0gA> zZP}LrOEkK1iQdni8prK-UB1?Y%t)HA>)cTcMx^jpFE#M1%1?GJdk!4BI=cEkwpqan zMs?rZI0W4^A!5$w2rGIE=B&_L+6us63sCO}8Yepx0f_ZduXZq$b-n*)yz(K?eZ~ho zL2M@Bs{R9)0+sfOX5{@wVjWsbM^Pr`@s>!PG@w)0wtmKc8<LTo;XPv3BIYl;bo?}cn&`@g!wAadqJ@<=gO?ncnW=ot_+I$D|~vMy{o^^g#m<=P`Kxl+vG zpyrp00V?F9zPhP#~Yk&9Ucd306DcLXrgN#}N_J#dcI2#3+*5ryHra`Y9Vj zWmAB9bM`-e_N-$Z56zpYQ?|1s;6{eNq+ zDz-3+j|s3j>iYCq}3>v@_uZB#ZjR&OU5lMMoFE0==KHKR5d`#q!3(}X?HgymeR zXL+mgBMF?7mpLwv6DKV#U4uxRo#->Y;iI>y)T=m{tAN-)IrNlRX zJ%Cvolk&%~l>q;HJb;)s)K^2i<&Zgx}70$QuH?8posoI3zSSy(4CrZE&23=Zu@kCop{o2e#b z8uOK$Hr&6BR$#j_{P4WB5U_slV@E@&0l2xT=%5b9{p?yEtT3pU$}8w8*&yngs}*8y zZg()}zG1@>8an9W%XaOJ1VP-R0Vca;JuEy~29likjrep)aU^d%f&5Tv5F7n_u_W@2pu>bc79@c8^GXBjg@ElWz@HAZ9%#yvp>QIhvxwCtdPV;j1Wx zk{K;x7I^NoX#P0EHMW)#(3C}Dv<57d2F@ihC~M^9QPRlA1EviAbhskq>JCm7`wpZV zXGPTZ3YB3(29d2((JR7LC)a)dpp4*BIFk2;|Boo@ZI3l`6>KsV$N ze+01y?CrZ&a_^tSd`fvpyrlvOtM!s|#9|>JdCw-?Y`@xPGW^LszF-59k1;UXveoi zK&C2=NyWA#X=V0pMKJoR6L=br8oWTp6EWcYIDFj!BhE{;1P-=KLE3GFo9&3b`!&&R z@QD4#(Jk>CRsR{*BXDG|B$}pg ziLy7)gQ=dy`5xB8N<7yBhUkwy=nm%MnDdmMEz#4%vB%n<%u)miQS_O@Vh_HD(LNX@ zWE0YuE)5T5TD=AAmK&0ME=97%KfgB*W-{G^53lbtF%7^Ww&C1Vf1FC|F?4o zzoD!7liTXk5mrFrC~D>H9~#qr=A2ePT(>yR(w#*w$%wUGYMr4&?r)=}LN8fs3qx7= z6Bl#2D-!+#zTY#%W;|-Y>d@_{@i(htkoTL2asQiDMUU>CHmRv@9z;;w+<&S@a+ejy z=4$(_?ehNu!i5vG5mXdXQX>*qT26HRA!w-sa#w&Zc0tN2bW#r)Dq!^HqB^mrPoVJj1HQ-Ai3Ppm%IhYU@pJD^Swl^X3l18ne=0 zoU~i2!K{t5-3=G64QD4^vMdp-I%g8TLNvPF;Fox;*D&|pp}W$Q$MlEZVRhAEE5iI{ z#D?Cb*|q1Sw3Q`VBO#~sD$s*+P!ll`b0^fhjFnBubT0a6r~`etXVvLjZ3CEe8}>W0 z|4200^h^fnH@6c0m)!dQHPrL}+%Nf8SdNj1t%I?-sm(wC__t(N#!1V5hk63Gx3n=a zz<;XC^DCj)yE1==dOq9h!L~q{)$tjy$84n&XhKr;Z%jQS7i6w?AoSq0o z$%+=#tF_uE_{xz+d*FB)iBcB*jfwzIurf_jvXJN%6x93FiXy(3#_GJxR=fbg63#_Z zd8910lModZ-Bg`c6EBDdYK*7(>6=1Qu$^+z2N6>Br`Y&PhYBo2+pqL^jQmMKuk

S4HpuZ|_ZeT!@Ka%N{RV06MNhL2v{$RTCrru8qPUNlH#6FG! z{8X{m)FYs+AlZjojCo94qO5LdC)v08GY$cA^q7zvV6Z~wN&c3W(j;pWLvme^DCl6+ zI(ls!6lt!h{A$a?LqP@&qHQ?h;&z8JG z{dGXO-l=r#LcZ`OD`VBrGwvqp@Y7O6P*i# zE<2r_m9we24V~%tkw8~{cU>1_D_cWzCwDr>@0a9A_y2roa#s58#t#3-JNwR6{Eq$f zMhSUUS8jyZjr+T8iDZ{-c}2XGAbrG^=TMQrOLWqT9+A}5#6Z{dG~I4 zT)Jhe>VrjMjoE`&RaqI?~rwQ3`${tgzx$;a+&b&hDH7>c7Bo8mdpUho53&?A! zcVRP}n?%&^U3Z0t`S}Nxf1a?NP8&ndr>F$jX&70>MREdbYRVliw-H`7i#?ZnM;~ir z;6b;A|13gCsu6)`t`FlP*a)}y1+|?CL)5CNen8+lL6*O99tSvZn!Kq;!j4Pw)bY~Q z2^udZaBGU5M1{>2z00uO`v!KGZ1ac2ahd*R9^-H!V1>N?im$J`YHJQ01a|op+~vv& ziR0s8=BrL3SFT1|F^VNqw?bqhY^b4b)*ij|;C%K=?5*dpfy#0e=a$-eFyzVlh#4aPqM$C zio<{TR80OGpNgEZjgh&H>3`(I%II4gOWE35I@|qQng&(YWpR`-zA`tBi+dWZD8y=W z3JXzOC@jw_p(=$fphpxg91zQr^dD=az7Z%@os#Eer(X6Gm}l2Az6w>kp*Hl}(jIy% z3>8793za3+@HHi<;R`2K@=ke~ddjrzdV9%yIhl6d0=5I9vw(n<;$#$C8GB|>8jyzpG1)!To7NI zaS?MYquGSRe01>VeCo&%ix8+*a;Sr!O@`Io<}8jG7*^iTTiBeZ=HkF$Js5~@WXEINR+sU}ERobI$pn+3!wK8Mxe08SSJ zRT4ZE9z4XA#?KO}#C=YK6>Y!a*}_~$+>%1{cfP4pA?2t88>VabImm@rG4&?vm%)a& z#7ITX#~hK$tOfaSPZSIFD4dCDX>r??lsfm2Jg6WPpeuS+Sx0J;08BO}BR8RbJ`ZM0 z7AeIeAivW~Tt8n{4D0+d)(_6Cp&!^6_g?7rXNr6LxX1KDJXFAo0bNa#+9g7mQ|IjA z54dduwHUoAU{lkp?M?;GT;cXxxUGln=9daxZ8}uRcoUNRn6J94#B{(yRY@+f)c{h-t+?B?4>vtX^0R9V2@rMMDlsNYl ziT2V)FxcGkh^RRDekc&u{<58KN9P~lTi01GA6ObtoG9JFT_Q;{X#I#e;zChqc9GNC z*AXNHz*pYhnr3Lheryg*Fbl#p%GqF6kUXrZely1AQ`Vn z8?OKzuW%HbJ(xzzak(dnh*RL=7p_4v73Psv!yU?tXmO$f^gc2rV#yO^_SO-Q5oT%v z)IR3~lB63ci13hzPAnwYNZXCJ)Mo_9GG?8@8@ICnx4_)08e;Gy`d+IwTWZ2JpZyQ2 z3Mo{$9R$+ZApMBhO^l&%W~B+5sjeT}is#^GA0cQ}zi*JEc1?Y5q3>T&k6W{PY*X@% z_=Uds5)p{7qyaX!OOTcbSW=NA{G2bpVatIMAjOV0Dr=(5%LCI}Pzh4%XR7tJaiS-qykQR6Fh%<*8j-#Bia=K8w6o|5(5`atWU z@Twpnwi}G)pJV0W$f7VYQo!QS^e8el3OLxf9Vd$iZBMDsFq(omU@`o>%V^M^hdPS? ztT=ogW!^SFom4Nf!i<#}a&REZN^i8{U}bf48F4lZ2ZcrSdsa4_%E2Z}?x6QpPV)nl z^n8XjV5qq;YC28yIAj`SpFaCKTy;24>z_jS5 zH#tNhqHt5pba*tIRyNN6OJmpQO+OZ|04IOeb*m7S*VWK{re{pf*3PGY7g5rdbC?-ErazHaaCTa|i z`t)UzPRE5zG%c8(9MOR2$T6gQ97Gu6$Bi^YgJ^DyF3;@eWVV{O6VkK&8|q+UY|?XM zYQ_UV!%=Fp=CnX87X-@0;sj}`4igw=aGI@&-L1J)FSA1(acY(|-#KBaaL$jig&7sb zr#oMX!gY32esPo58$L6vQj$3fF*Jp-%@Y-TqGXqxe)F3+A5e_im#IJbM`7*%rLc(& z(^S}|P8T8p8l9Df@L7r>#vBeUDcMO|B@EX0KZH?%C@$7bXtNL8B*2(#Oa^WuI$#P! z-f@aHXm5broJOYmTts;>obE$rln zISR68NumZZNSW~rV!u-nO9fDS$jN!)rdb(~r3uFE~kF47-mX zlNGipvatM>{6De3DzQ+^Pv&`xyt_fw0b~y9weufOAI>o^&&V?L{ zqq98i|2RcI$S>#*jY3L8YQ8nds}B?m^)yTEh+IO7BDL8&sbyRfOvzyuKfOhgk@Lu7 zP#B_;*icjKI}iQsmLJ%Rw2S0nJCnzUzpagGtIL#+J+Y51;u9~Q05RGOk=i^P`TIl| z6SyTDM2s#-wp45k1BJb_2V?|?oCviK zc)=;*RtEw)M9K>f2|TTe_oZ>4fwN@J2{}K$G&mGOP}@KpE|Fo-iW8sa*V@a;C#*^l zUa%dA>P&#V)XXLbDHXHQC{1tIkEhbVxPS5T63=P9qLJMu=zR2ac=rgG6`wKZ7q}u$ z@JrAQr1D2+khj?MVFdz85jn)F-(~vCey{+2=dDsE7_L$7n%D%1St8@Y>um|R6b{HM zG)CzaA*D4g?3AaFYz`(uV#6(1Gk_&~1dV;J=>EgAl!=D6W8do9`CqE5(SJYBDjB;u zIXf5&*}B?T+3FkpN1?5(>4+kX^6BAPFUSh4F7|^+2nJ+B3P>{KmqZ930&f8GeOA$2oA2vW|qVTTvKlp0b2^BK#+i@1O2I%E4-~6eDC>_@X8c z+3fk^X^!pIhxgCvXkK7;7+pcBoeZk}3PYVU>I7&;s>wVe?{PM={tK()mw;8wVy%Wv zt67*s;rqK6^;5SbT%9Sf`6g^5$Ma<`vjooU51iXZqg2Df5Y(T|{b3Knd{{~Ui%whJoELdl_wx}VYhJW)2QAxn7qj%J zk0$DaOC-l%GD!Ocms8^-*{EUwMVFa2)f`{FM695y_{}lb=$^}oGIeb@2V+4lwS58# zp9B5%ke>UP<3cPvgc-f@e~8K+QVoU2qC6xA`7E3xL8Xin@pS* zv2!z|HSXq5ZS!?AreKOr2?Aj2i8jGeoF~pJ0i9TNK$hiuv$LVzPWoso9N0|2*}!6P|UQh`647iRqpuHrzN6oaMM)ybPyHgcoc}w^vR*9aveCWcM)^r)Ar2-k&2ev-^O5>)^yj|^s}s;(M7~y1SIA{Feoh*b^e^lr znl*_|I`x>cu{uQ6u}6`QP)(T4GX_pdGZq(BddauQjE2p6N;5VaLY|5SaP5W|g)QNG zAE-Dv&wPrLIB=Bqigo^iL)JJ|Im;ocH*>IS#__kl_=rEQk+(gCoP)@D^d|5b{iF4E z3@?Vsa9U+c-!K6;9PRJW83&O?#A#dNqCb}${@VX_v<`u(_YchFd*@I4g&U2pf;g!! zmvhXShFb3oS3P70&T{F95w**Slz%-muyk~N^|AV?31YP_-NDNGTpp`8@}wTO#F0T% z7S+BSd(rYX4trFJw_b}3>O>SR--dnoD^jFY2_v%PI~>+I(nHq({mJtNwbpkMdmCZ9 znZ5r*-78w$;)?Iib^)59V%F#a&xNRp-;CS>2WhTPm$@QNj!3UQN_0^Qxd~{aFF!>h zY}N;S5Z_LpVNqP6QMM;kfNGPj89G{trCV=>iOZKNF8TxdA4%n`vV-mYmei^Lau`(l zzfV&CqZ8l->7}%|_{{Mnb4MDFjs)=&fC~bn4rBQzkOq<;NFNab0l_}5gBUnoDkJqr zFDQjZ3HBA5)(_NuS_puUk`i->bz)OXzV%`qFVG*~C!nz)0wt*;`O=0PU5vz?Lt{-^#<&30E60?u1(kTM23{J8 z#cdPXsVYZM7?xTrR4Ukbwza?I;*WF>s~(DJa*l!eo7c3h%=839G*2}y^JXc>=Z?@S znZtmwga{|t@lo6f*bzLGTi$>6vt_>?wNq{QxdUvohLsJU5$NFwNQX5~;aezy!?m(3 z1m~D#f0=PG)g4WYPKu6<&^@XYfFdfnFJtiJ6Hh81%9P)^FE14+WB7EJPuvtACbUyh z!OH4{%46Ckx54U?3b5H04r`mIoP2MS?m6U*+a`gc+$M}lL>$NZnJk`me4o_D z4Hlhw{kN*DN0dr~2GqADgmO-};;TsQ0+s-wouv0G;rl7@7hEtB|x zCe~f2v9Zc_hPFD6UA%uCW<`~piRIbpnqVy*J%+$|giNX$)qDqPD!zGg@017XX-8YWL?n^N7I7 zS{)dZ)~7=pBDho#1y>(4u0c*Xa8W-DEUhqxkI8(7_T?i&y7LHd9KI(Q*?LFtq< zjt^SW=Bt-j`JI6)A8h>TAFq`BUaP>0dpxP&R{H3cN#;0uN_3e(nGgQJx!}sOkfE0v zxd6}xpkt;eI8eSkRQUnny$|zIs28qyRhv*a?Og0`n#J7TPP@(H&L{d^+PQ*s_m>j5 z9_hBioDV^?SO{gark1itaq`wlsRoKBV@@aVz&JYqWvmJq=vlM{IcnwH0B}mNi?DKU z9;CORD=5RJ^?m!dM8?Sjh7L{`|K9H`#+YSwFt-BWvYu%J{9oa5E9!vFxwb`4EfB$H z>q@x(9Ro(lic*O9HTi}5($Re0esqoLdADn~k!@ zMe)*+ewKxiN$NEbwk`Etq-tVx_=+wNAVmzOV5hMfu#8PTdWFlXd$)Z zp}9X3Yr~KJ9LHS}$l`gOZ09_;?cvl`4k022OTHkpEG&)vi=9LfzdeKa=$NXbW z$^3?$BLX@RON5_>tF&M7hB;P8fU2KCsR=kMXcLPoIK~~%BCj9MElVpj+yC4>tZ&uC zOPK#Q_27lM^{MV+R}!}d{*2kp4=CAjKY}7g5>4G0_fe4B-7yG zSc|St5(|ee} zR!z6OU;O7uTH<_q$jZzPBUh6B)r=j8cYen@u-6nWUaiVEDrTWpsNCLhVmf4L!psdk z%HoDr;OTMA`I+QBjCiiv3m+8E{k@j~cPrqD!p3;h5wv5V2`@Ak;;zC2>r?PK5)416 zmSUx>-*(rP*^R__IFPp%x6rZYdN&&DJr|jE;3!s-83<*~3ubuK_a%abhcH`xVxd{b z3F*pswIU(=-=-$udnkn)e2$*l!T+0B977%N3g=zFh-Jb^Cy51 zomEcv><0BcvPDx_+6rTPYArL-+d$<@Fxa=RI|K-7>6pA~E{$~$`hrV|`5f$Jp_64RXQ`JZ~2kg;Sy-_C20a zM?yakRolr5M9mY0NzlWTlOE|3%K{g}@3Cu^0SfnkUh{6i7kQEC)Okcc+hYoZ)`y4u1ilzq1m@GC)+=@2OhR9tOGKpCANs7cFQk13`AU z5XLeWFWvU*tgQxk_c1{)Dh~UsWGD5vl&u}!HcP|>+%+aJz%SS%7&axVyJrK__2pv0 z@sIG}+mE@tL_RQZ!U>N3ctFZe2^^}hlpm}~$mHI=wr`0NPm$6^Spk6+CYhYwSxAf2-Zi6TC%+EcJ=HZ<}iK4@kWs~Rr(#gsor&AXgFA##$v@_DmluwoCSJ_=fYcf?MQOlHnr8^DqJfjMau zh-k_kZo;gnT(+Z6y-Gbvy&Ww8}Z94_(wQ$Zj<3j)F`+-{(NDI}F+q69FsFyw2Q+YxVcQ z{z;gVc8COmJKP&=G#}F*A_d2T>;M=czv7@H@tR0E7@P-NqG^h zo?yd*1zD%e5K|#9dFL^mz)?Jjx7>X`uCB33ep=zvrZB2J1_IN_*zq2=d$~Ssc_oeG z#jo}3$IsqvA8Ple){WGZMHz|7&wJR4g;~qc2yrN;=+JHnQT#YRNjS2ty4od>I!m{Q z81sqq4f7OcmGc(P5+P6{SIW^Srcg`gie6_^;@C+ah*057euMSPFu6R6-2qFdj--0Q z;_bNvR!qX6uNIx*bNc{Hq4c((m}IvqNV{^cU-1l93%6h$vjcpN6wdLHwCtuZgBBpr z@(9r!)T_7B&&aTBL|RLy0q1VW!E@YdKxLaGG^T|X^5paVgh?Tq&K;3KF3;+aG{bsW zTQX1^bw$wQ-dijkxB2#rr#INNy7sN+CxjfJ2cVQ^J*+{HgD;m8H6Y&;Sl-n9AL{-Z zxc)(5h_&A3QS1Ki`r{h_-Vpec=U>?Qy~PY7XtLxQ3Ie}*b^CE4RJB&_JIFVp;Lm69 z@gaFVboA^dTA(diyr`|9{jr?9GVqJOS;stl^eqB{bzF<=Sf7NMwV;l zrcy?!iUE!*qMhYkoh*uD$lT52-!FsXm;ub&vk6D|*xZrVE$DX9ZR$V0?C@PS^6ubMY~7J}X+rA{ z8A2>KG_rniuM5=bBq9kZUVJ+B4pbd#$e`ev*8ZL{cuJN*iM@q;NBJ6?yH!61kY=W@ znm_wyvY$f2y=VO0WA_HBw9$1%=Tt zQNBC`6=-Az#|)QM!9-!yW&Nz`E7`Hh8l&>CulW8FQ^EH68 zf(VNr2EyYhmJcHNupmsw;}BxqIw9YeY|&ELO#2$rg~FcLMm32BqGbUGa+_Y69KPRj zt*8ABN+F^I$%u{>88jL&sOXjk7y{YzA$hb&gLY}5aF5&Qu}tXPFSF_R0iz=h zx9sTA;k`&Z^;8trX!%YIY4b-}9lzHFFFp6D~?A2n}u6Gkpn#yM}Dk_jVD}fI~O8QFM+asS8y~`;)&d#7u{L+>(nWz!E3;*1~BDJoiJ+W_m zp<tl30%opI$mz&mqpaF4sRoI5VnE=FDSyGB#iNn{`hE)(tVWn*krz{k&%#vH zt>=?Pn*=#GE9SV3t#3EHzOjU!n%3fPRO(E3UY03H9ZV51UKmceHF*Hr3d+0=6<{gp zqz^J(YU1|s6Z{d)xQ$%(E$gQ(Py0Gfa`r1NI+b&+gqs><+4B&Cz?nKO2FNws8fYO0 zBN0vHZCr!SV25GHeFsm_a&`ER<SU=oGdsF zX}5v)%PjKa=mu#T!zYFK)3i5)m}%O%tlb&m9l~jCP@Cl=yT|%n)oE>>q$)azs<-xB zv^NN@3R6&62xT+jFLOw0?0OQ@j}92dRYo=aE8kVLjk)st-;S`K}* zxqjghL*A;Qzf>AF;)S|j-mu2Ec59>mUf?(E!R87Kmk<6;rF{hYlEjq8`o!2bVI-WKc-D4a|8$pJ$fx?3P8p8k=P%Sfz^Z_=>ZxU^TL zjbHPcs+E+g>83q_%@){Y2&N_YQlB)_}IJ;bw4)2P$ecza3y;9NuSfo72^}2SCbde7j^WS`+yCGKJRHO7Pvd{o0+At!S1oPKQzxoX#>QKYftMTGK@N_7)@1VDy0R<-9CW%5D`g5 zvjUy!2|?6HENo27J?uy8`*ZW)H@$clG}URR0A3;9e%dLQm=j?yi};(q!`#mljTZbm z-9H%x9wU_j>dtnn&^0ZET{VZ!>f`5kNz14-)wCWoMXLLt0fN-2q@y3lht zA$9+-(0~-r*L}xSIglcZGnvIQhHfJ3qevA!QqThz^#P3lsD6RNj0BbIVOA70m&IWj?*_1E&_2PORf}HI`Af*hN;~}JPb`9dd1&m6D6r=r zi!1V^yR%_-rb-Zpvlbm@@pl}fVHY0H*%4-@LPQa)yz`SUcz@OeOqrjak$FGs@Odo% z&=JcQm-9aef-g?wyRUg-ylo>kv1m)<(@{;>-TWGNBZPWd#*~){ex2ZN$;Zka!fb@^ zLR`-cV?a+y!KF!wZ~Xv?J&I7`)~sQJpU0Z@4P3;sB$VHCmY5weOf?c=-kYBaS>9Q# zd@cc1fmX2}Z{4%bwY*A5szYWbC18n(US_`q9SG&eHeo>^Y}&qk_@nphi2UYZ|nW7UR+7 z%bLabN4UkaK$2SSp<24Zw*5v%xkn1&-oz&09mUMn3LZGW8psZ;`rE=q)TH5rVgLMn>L5$^bn|wVYcEYY?vxmw7wY5?JMYvQ_^KAeRb}u)E-LCazdE zp_OZ>MRhvU4OVV6vQ}t`V=Cv=QiKL@z!oBp$EA}{NKs+sMk_+An@?(-YP7IB%xdO(B2^AgLU|_$c#PxSaeI$2)#zjK1Hy8l-;Emn_^?3P_`i)P)-=1x z^%~xwKS%7C-hc`sMW9F#r2z6#GJ*%yBx+DLp|(O~_n1JkdpDt2cQl`w{CU5_6v7O@ za|nkJvqR}H#?(@YM^#6aIQ+kJ9Bg94?Za0HnJ~vf9b)~T#!U}w&YCr^jLp`>y|BF= z5)k}YPXLGr(eg9kxG_R@Fhe~c7eMn2Xm|8*P_@`C^mt_uRsA4p(cJpTkN)kDJb|6N z92dZEHFWPdZ@ml`@Yx9OaZ(q&_6Qk$z2vuqX&(q-^1*ZK2skp+vne6*C)SLQgP3lR z_C&DN#4Sjodm4K)jSKrCI00ybOSL5bdfIW>n*w!--)Luq;Lng}@1VRh zne6k@gUjwP6ELW**tdlYN(LdDh6qjMbNLjd0ABVOGiZ`_aU@!f!V=kKLH-wO?-*oR z6m98N+O}=mwr$(CD^Y3Nwr$(4G)~%fr8@8J`yyVv7kz(p_m6#IpWl0}SaXgw$M|lU zm4Y9r*t7`Q_k^8b(8KB4(~$$o_JL?o6#&YSf@u*To*kYj8sT{+37nxL`zS#Mg+yNw zCHtVMQgBmdw4G)Qx>OKI-RYAg3nVNJ!t$bd*%AI7kQz&s%j0C6BItWhjnEw9Zm%R> zeD=vWci>(;_K6;Q3WuMbNxq2y{%$dLK+Qc{w_LAC)tgMWUT>JkxWcXc8`=(8-)LT= zLQ+6*@(q!GuuspsF)c}bl9>rp|)N=`yd@w$Lz}QC)6&oF|H0KYq8(cm#_vFK`-7@=E zSW^V71;qU-bM6yRI63qhk8(y}Lv;Zj^~{ikDt4yct^-xx-Y<4(Kn`M}$N<8Y;I6L>t;;qyJD6FgSG z?lG&Xp*(7aT^1^~)1#;2<->3>Em-Gd*r*9Lb(HGR7HEEmx}hx4 z-Hflw62Pb77(_k{KcwFs(P~YssUsq>I9!uN~QhkbXarN{U|$m<>%=0rLSk& z&rcRUkvo6s5P#_&Jc*Woh{e%CCS}Ww^KmSmPe|-U%=vGIQi<2u#U)HBZ)j2=!A@!9 z!IvO8y^*tInuq5hJ<`c37#3o!;%|pdhijJgK`qb zMSM`DrS)a$B2~3fy-or6(ts(>NiwHK6=Q##1TQwTQCNpy9#qypd|9xFfGpC>n0XY0 zr20Ov3Qy3+JCX5`I79L;@Y?>lg7BTGTbSE}w0iKqpsKr@`i$N#l;ob_!7d5p$Ts{Egf{He|Jck~~0G9C}xi zpvGnILs-2}$H?^%c~>0hdJfL)bz6m&)BDNE4+KK}i}XTkdP zk6%ba04xZnL?UGgFyaU>XMAKuhog?{hkJhz7$5Dcj_jdjlTgE#AqSJF$bEGhqNySW zu(eA&4M5}vJKQf5=f0^7=zf z$jANUBV~>tN zT^ehLv~@78I%7ZCivif4;E2dZM!4KmdI1%THMB3>SDKb)o~4=pUH)-Sl+Oa`=F$yYG}uxmuzQ_&{tIW**ZT%Pa#{Vk;bclgX;cjRyn~q zxGQe64d32b+xW>lTI7h;XQ*V4l&6kRO~4J>GdYE>t6EN&8#&_PoHRq4S(CsrClUU& zaH@RrD_`3n!uA#-C@eyFRB@z~Bh!Q0^8{-$HZ@s%2AUFw20(#jq2qt%{?31+ZQ zC>ySo)#*~B1!`_y=(7VWhXAo~RZx+yMFl(-w0^Nb)5fg;Xfyh`{gk3DyjJ94GB^_5 zkUCYnf3x&n;m&BcA~H^|G>LGHEVNFBsm$fNAl8UM zn<7t{*t4e{lx5nN3U={#q4V+5l5Ea;U>RLXdM(Irdt*fmN}smzXU4}ks4Tj5cfnZ+ zl#YB^Y9=r> z3?Uf@H>~g>90+wL93NaDM~A4g>r}$P0|UhJ)PJC$!VVFFj|XQMQOJCxwH<5o3(;1H z;isD@LT@GgL-)qIraJvpwPfOwv8Ib>#A9zHqqauR1=q@owwD90(~W6_XAz!|I{^Y| zQ_{e-ooaY-vUeh)n4~J{rb^$pV1{3vs$G^=0%r`HK*1c|J+7TTewW)KQRLL5VuPpx zO1dWPDRLqdUH~tvLFdYrg>nf;ERji(6j`aE124pNZH2gm^sG3F1DBS#3iR)Y#*^VP zXv_(QHUuL-ck=0$SftsA_c{OH>K!qz_>ob1c|HOM0InTOB0jD+s|IqX3eZKI5afn9 zv5y>@N{&xq0^>}$c4!!$ijhDLANb`=8J#dhn6%?k;omA7`iB`z+LStZLZ+W#$uJ5R z=w(u=UM4n_qTHY1iHne;|AHCBpNwUXj|+)EH3?9h9nH>#c3_77oSeZaDc`?$uZ&A% z0Z`2d<8mgSO=)sWnU=`Q4#qju?M^svQ_Ooe1-ed*y4C8ye3>9yBZRrD*NwcHG<${c z;=)gxx|8t&%T1&SN!EZ4bB(~%BK3HY4XALGG0dwI_t{WMdKk1&ZD_!FE;n#NA<$Fe#Hv4Azs*L zTnR0YXs{kSCM8X1DC*`ajnK6gbunq$6Jct4;~$|F9)F?oen103-xZ&iqssj=?|U?W z+JJvKTpT7^9VA+f+&M+i`U|%ad;ie-lxnqK z%$ZKMz=PbHa9kyR!bM^y6GiA{ej1LZ5jm}bhy%QX7+R?O*DKqR`a_C_9pVF0;`%Q# z9j25@gDpbn!E>0Ie}gNZX&Fyb+N%s47in#^21YA&mU=hL7kV`pGBe)B2ZgEs_>vnf z=VN^N=IhFWKqx_vU<4~z^+FFQ`zDWALod;WI#8$RDcW(>DK%HRIl9FMo@Q{^bx^zG zik&b9^h`-SDtZnu_RNA9hJ?UoTBwhr#r0(p2Hl#~SA`k8_+aC42onI19Y~`SIEK^% zSodS7`*uNOpmoUtL_BUNsz|yt4uMbi>T9yM?j2y)No_;$L2*+&dt6=^%P78TJ4Gvg zIKylUs(-Yv5Y^7?)$puz{>sLPDj$B@Kp%> z*Cgl^P@Kc?`55z>_308MH9PL9q!%`8H{X+r>`z^zRPw5QnumzQ;Q+xY#%-o{2Zf|} z*AE{#(joea7TTWdsU)I_LVP~_H~Js9ivZJZ#YhyKoAH5qcpOGn`(qNflS|Lq;Fa4x z{c~xn#KcSz$WNG7gwMgE`%jiilDU&kXzJjnrMlaG!FH5Wn>4GBp~m8(zGFg=$Q}~d zTi=3_rSyuN@28yoAIOdv=hgRuEZ<+=;}BAVtw|7DLg+>muqknZiN49ki+YSw{NP-T z==X;Qq;d+05WdjY$#eaD_gtQe*W?x6`1lF$<0LBsD$W8@D^a(RyuZQ@Wo~1AvHTej z2J?=pZgYI$NDhgXkFwU(*o`^7G^KWZ!@0nESQ|u9rr0h&`A#2sp_Zh8y~l=6nJ9jB zu`TFccITm7j%+66%VYM18F>N|XT28UXoRd$WmgKXOoK4XY`+50yMT z&yjN==->G>@jjw5<3VMJ2~+vO#`K1nvH2qTXP1IJK#=-_sNzNfRli%o`dw$_w`b}H z{-qZ-+g(U@ebs_eq|f}cNq%*7Y(`! z=H|9m_GYC2)2I9YHcn2-0}CNm1Eqvrz}#I81V{WHg}O7|KOh{nEVK-Y$3!q)vvV|D zC+lh|&pR4O_q+x9pfq8?K6vcP(7#+bw&!v+(vTXO5VvW{b?ne->509VFD zNx!NrF!rk>sngMGjOo`zwF*m^LPEv5n)LqMe-tz{&cDQGB6A8DEEBo1a-pqPe3k1F zpkmi7-{(mdLsmg&PDhtSkBouU+!*8}->0@9`qSJ$O*W?<^N$YNUTuo(SU17zHU|f- zoF5BXIM8+`4mfMpHJagb+m0hwxWDt37n-^jS_E1}6RG^GE{t~~E(-XJ`p@we0vx+% z5$U%c@SCSl?fsp1_Bw1U;nX;3-ZSS|cg7-4_2M%P22WkO4;Io1*Ks<$trM-I4$=~3 z18TffJ-sH%Rv)9c6_QML(-viYv|8A z*Yyork8y)tj(j>N#gNLxa4n0b%uGIW7wwuD%XK_L?vcBRH)R2Rpia+j@9jL9&Cfx_ z;=XuaYH}Tt;$jl)iy&>WC_Ne2&=8%H1P%;LGnkTroM(otyR&F)t;ovby36)GjF>lP&G=_o@@u zyseh4o}2b?cAdwb%g`U#JGFt4=sI>&$c-kry!7j&->eiWSr$Bz329uIrD|}9_gQOb zqBs=$GfjpWSkoiLgM-s%XOD9*R-I##G%-KZ&?`LJ)VPs96vtGv*!cbrTE2X0Qfo&B z_-~Ay2yh@i57|)p=mz9@!(=~qV9Jr1gdB%lx)H0P9UUmUsA8BTX4Y+XpaobaeoSST zp_%ex1c1a-Kc8GKX6&$;#<9HNj47I$e%IUJJNd|pEyu`q00z7j8dtNi5wg{Y=RnQ~ zH`%`(>GbOxiV|aof_Rj?8PgK|R68;kQhR|M5m!y`-&aBXG2M+S1xA!1mpWxFBj!8I zy3$!TqXf&LgdkW*|IX+R^Be@<*kp_ce=O;2UTFdM<=_}xx8x0-p$=$XKee&Ed9f5X z1J2|0A?T5}0|*{WV^rOOU|N4=+U$8Ocav83bVpnhG(y1k=_nwfm607Zy zWG?}!4hT6kGn!=5y)_ecadff0YOe;)u*o$lI2ZT4$3=H)BW`nbW-_H_>YFvGvrdU( z4nRpsQ8-<^Wi??Ica*aG_@>HYLIvike)e(3q4U;^@>o)X>1@=~D{{vDlCZ^+BBsP$ zBT#9Vi9&i@`k!JHp5haV>TXpniXfBI5}nbK69il~7pkL)icztK!(u$A)aEt^f0KOb9mg|!KRC1hSSS##rF&=aR9n9Pp% z6Em8+PM~GC)O8GHq{MtU2XbX-J@OKc;1*KA_@(`=Z>~>88DVNf%(qg3d*7RI8c_;H z%fG1{52>z@gpg(J#pf14K0m`SyYS*5muWk!Vr4j1lGvpxWqHMdv`o+yD$q$VqYQDU zVGDRs;+%E=W?VDQl9(6@=es}^#}LAp2c^_bD-}*(JQP4)`k;2<1OJotSUO|8cZAjT zgtnKnZ1QU9$iI8iauFui^pU)2cYUa?3U_xCqqpH+vNKc$Wc+b1l~1$c&3NV^GV3s2 zwKQX{?&eHQ#lLXG(tzzIuYX(6C?}pQ1Ir|kMT%)2GZ^*bxwzHx-RVC$jUE{#@x(JA zMAN%STuxEZrF&HdH5kRIwnBB0n=7SQVV~V4)K6CV)VOm4F*pEHjTOIz^G%v`p@sQt zL_27VhOiq8;CZEIpp}s4+FB3@Zb7TH_{cs}$MF{kA^?OHBTr@c*JSl8G}Q$i96Bk} zoR2%nsO^MJI;l~2W2oS2tS&?P7fO%hF|X6Nw$*~}!~#xU!8oQd+OMv~X7`wqFd}fC zO$IsAFtp^oViJ^!n-a``WWH{%=?|r!lcP1&u-376Z%AH)rAvq;%&(;I&yE)-jqUsg zpVe?3^}wquj0Fv+Kn8sao~K@;8o%m*HwotK@uhN39CS#v^lz>_f=n`kWH^@F&w|n# z%fd-`Eitl-d2K7Ax(k>E+N$_KiJcP1>k?J1mTrF+rZH)0Svw~=CsOqKpLzQ!qs7qY zTCi!&P>g$^f?L0Kq#8_CBAV;oUI4vMxqf3kYq`!oX$Y$oeq;{3SWClO^7WS<>u4^0 z;A4k65P5@KWI31|$l3NrjN(}KjY0wQyw*zmzOi_-FWbOd8=nK_xl^iCKc{b06J%#M z82h&uoB5)~6CB4hZ*#5xXW%8rCR=4_9WHzI_fuz0W|<#`gaPTi-dg{p8wXjI65Etj z3wTH%-&Y!xErq^@VS z#qGapS#qsD?0SLICdX46Y_Twc<+FZM=u05CHn$5Rx)uXOtO|Z3XqYM!ya5Or=xQ`Q zr*(oj9tKwdI={IaPI+rlOJB4AWN}|*QP<8_u_gBiC2fT91Wh)(XS!EF;{{qO;-Gi? zP++GISb*+~#@__Zzf0eX?R<@@HPdJynYNcaq3>i4%vCy7;`;M@ z<&u!0(&^7%`QB$AokCi9rQW&8^B5Ho&mA*28mP~Qp8Ag*ulo8IEqtQ)(G*TKs(oLr z=Px{^Xgak(muW*$EuWJxAD`mZVRNi(1+a%3I+)R}`oGNTk_#V}LNTwr9Y$heZSu1YB; z4h8l0$iW`4YFRr|GF^WCKvgypkG|&H$HGA;N2g}p>8|I%h0;nnOh-2SGz`lR*O?Qy zwpTvox`${gM514W_)vnB)}tO1a9XnJB%)G@t%Etj0n#!plI2K~Z|xYk*^Oh)i4QnQ z`2J5WU3=77VdoD(xe4{ZtD*l7prKB-R<33YV*i;{BI<1AZszRrUuHW^C|_JPtnWTk zj;3|_INOMNF+-m}Tbql(W-8hn#SNR}R#w8o+Rd`=6cg-O8CRFK8-$TTh5JgVCD|?b zh)4+Va*N=Ug}D1bk@?|~`*ixA7=iZzKh#bRJL!Ng+eEL2o%bD&uf7|fr7;7Z*I&OM zz)(>kZ5ds8vX|W%Vl4K(HCMe8JJFh&?Rj|XUEd=esWZ-`F!%6hRy?eNHz6L2v1HbQ z_a0|W2UmtJaQ}hRFy-r5f#C;o@iYU)z{cd>me%5VPot+JdAx8`uP36XZyzd}UWzhr zRhOKDM(UvOg_>K?>KU4S*}I?D+qBe#EU28+O4cxJEUM-$FP@RBL|v$FQ#WR&pr!nk zG<<`)FXA(Li60tkV@{RD{NW%98hMFz{Vv;yzJNA|NtR{Stt;`FSdP=8R6_bqt=PQC zr4AdIr0S_ey1P?ch$*)C7*fz?`mf8iO724X+#j_tgg!|ES)17@@_lQ_j#lcbj@vFue8gG+IK7-i1T*pxQYNl@^iH3)|tnK3rcKv(+9;dohkV znTC^v;iEQ@np$zf&CfzyrnHDJ)avX>JF|eEFEj>C2Tc{Gd{%rAmV>-F&ALHUNYilp zJ5&v$7^BVNggSMfwlKEW(F3&b2ug zyPAyu{e2%Q12g1Fy<;KYIH#%LM!wkY_*Q3hI}ffCK`Ag+e^b7MWUs!YY`WyfUi903 zIa6I>&5MVI*1+QeT`1c|+*9l7zR4zSnSMgA8q2^n#&%fT%5;g<(=rX-PN@MZtHNaQ z@+={jHzGHgcxmGLh-Xl4);i~~MNEulBV2aVm8-p3;tsAJxV7rEe*{*rZ>4NCOI)^z z2icurcd^xc?TjiSG0&w#hNT`YjdE=iQbA36M5n|mH)O%?pB7YWRXZv+2r7$8u&aF* z6$q)LxR<_G)f9qp-$!g zU%DyR{=ZekM1E{phFVK0>`7QUyVdJGKEg)(2Y)BEPwvly ziA*e^vlA~GTJ@*4$S!ozb8wD=>7|0j#%;1N>>`dy|JZmZ8{zibgLT~-VX85OPc@EZ z#&WL=hok>i-U*~Z?M^bxR3$01uJFXzk&~R?Um0kwc{#a+0)2>2+|>R^kE>GchPW}~ zV0qM2f*@uBx0icsH4(d}ghyLyrPFHME!+Qm{guR=QedNwTg0EIIFf4ZuQ(ERYm~|X zg&+Zc@Cwf9KAyegqpC}@na+{Qy5#-)GlIVdK2P!13D|5B>MZ`EjC@V>q21`C-_!@X zpCrMpsej8PUv!`bxJ;qFLQBRyOT7=jtdD%Y43Gp|K;_+>?p~C^w9loQhmA3S8fl-o zX1L$7pXJekkr67ixgo2y+?9=w z&Qrk8w;j2Z!=Ym?-F6w0J9~BVR7-n4eSee3`1|SY;Q)|oT7x0~Z#0Zy{%HC|yNz<$ z-cnPCq3DGS%^)>i@pKM769v!{V$=ijGG5)Ik$?ZHet2@H!Bl9No|Z{9V7CH0Q{h>} z32@Js!U0uRpxGbJMifLEH67@6koNChIHL5BQU^e&f-*UPKko~n86;IwueUGG(Sw>I znL-zrt7x;QgsJfcNp#5J!8I91q5MFa+$ zY(;$I9%$!OMN6{z{I^2#%3mw0w^=fvYkn?NN`vv!U|%R-I|K*V^%0<1&~bvwHqX?* z)LBeMT-)5h?t6i(OI%Cmw3nKfT1!f{cnb*vqIPLsbNUM>>Pe%4niS^5$FBNgw5Qo? zgs{#8Ah+Ui&S+bv9DB@%lf1o^lB}N1l*i^ex`XY4D@?ZYTJie&&9#>( zc=QZV+1PC0YmNs*84E-h#RaHJ=ZGIUFGCYqLLP(TWl+_*>7r2!}!=ajVYc)mF#BILkv?_IndIYg3JYaP(X`fb7UQaF&>xGnY zX>GvMNd_A61`W=~2i=?&*C(|IEcwo6`3JIrKV)wX~uBh`0Dn6OjfW8Dn_$^<$j@Pd;bb!#bL#;n5f*LqF zyvbb*OR%gsA9?q5BkXa^Hckq=sLy=*Y$m4tqObq;Cv3?*| zbi&gLtdY&o`ssC8S3JS)-(+nW7C!LCVa5A{nE$wgbCDhi5*y21rJ>ikqGg9!LY9d2 zbIW*8nqr9~r&hgzJBM|}TeONvb7wV(i{vNew z8(3<%cp%J{Rjak5RXI`68@lL3g()daTu|{yPvB5>LG_8k=FP|QI4pv^~gM_9~jpZ18wgGCIl7}#^lfw zs)UANO7DvL$m^SAISggiXrl+zsOYAySVl@k%qAyCDIAuRq*Zn=`_*(5d za)oJ3?-zT6zyAskajMX9DrTUDUM&{LlLfi+N3H19cnndRB$sJxVS;c6Y}|0yuRQVh z$E4n0U2aHG-j{sV(}{h5hhdyY{>Y>%uYX_RtLxC-dYoWADQpmqDOy#^m4?&ZR{=6Y2k3ePo7TAyYk*HE> zufbwSH;B?fJBAB(*-n_FE?e;4_(C<)Z+UP9)mpQ@v(^6;VTJ%zR;6p_nVWzr^H4qw zzf=249t5{Xu+uX5FUcWr#}t$0mJgwoDzit5^n3rp0DOUD;dWpcuf6g;%`loAmbM3J zhMqM#rfx)k;bc#;=B&Fs1p!=}#L@R1AXB zsiyP~urQ2Qjd9VW^DpSWW6c>+&jir`*W3X2+yJ-S0GHfv$J}q{-0uSBMaKbDzZ5BC zU%da&A!SZwbY`J{{W|$?YiXVTZ5`6x!OG;Pl=gJAa{ftVQ!#TT{eRxY+|BG=|EsK4 zoRJ4+!puf6!axLN>kWkHUUOuj)`$Hf{UXcPP)?g`F}0Fv>l&=`x&`v3G+DR&;VyJd zub#PbXS~F%a{S`64WmT5X5&d1_wvY&(W;L|X-!B`kU!jB2uvr_s%{Q1Il$<^Jjza& z?D#Vt6RG)l!eW*Z3vub*_u@ah@rM#+10_S|rpCnSopWy-30oY4`z(1OBxm-o!OX%A zNCCTILn?ifEF|}kkx**NL4`+;`HStS$KoUvPb*acKVwGBt1OxR?iZ4Ez?u9hE&_sv z0Jm0&Z@)~7N9IJnV0hHk^d> zy*DPg7a2UI0Sg29u(Q*op-^adHQAHz%x#GnRHG--0Pl`ZjFIy zl|oYuA4Y+Wu7x(KQ|VbsNUHe@qIj90)P;IY;IWq#jDF(t(WBOozJ`V1r8{^mN)gmO zHXKHP_}FRZWmTfK{BEoc!zOyTq)7u;7LQ^Imq`u$p#aPrPC{u{c?E>YcXBlBLaLtf z#i@hZG};#3Uhp!<4Z$)&J1jKvSpY3fU-e25J0I@V#t52N1h#9z4-R5F5rdq6lq*mK zy^7p#6~&UOsi%WXK@?G?PH_HhqbXbEi21e(RRP-?2R##iu36pnr` zGH?nw#^*Ehbd2H>Nuq}N`q=KW|NZI@S;{j?ryDXkIMXoaQtg4vRKW$wLQkdML#MEY zT(n^_Kua%*<^Ajm4GR;coW|hKdEAKkii*94tKXU3<7%w&BsR6AQ)a)J9}ketH=NGLJ>?( zZXz7`f<^MnLW(&-unw^y@8B@+xGtT@l+h1Nfi0TsO z>!z$Z<`03K!*wiip>tRdC_m{9OtfiUejYQv;KY50nn74uxW|?-!K+)qMyXqPj%))a zxZe~8b;Jo9P}wk@bu)AK=}u&(A7C9lY;f4-gW1 ze6vjb_{S&~mnTl>J=G!vyW?Qf2gEpU%*^eB^ygz3%kR)o(~FHzdjbo_0OeP_P}u3e z-$;&Q7>d;AzVT0b<~3eCNIt<~4cBhI{L5dsGu$2a=3nRv?D4hzy6;oUwlP33Lm&EP zI??fE3%{D6_wl%g*<;r8dwo}Q@SLNn#H}~QJBt#|fs5g2L!SpE?|I~-FAlFq;l(d} zFlET#ecGXG-Li1$n}#pOubRd55QQSq(oG>0l(;n`Z(vsuSI6CbK^SD*e@2~F&v)!k z8M6tEJ*tXn4h3mo#AyI`3WEIe`)~i5T;CcY(?9%^FY@-^=8OEFo^tB{an`ArIsfQI zQg)8Er2qL}(a6gAzfL)2IRz9YRK7X`k*L)GLpNXa0>Aej3N z{wV-s@KOe~&i9{dH=|A_Bw1Zd5ArW^lkOX(2-P(D%fO+Ym>W-0)-zT5m}{{ujmjN5*Uj`y zkG8kRqtzN1unWQsgNR9D$grKUoXAwTLV2P3p(J5Uu8)LNC(higq?q0(b{e#yI%<0Y z`)XmoQ1-pXbI6Abje4_mJK9r)QO8_i_c#|U!wpyV7Hgoz!d(O$FbP)$aH4OIocaZ~cp(vT`y4)R;jH>5r`nu?ArI{^UqYY)T8Ybfp zuV;H=e}DBMM%tLBJjN5XT>kNwn_f?x5nN3qKlCs)A94FrHymCHp0qa*&w0ddUP5x8hUk^g}v4q(7sh@DSq?$J-znK~)3GG)#Vvj+4A05}}egQ_Gr_obY`8DZ2b!n?xWM}%*OU;B|&JLDOInkrR?5 zJK$RIc$!TjO?p*KsWKOrX+01`KGWr>*cKUz^l{~?JbAHc2qrj3l4Efx7Pi5hZ@vC! zK(7InrclbyJ+#Kp4*6df7fSz!HQ@hecl^&i(WB|*s`?k}d)w4ppV^Cu)+pmQF?2dy z*%~!x0TLt{JDV^ec}%WIe~?hN*N=P{rtct6clZt-Yt|e+a`$aJ z(e7DF0UD&`14N8(&_$d1!-`>Ttyj=ZeDr|G3OeAZs*NGN9|N41h(3w27s-7!9zO+WC&?7PNO&3?zd2stz6z zNp5&1a9WJM9{YYv!$M!Bt#FTR&c;vyVom)Zk%P}Xvxt+!A3hWC%c-eJFRj`|^Bym= z!RV2S*}r3*x29YA9c0F0HHs2FSOgU9x)lelIVPGWdP5|-*SLI5m&MIkAVF_(6;&zZ zELql{Xel*lEo^KlXmB+b8my}7Z&jagz=H~H3uz7QNRb>^10fkwy2nWLQ`PZk3>chk zw*jM5BQ#N&ptxvzzt6Eew5tK zSlxEEX@a)AS?2>-pYIIrdqypOv@^#+vOH;5%kf0|HeqwQ!m63*pFmt8Vn^o|tQ%N} z^XT#gvr#nD2c8&3!t@YFwf3SR*jEwYDT>yAo(r1G$uT3Z-JwljE56iDNBIXZoDzan znoU7Y)yTJaB+Po|wC1kqOb%c%uo*%DzdN;Y=%`Oek+aK;Dg@W1)+&Y|25qFLVV%S` zl-ndgu{s_v4VL8BRP5T508d@7ItcAFu zprdiC7bIF?v2_h@o14f^=BjhLSA|@kJ;$^@kOhL-t=ODK6rYOa+ixu-g+$}{S1;A8 z8!lQ7a91kIh25HyNKVTu?C=KdPDQdG=A&a+mzxO374qR-9G&4-B63tK+UBg2w6ULB zg4)eo#@qHf5+@v#vFeh}zh)q&;LNNMX6zdWvW#}Q>n1xpQfag4vQO$N2ggp8bZAkz zur)(fev{)fCr=IcON%I-JmI7aUszXC}hzMY)Gv zeW6yNr_Y$#V-!+J`@{CQaeLsz8okDA;#^3OD%Z4zo@B?2ELdH|hqCN8+@<^z*1em% zW%W-+XWG?<=qR>S$)>bQHViDprU|RUW9tCy>Zr$&J@w*L#Px5QtZ9?iDAm_RElQ2* zSWZQ>IBf^=a2}AV0hK{+zHlB5Mv6!ZovwUy>RNj0x}o{cqHycOx{oV5(_StifqRP_-I?fH4cnS|4Tym0c6dp+NimfD8;@mOf@tGuZe;xX2 z!F%6ThgxVJkJg>PqW8*)h#aGDWEpS*b&NmEU3dy5h?gN%?WzBz%kfU$GJc?(e>RZR zlB$c73FUo*_C(WPY=G&)iiP5k6@k;*;!-)b#Q=k4XhE2@gTV(8IF>5xJh=+9D zw{`gpf_rBeq2ha(yTl>+jzEKr4BqCB1W#aeb69G6!@4qZpzfE1Fq`Q0KS$yXdwoMG z_bCFEnz_XL*S{wxa0`+7NKq5R6Y{H$?pSP>F_m)bE@O;wdTAfojz*Q2GjFVF?#I@q zX>)&Z`7H!be6GV^qHujLBViN z%B_!(`BB~sO*WL_oHmUnlm)`nZ}8_hvE#{jgmZQK*vrg(DNo*V@xo7PH^J44LAZ~D z#hLtK!!qq&7M=KY&T`A0`kIY@Ld4dCF+)d&FCn1qOK-1r>I4T!gf0Fvog}7bdas@SIeXDanj2ykuNJ-p!QiIhnnHrPf;xfm zCL>jcmy5VExCU!WVw$obeM$30!e;hk*H}Uagigtc%$xeYWG^lEJdN5~Td>j+ql~13 zk7DttF|Eb{v~K0-)a`F<0@S4=O7jTdr`!TyCzb(NT~R8!kaO_$QsqT5&Ll6r>86tc zv?I`c=x5WvmIu~679h6!vcvTWe>;=FCI*AE*JBv<#X_k3$>3RPc28mvkjC;BVgig= zz#GI&4VxSbB-$I)4xO?`M}6392hu7=oDXpWB}8h#zYm3`=j%-oU07KWj1#~~ED&Wl zQDK$1!oUagGP5hd)UDdD4Vo#TETBqoP_yl21C^@Dv&n{UXx4+X-1n-I9{xGLxO1Xf zYFEC{Tp}7n%ZG?pz?A`cBOFzXAmf0QMe7DA8Y1-WxfJh$-%<(~>Ge>?7x-%b(8LC* ziYUtRP}cY#l`5i5Dx!;mr3^y4)IL6}b)$IxdU9MV72(x6molB!@ajqscLbK%|6K6z zSLnQ=`O#3X&DV_D@%r%;c|-L0Q`DY#^1STGa4pVF8w^Tq~`zi^(?QGSR=igOm zw&uXU3&(p^T|{2ic#>&Q9Ld}DJ%t92=GvJXA;}rQ7TBA!6)Mm z3nq3awU%aRm-}jQ{$5R|p4Hc-*)CKrSwBHGHCm;=Y|7x*;3v4X>Pauiz0_*kAUgX; zs6IIa0jA0~zxa`NL`3Gp8!IwyJ{yp?Gb3G=Z>kbEs+AHqYs#-r@>2YH4Rxt7q1# zgqc@xF>mrqG7&h~&U^L=fB0!s-ygQ#fbnjLE!^vGuTA;;hWWbclczO9`MJvp*j(33 zk`ep$8;@yBr!=sVR?`RG(_88e=r1Wucl$|97bv*+MX-3N-p$x0-tST)ci$WljM-JCbxWkdbCqJQFGkS}xm@@`8G&51}cjFS(Jn-qvNk~fLipA8j;Y&Cf z)W&QFePnJy3f)Q3R-%oBLp_AJyJdW1k+FciJ!afT*&}X|gggzFVMT@(qN+@tWQB*Q zeCgv{Kv}bqvFV}UP9QDE@wQI6!=1f2p<;?_$)L$=S!Gc}%xSqpXd@D_<5E|~6P8aq zjWSc&OheO!%VtoM4k=5+tUDdoPYW2!hF9G{zGguVGb!v_z5>g#{Td60r~%1{lHJt z{9g^ShLsPF2AY3eTf@ixcwFThH^ zv!eZAPRE6cg1!dniI0}W#TT<2d5za(ZhdQ3M!Sr{!gLFR(fhs2q@foma5m7>dWG6H zL0&HfE2I9h*`$P}!scP6dfNP|cv`z>sr5vPBQrktMwW|tiA*t#EP5Jt!zxe?1e^SX zr&cU*5uQhC?%4&4Dqg>akGuYIsXouC+jO-bBtpx)u*s_Jf^!cCMSdmMwPXcu{cb8T zP($_+av49SEB54d42*h+js#e(rvkLY8j;gK%@%gN7%z`uuNWNx%J%fa{}?O=`;60* zGh}AX*qDZ&OwolEp^HpcT5w7d4>VIwwMcy7%#%4aDtEooO&8tpXabZIpPv1gV4-~%1A$61|MiI*~ArPcM7KCg@6m%yO+OFe1TI`Y_qYYgYZ=qdS<$V%xBATjRS<5& zA&tPBtS`NQ!v5J{G20ud$>IOQn|nCv8oL`d6{14kuber2Fd4&UP0s-R?Zza$;sqm?AqV znk*!s#(zp^XnzcbGP$obu@u81BV$UuRwjd&#b)(6o1G$@J^L1!$B^|JX}yriwK+3U zZTwk9u0QxQ6N+-G9R?v&E~K8?46Lz&vCg+DtO&KsdPnD*g(Y1H@6)V{mKKRhu*-HQ zri-wL=DRzLa4XVkq3-=CuJ&N)xQEDjC&kt|Di$*`Sy%zZdt%g*$N?Ym%Ix+ItTu7y zW6w`FH%T*1Xo3S>hlzhOC!vs9c6m)BHS&dm;;>(qJy`5uHR8B)aGH5C4jnFaRFg)@ zP41nB9)Fwnvz!<_0etarYQOc%ua93 zMfR<5G~bQ5ss%<24lXGl5~>mAZUo0VMV-FN+G8)!A+K2)e7&nGoj^Dh>%#``Eok+7 z?Cf!D>^s6syA4<5V8EMidP5ZTal1MV!JCvxJjpBfZ{8Plm$p4I+a_(dXD{__Ey~?- zVY?zSo4^~(7D#x&-@{2!oXUX#2Wy6EJQ%|}V-aAFZt83rbo*Lg1(h9vxyPAe!=M;B z7uEK)`k-NEWdnSpSutR`x}t?ae|wvr2-d2=+L%~YY(?z{^h7I>izay~ZjU7hww4#D zR|%FD@CDIscC!#i*_-o0YCMtcI0upfP?31Ug4+ji&Z|B?vFVPj8eq@}_E2F#1_iqU zO~7+G%2_;n0i61PMC(8X%Sg_!`(job-O0!f9@TnJB^rJ0#-9u4{U$lFmT(3rOKxM1 zdCZ9UPJ;P)G6$C!;rNcX~|3W34;SnHFl#REH==_ON5D&bhraVx z+5hP6OyHqhzXv`Ql9D1zB!y(_3av!WE-x@XqT+3SIpSQM-ROfl)ob&eSbYJ&PO`dFODF4UsqEi zg5Ti;n;Biqr`e|Ak@1@t2Yhl~!sD=2fs4zY>k8O6E$@ub7wr^FoE#Ep+p}FZB5mO} zV)>Quv_(N*`C48Se^~b8q>ze%Yg%}_ZvVW8YCrNx0{zK_CI1YaO){PQBROa)4j0Y) zyLtc5&!h}*G7i@P;j%#JA0;@t6KVhURt{{lY~UXxw|OmY)#h7peHO>$j0mT4POe*Q z8Io*CD%0ZhB4-_FuC$4dYkf|b?~msf(+$4##p>4LY?VEQ?De=%vn^Y;bltEX$Sb^7 zpVqOtYioVax!GAZJNcbwfSTi~w<1#2FP_po11*X?Gm5+n3=AwBlkpkSNvdQIjiqYN zNg_+;uB=Sk&~0j}60*sn$ZQ5x@WO3w4=zsipqy_HnwEh6dLWk@L-Ry z7S%pA;)%2cl_2dbyyS4nGwt(6ANGkfJBgFDqAe?CCWH>isfuiv?M_)B_8`20A{pbl z<8Ka*DYNe{n|mpV$RYkQiEwI4OySMQ!rNcgOKcKU+1?!OB$lj_AC_@yXJp*0-pG~> z-L~RF7bcf2IW95ZQd;^2K{ESD5ux`)pd7EaGQXY#ukzPu*V#dMad9|QdA_3di6m!c zg5rhU5qqeLe_44&h5FZ5iPj$PuIzrMtyD{vl9wZEF1K`;`>G+Wo^P7O(*-*G{X)6K zV^MpBIUaJj)bk$`UM~C1Fx1EJLEgMc?8;vg@(bc-95HiTR~A~)@>yl0D?aM}VO2ei z*urEPXBFF*Y*9f)oM(HM@So+k@g+c9;v++Al6${)F%#;q+Yu5{Jv#>K}Ke@i(m$kO*%vFM?y zH0>hERnXt-Bki)o=@fTmy;xD>O;19jsnC*| zL*|lgRutuzecQNn$9j%)ckGWzg`K*QpZvBU!JcFKN73etm(J{aPp*_&t`+dbY0vAM zxMZ_6b3F?N3bxDj%26*~@@&4SUG}Z^1b^}2Wr3>QmR@&?rtd1z;hstre3wxDn%9@` zrkMZUj&tSPmN&-)e$u-BJUmPO;k7`nAQy}t$Okw8XX2WhYWnoMtxTU>3g>B>~0wbmac*p(N@ zy7|plFwG{-hM$|i1wR-%LM>n02By4PlhR|Ow9Lb)R+Y{&ona+k>7 zS>G*h)KCwU84@pBtgcJ5n47XEKK#a=uUemj<~VY;E%sUL3b8eP;gl zxZK}n#yWzLA2ch19OB|n-v3KqT_!76SUvpZ!yeDH;Py~*F8kyYi8nby^?so=?m+zYfHclA8dsXhW5 zjd&x@XMLKkx+S%2#_FUujq+2=Hyz;045B!QESPt{YO}2EvxSo78l~P3eJ9(sPqX>a zt2nnn`P<+3dTj$XFL11@G7U}hV8`FKxArQC@Y=L*5vTnW>mKpT@q(3B1x3P5UWx z-&yUvnZGmAPdc#pYp^`+=*MLP)6&A;Uaar&q}Nx9Z8(2pdqF_|63rvF4L24)Xter( z@2Ye-eXVknZJUk%yp`Ooh1JyT`|b27uhJ`*J9t*{@8c1h|4-$%+Y;hOEo|O@x_rVd z*Px^K@;4h=ZT{1vwRQUS1H*J8#O={Nzii z^VLG_COfrgaTwsdX4~v7Etlu#k=DP(Ioo>flMhijGkllF-c_6XvV8Kl9aS1iS9vUA zr^M=;h$RpPL+u34|42Jy(SI!T;v4ZJ`vQ7X%}w7|IK(v4xoTwmrbYyl?at8ypJ}Wz zH~*xzr-ZDdcW+jR`TO31nXBgHHtqAr%d4Dfsl6Lm?LEn`Sf%#j(|1`l4&=iRKWvey zon<6=(xzQ*t=cE8!wJ+`VQTZ1y^5n2oqlOwEny;Hm+Mk5(ePeC_o^3fX1L{%Z#GGX z+v!ctGb_Y+<(sOnmE>G7ebRpW_2GP7+i7(T>g5UHVlp;WA_3C}8jr==e^$1bO66-( z?JrGU*|pnCd1kAC+MVRj(>mKX74wUIa{ha^OHhTy7lpyW$=mdbx;0xlxi4F(<#6tI z?OD1s)F8c0>r?nV>*B~yFYj5j?^Sl*%h`Qy_9@fWtm_=lQa7(C_srtkefO-_!1k)= z@u!zYU+PM@&1YwSVe7q0uRE18v2!>5ZD~{-{775IPhC%_Xt!pdg6A`xXMGlfxC;Yi zL3JfJ+H6Vh+MQ-KnM-Uj!&eyS*Z6H{SZz=hLb|6QZ}`{N zaVKkVRf&Jh^Q*>`=jkgoKDXV}q;TDu>Qzndh1FVN&I7u=JhFe5~EA4_wR09$$N~9bS-^*qOhuuSk$9t$;zJ*Gc$Ir!v=!t%TQo#aaN*hOfxR=6lhTkP$D=P#_cy`B|QB>dL$tlim+)xBl?G>g6! zJh#{LE^sG?w$FWA&vEsn`N~5#GwYq==3VzXA{n%NL91BFynjr%r6=#?QA)gX?u7E% z$@!^ztB)?yYz|33S^RL5@`@dn-s~$BJeyt;c7E(!cI9~wZ+6A5%5tm3`jSk)HO4W| zypDf6xS9KaUxxS9?H13ZAN~0LZRj-F+`ReA>XBz2YOS0!c`Xjn04MHPd@=r$%dwjd z@GE!tdk#(#ej=X*LqBmiBQ4AIOZ1Gj6^zy!>uGCQSpH?C&BgfLNjM?gs;ztbxpJSv zpNsyO8cdoz2mU-xPEH(hV>aG|vdRknD>LZ9K$!w}0RG26yFZ&iB{2@L;jI~WYOgod z(8&V^V$r!MAuAbr@=j6%#^fM5MV=7*{8bHlxky3l~ZO?mEDEq2T%;V*U@{e(z;^ zvq%-|0Bt584(EizvlN+VJk}m|uw!LlI|Qz+;9;9lL{j3I5*e9TYK}NBFw$`GY>jvw zY83Sn815l(IG{KVN@B`kPIMvp(1_j|1S)Y1oq7O;{wgl#*Nm7e~E zDTM_Ix^IcUWzlt4OhjU%B(PYbSjrT~&w{wC28B!}I?_lKGV8I!>yC4{1~zF13L6x` z(`A2500B+`iE@T;JuDoz8G7f_@SC5s$TV+%)+7-oVM&reG95^4Q6v&8Cx8TD8!HD% zedc(3IiQFG3fe{LR!snkHOYrWqm1FM=EV<-v?1IY&V z)ADm9QpX-UDyHmQML@Fv;+Zo_H{H4uKr^hS|6sCwSGH?A@Z>@s=!9ZYF~FE<_*HHU ztLc%QDXcx{&Ohdz8$nC%U^8?&V_nkO-3_!)#)kNUb} zUkRl!;scKwh@`>yvVK0w7GiDZZpJv);C2ul8>SlPJOPKquf) zmDs@OL;ZFrNd45xSjD!2#&d~t07D8|K#=2*zdq!e2|{7*rhNRfR!sq&yo8ZL_(cKV zra!_4WD~*DW0X!L701#`+^52W%K#@CLI>Jkjy|419M-z|oOEK%3xMH*R1@tlc1;ro z!y4s>MNr2r&0SefPC<1vc-Y7*Jb}PnvFRTi>4yFhNzd$GU>hCck@Ib0?kYzK; zcV%zH8(y_?%?0_#z!lIFY)BVI@_mRj8q`;q#Mg2(;(Kvb+y!8O#ejgkgYehq+y{)r z)2U97V=zfaRu-1-N=N2HT#$rB8$G>0?-{4`;p76T8w`g{=7ER+xIfr1t#lR+w@!BS z^d8)g34kHP_P>K@I4Wq93+CqqP1yf30DQYXZPFjEEggrl3P!aP$?*)49FOQNIpRBO zm593qhn$DihY18p^pO0{jWrE3!Cmml=(|mmG+-tj1PWMgkN7AGVnSdwM{RIq`-<1ifDNye{`-vCSb&^?D= z*1D=2?ud#h+7T|6~i}I0Bf^Wt1mS>HD*q*>G6@ zw@ZLk28@V)%f~0a4Se=Gh)0Xgx4}xZ66>cfaC(`CELkg=L?7RZm1t#V(LVN#_(g}f z64~GwT<-eO1+zmA7>Q;UJUyTh@7?KGyBePP0L)_OB#JK>Bf-{?KaIIP6(#Mp;~mJ( zge^>al;>A&|5N#{LyaHaK8!hZxch%-+w$j}&dT|aamXW4k+~NNMMVn?~W z&kHE2r3;Ln)4EeJ!7wFJp{xft>9FWiLI6T5W8cNXq$Arwg4=`Bm&Tu|2$Y1 zYB!xs8=LqawzlOW26_Aovr#H3>9=q=p9xn#weY-ZYXk z$q{mKU5dw;4r+RT!2S`0vH}<<=xj%+7-KNjn(+>rP0a?)bOD4LN;6R9YuF|&6P)%iWZPkp~IK)lkq}8x#nLGMmq|t=z-{> z#ABYpY*;p%NR8G-__GPXU~LfR$F=jz!BJH~A6_U&74F6WVt8#ZvQbFVicIvQLYoZH z2^rV_v15Gq`T1jUP+fC@WhB~Efjtv~$E+m_Y9szdOiTDoaN7u`1R&u%1{fQO4i*&T zT;#tV!^&q65Z?#Wm5+j{HZr-cEN=4n#;-28E;9&geH?j3kM{?!K~i*Ql-C%uO$5eJ z#`qgoK~$rpl#(rrhkg~Pd7?wh7LEyEVpdEIv;pqd*to6={8bee5NLnp+B!~%;m$jx z<}h+NF=Nmm%%>lBlTid0Nr6Qyy7*(~feFSC0`z|nT*k@~twKCIHNaCvAw5AiyYbR7 zL13(9eyEIdPz@djN)pvObSB)KJm%|D&mE zbA7WjAj0**?B|4Xsi49Mf%;E1b*$AVoq$nChs7}&MU+>9HIWsRbI1fwq9w)3N)KrS z|Bos&Zqq4$9q0^uyKwXZwdV%LY^)tSu6k#YIh5l27sG|LDCHE@j1OP~!H2kF8EdI` zTMXQh*ACZ$Ss+y#@!9ce{8EjPZai2JBR@?k9wf&xy5CndbOw9{3Ib4|H|LVuFr)9Bu?g*v>C&y0u61E$?qcl*F1>k8NCG5d0Gg7Ngo zBpQj}K?)cvqxDwe%j*P}`3#0bSGzt=nKG`Ke8ZTk`*}Q!u`pzt}lq*EVV zp7!O!80;qxYY>4(q2oeeIWfV})un4Qumxe3{}xtX#`d;N{4gnIfpZ(7hSf&F@ySO{ zf1zGoG`gl#&G+#1B5;m7@c8JM(msFuqLHK;T5wPodXFa9JxxpNB6tB0WCrMdwSAJ~ zBhVXKR6yD^BFp@be9qxol*nvw$4Y>4L|LL%3VWELecs<^ywuFVkkg=@1c0(f0eQh&N>zSHRkZ-l1xvo9)g|l<*Yrf ztdjFu48z~iYUd8aPWTGe!gU68Oa#H*`M}-L!UZF-6TXtQaQkOxUnRkl3&Y|XE&OZ@ zcEVS&7S2&qn<52IF3$Ai*Wmf2Q#C{^CzPJ?E>U;JqI^U5#UB%Rc|bEgqXSOUn>2K| zgk{6V$g5D%1&#w9e=2?W&BQ-%rXAy!+R+`OaeSgj z-O@Jt4#Uwp7@00IL3?^hro$gg*4VI_WAaTyVM5Foj~O|-84 z$;06hMwt*rV;^8iB z1~&0XWpYJmG?Ts^K9PC62H*`G}xom%S%yq|xvG~FIfP=9*f zZoDRJBm*Y0aId=qJ?7dyb)6)JGWGwe)MHeNSzhi)Ko6J<-m@v=a%NsP537lHe0R* z`If4$aaBA#S=w!2z&m>{lpTy^Lm^mg*3?M&7HFv}7K6x*cukLIGX;bQG|QWdn{%_6 zHnwBKr84#B7Z+AnBXa16a?or^R?+>$4`}{*a_>IhbjvyTtWkHw)|ay)ahWUd-qq$~ zMbh6roVsj;_qnC-R{G+Cy6bApVOinSU-;(DxUEl!i2)1EeQ9`hrfqj(nKI7?Z>Xur zoJz-a`PxkYit1HEbv|jy%~DO^13J-ut986EEG=66S}D3!L}Efp;Bez~7tNq{QsUMm zh9~(HYg1pA*=37C0}n4g&bFbQ+?-h-W}onYeE{q;cIy%eZK9wZjSwGvT+&Cgv z?~{9p(;bY_1+k|wkt_|N!@J~aoY@|U_RGoWX<;p{Nu*D*&_phw`8jYkMNpRTWx1H* z>J-Mi_!`M468#5Aix$$u1M@rJEIOc?k^QBc?T(#=n&*5eS#u*Y)?L8Ha$9wRWdH^3D4|Ps)Y?m0q~SiKiSfEkJ!=^`lJ(%W3o|CZ zSrZL-Xxc{OrmsQD&s~zPfNJOpSZUl%V8tdG%ei}lQkM+z@-4etFPR>GOH9+Y_F<3=~SXln9Kb-o~f>2a6Xz@AS3cn^;c_>lUwlK(n>z?A>NbC z`Ud8^aQy>wy=$)w;JZzA)_*Y$Z5hU=KAG&htLw1Uh00yE!|Nu{EZkch zY9O6x7Y??>!7pUNME*d!=R#s)ghr|R#41l!c?~=3CS8&zr6*aA7n9*)*PWBV2w+&I zpW1-9fr3j{VTcls1>ua}F*bbju_Xq%^v;-W~paSqlf zolj*dt`BBjHI)H9{zrkBo=B%>8}4jeBO~kWqO!~Thi!I1H(in=n^fS%nuL=X2+s!p}HfTU#NBGiwEBF^^tKU zbhhv+0dE-sbK$>J#t-J!B$TMgN@Wh5wTtK2BG}4BGfsZOoRUS#G8Cxv|6EI*n&Xxq zt{&OxCC+BNqz$9b0WM7_PyBJEVObHFh%%`~!@MNZlo*oXDCwDcFwT~Rls!aApL<)^ zbBftGKKBRhB!{?fX@l2_y~%ygNFfF(XJzHh#?`WlSL{1lKT*gJM zs>bd^H9NCxqxn(IOky5k-wALFowQr(gw%|`0991u#9jXQh?4l|l>pd6a&rx|v=fPJ z1mutj{YzpJ_gsClbWFk(G}bSlFi-6@mwoQh-XeD*j@~huW4(8ub%^I|azA)h2t#yG z7e_V_<4jlM3D(I+qX}yEtqj)cpzN*oCdYHa!nm%0t^wHm)EmFP*|FMw!tb@&`G-u~ zK)=Sf6z+BiTAI}}i{*_Ac$ffr*Wrv$F7_0gJkjx;@)XjYSh`RjAgrCck`x!zP>Ifu z&%he4P|S)H*(9oB4uvH67^0}I-_ye_!w)u3v2+EY>eD3#8QR24<;7?*hj8k~rS)~7 zSXs5ww)T(0eHSp$hEIBnW|Iun<_i`}VE0Nc$|-R}wlSIs5pV{g_Dar(Zz<4X3`W?K z6&CAIl4U(Qk-tTcK{|zYF6QG5ArrEB!;5s?tW7 zrE3hcFY&k)+)e{+YOJ0X2uDE_hd2{|m_dC}kgEKqiE9Q^A-+>2UonB+L@v3$9?AYw zVQv?X*pK;X4Ovc6Ev5Gbg{{Eu*7{N3#0@9oMI~}KnObQE#Y{&3mM4`w%wN+xrKYgD zB-ay0Q}m{QI;iY`s1Z^NqIkjrTlf`B)B#MajZ#9u41oRBC1oM1vq0i|F59> z#StM@bHt|#`2)cpl_rWB($DNJ3Lap}QM-+A$3pe}NyP(@+i1>o^fe-oxX#Bt`mcQc zb?pD4W%#ep|3%CHAYnr*^M6Czg>~L4?l16H1OozM{P*en298b+`i4$|w$|4AHbzqB zHpYUsHZET$Z0ztC;U+0*+amF!@PI%^oUIZy{`L{%O^i{Xk}X0&nl)n~tVEpcAJSJ} zverw15zP1P-O8h9nd!&hj$zuwjg?DoxYIw{jWM zW5_pj+wFy8Tsa9g<7Qa21WaV&;ejoYflRKcz?#fSH_)@*QVlN2l4(QNk| z4aPnv&mrS&0|6NHq05XQw$J^RR9T{3SOcMKCXIR1iSf+xJ0E_Wv?jEc*I#ZPzyJN2 zUG0UOXHl+PikM*&g$U@g+KbG-RY>uaIl&DEtw_Q=FYq?etc!;hEC_}UX{eyh%dw2V zTTSlap&5>PY{6I#(6`j-9`D&I#|YPP8a;(sOzgeKDWsLa!i-$frD>zr-oid!Hf&yS z!i^cr&7tN}OOGmX2)`8k?Tn!!4=tz~3hCTq_9CdiV!NIblUDxHh(FJ$zs)B2(t5@u z-`^RA1ShrLCkg0)OhfoM;4Z{&oZmAec$qV@ zGQ(7(!CBk<5;Ar%DLJ0p0!ResC#U<+3i<|vib1?{5gCebG7$F7URKZXuX-2WgF>YJ^i zMhHDBsh9PDU8dlZ$yJKtc6JA#y!y$57%sE>4Nt+wF1lfNIWyA`=hF=9Gj%sRwi@vd z%2eVV3y&dvAgyuJ=eNJR+*080dbO_t@BFJO<@&#yqTK&+xc|FRR;p;KVk@J3$S{p` zGaMj6isho#%m)?pOG^G0mzOAw0z?!AEMsv=0T>WWcE>??WS=fII$t$(^PDPMU(P>o z_*0s^W#|x)%tx8jIgZY~A2yG;US0m2ZOQt6yJqW@XNY_>_R7(Nxb8Ged6BdYW6{prd!|zuX$@Q2o6Ona8zzYC1u!+2!Y$Jc9a;wy+pXt}o6~Bu1oF1c zp7Y|SBTNi@=I(K%A60PMjM#sfH$y*c{xUgeSpi#HB`?|`!Tb&-qJ3;vxS!TIzuTZs-&%#bAkAyw9m4PJgvey zM5?up*b}eDEY+#@tKec)-c(#QF0P?MRlD1+7%Yk*jW;)`f;0a-ZJ6CQA?E%>i2Dt7T9?s|9ZF|KP4;CNWvaVKZ+Qeut;Jith_y{v*Ny6Co6!8MZx;Wgo z=qAi%&S;8J{iyD&>3CLCQdTX*$+Rx1AwA*D_J^0>suTgBMBb=*hefV+Ars#mmr+YsI3#!F@Xc1t4F-gB@6aoyT+5O(qMz*zG<9Qq*f0w^V!03rpr*-WLH}; zfM{xSPJeu6D(%8HU%0GEa%waFHE$G?FH^kMS-&I3)ycx|iv{T6Wx}9$$D&6{%1N_8 z_CLw)_9+O4&u94##vI9b-HHm_95m)fa??q07`DniVjAy`t7;)4NpeyAY(aAk(+T_O z1om+b5K2g_B&b2DCTK<>SE$Ode1DopAi)xaJjU>**AJK3hZrnhEQ9E`2=|HHe<^tv z63e(bn#fMWuz>4erc47}!J>U58%<&N<6AOAewyzNTqi7hJc|X{782&cM zHZYclNbBwU6673=!ClmxMfkC$(CykGR@10F!zN1Se83LR&a~$Ht&>~43OX22mt7tcZUpa;9@q}KDX3O&Ugp6< zLZLfIMO5;pTee1vNyVC$FGxzK2f>0Z-6hM82zKg44nWo|n}$Zk6&;5ry3`(JFEX$q zK&KivAe${e^5ZGc3a9hOt|!UOE&OocpVryE$Y4sPcs4rJ>>Kbi2_subQ9($2VN(3o zb~tEzMsHaBmBtaHAyES+d3A(qURgiskSSwUc9CfJ@99&MKp2sooSYZu+-0t0+L*!I zYagjOlPgx|lep9tiU%ts&McF6b0VE57%E0Ho%2oi?=Ks+5%aj#au^OBwNwhec zta6QAeQI^V!dF1C)>RHAmB`HnxyqWx?td@4sd15zPd*Fc9hpDXP23kbBenBxGeD$k z;%0VBQEJ-C)&dTAw_yW@k0u?IUk*NrkJ)(XEeI z9Y>6Vel>#s_v@=@0<{4A{pl=9cQ&Iah0iD0H`q)7NeCIRz8zx;! z^OO;1+IqoQNak&pV`qKW+K0^Hqp!~gSohcyS)?^P`JNZXw@gc6{A3OLZ?@1Uc^I2v z+X!^R*HCm3{7JPq{8*Tn>5;B|X7n4QQ0Bs79uTU%nbqOJh`nX(BVj!#f;#J+WZxx4 z_yM&1Y`2XzhfqkIMO7tB3raJKQS+H5F%o83bM+hxbQ zeeJm=Dvix$2j|b4?mDacb67v-1^lTp${z=jc1=j~QD>7c*@+1?py>%Kj%Ejp7Y-!? z8iYRUlGVrQPandAaxFfks53@2EC#0)%mrnmGRn&>=$H$S8q|kE_iWko4`^vCS2aWg z#!`RHUGyOt*k?bBYu3*j3u0gB#v(3tsije zgIuNNWNtrOkx@Pzs;A9un+2LX!zw+p3_NX^Sh09HZAf>m8l@O*rXy_82aWT$Q>iyy zqO7Of)D=wcSn!0+467&!Hl))eff=$aneB?R!YykdKW@k^_uR!+Q1tR)+IJb`-6=jj zymzA>Sv4>Z&g&WWu#|~GcP7qP&m*w-S$)7Xr;(duqCTe7p8H3k5>Y-n8438+%^9~K z3r^LIT_K{i7DgEJjIocw_6d0!<;wKT`X;&vv+&msmhAAnIe!OTdybPctzcEzBy88_ zWO{6i4YT%e4^WQZB)KHCvA(0tS zHu_Bg+6Ko%a9~$EjRB90`P(2~6uI@SFibxct{H#o&y40MdiXblu@VFXbhz>Nko;7R z70Ntmm-FePqhb%9gL+7U8@(ch|JfH5Fm)5${8|`Lef>LttM_iww6LW2X61ldBmG0z zax3y)njFe>j*T{i0s8D4=L>X^j0)({R5lMGVS#7(2C9@AxL&C-lZQx~czI7Iv+{%1 z2hEG>RzX4S8x3v#9sgGAnPzptM)g&LB}@%E>fy0vGSa(&q0ch|=ncKjNrK z`jA~jObJhrJ^ri|-)J^HUyeZXz~XkBp$VhcTEcTdc#a2EUOGVX?@mYx#Vy*!qO$Jv zQ4rgOJ~M*o-_Wptam=~krnmG*p^j!JAqoQ%+YsDFW7Cc9M%YPiBOrVcD^RY>m9Pd< zu}#9M?K{+;UIO!D9qOpq9yxUquQRmQNMo0pT`@$pVt=rMvyX)ph(-CCJLvUJy71DI zBk7oc7)-%ngdj~s@76Yse3L^gV0 z2==qfp&Q~L(+%RHP0n}+xH#k(hPRx(!AdBM$JCfJ5*C=K3ts>P?@@SZ_+{U2qFZb>4kZ{Go37{# zSQc+-dq*a-Vy4?taS&{Ht|MLRiS)Sn14JOONyXqPNnpq&2y~)6wEG0oNy>qvod$FF z`9o&?&6uZjhZ4_*5qWVrEfu(>_n2Xi2{@Gz9MZ8!YmjYvIMasE9yVQL10NBrTCczq zcTY1q^PF2l!Eraguf{+PtHV3=2A?Cu&NN&a8V(y;q(^_mFc6)%Yfn&X&~Pq zU1?qCj^LF(EQB1F`8NxNjyV%fde}dEa(Hx=r7$~ts2dzDwyi6ByBAIx$NllB4%K=O z$AHz1<2bTUb>(MCVPpK(E9wlLElo(aSd(Os)^Raum`d(g9Vd_+Bf&V;l=@mM=cC>) z)9b0enb)u_7V!!E_bl>u5nf&Rl|2r=2F3rHMdb7y9E}}F82^$Rf+P8%dKnOeKh1vs zhH^P*4Ydr^$)$h@4KVzxrHyy#cKmWEa9P5DJ|- zG;!Qi35Tp7XNj60=$!S6U#!(${6hyh7d4q=pF{`0t|N^|L^d8pD{O9@tF~W;#Je*P z&ah%W!KOIN;SyAEhAeTafJ4uEL`(RtnovM+cb(O#>xQnk?dzAjG^~4$dFn^<@-Na3 z395;wBnS{t*H;Jef2eE!2}u5Ns{AHj>WYZDgQJt8v%x?9{MXqJsGP|l%OiZqQ1aB! z%E=*Ig`(!tHh>}4_z5IMpg{49UvD*Pp9!pxt_gdAW%sIf3k6CTycOT1McPl=_#0?8 zVjz8Hj*Vy9c5-krd-{BQ{6Xy|P$6LJvMuX$* zA+@I_66_ET5l2&gk9n4$1M3LN8(yEViRx&mtd#LD}AqEs?RW=xKC(OCWH;~>(X6h!uDxXIPH06xh z*`F4cVlbDP`A)-fzf>MuScYsmq&1LUMGaQ3bRm6i7OsJ|%uhTDT zlvZA1M}nz*SalJWNT|`dBm1$xlaA>CCiQ zK`xD-RuEn>-`Z?M{1%@wewf#8?F|(@1e0+T4>nmlSRrNK5f)BJ2H*$q(H>zGD0>eL zQ!tl_Wk)k*e6v^m*{~A;@6+JGeWU-q9>?+L_#UNT%G?4&BnOgvm9@o7l?ov~XL+et zbGT)|G7)KAeqb=wHSPk+J1bdg7N3$vp(ekjI1D9V$G5Cj!=R2w=3*4!z*J-r-cyeb zd(i2KmX!|Lhey!snRw z?#$Gu%S^SQEKt&kep)up#j&9}e+3=JJBS(s>MH+|=R(`8xK{mmndWo_r`-w1#SeRD&YtAJ#GiVI*TkQZ}&aq<+bU2+coU3!jCI6E+Ad_xFW*ghnZ$q zAoF*i&3n1j#?B8x;kjSJD${1jdRB;)R*)Ao!9bd|C7{;iqDo|T&>KSh6*hCD!rwv= zyK#F@2+cv3=|S1Kef(E6Niv8kyLVLX&e=U;{0x{$tDfShqkjUME>f8d(5nzSkY6@! z^-0>DM)wa&%m#UF1F?zR`8Y3X#tA!*7Q$P3lZJ%*KNlrk_uaPkxw~ zxZ1qlE;Zo;nb@!SMazSjM>;34ROOoygo%SF);LL>rRonWwR>bmSd1XD^~sGSu$Gg# zFZ`|yKU0%!v07dz^v(tY%;So(e`o{ZYTX`hm;@b0%8|H>VW`*cr8R%3n|ehw2`(9B+V72`>SY}9^8oh$En80mZK9T4abVG*to;E z1_S6bgDOW?!Oy1LwYy=w3q~KKdbNtyH#d24PFjX)KYMY93{3-mPP-H>@M-_>N~DDu zENh~reh?JBAK=TFN-SfDfT^=+{w4ea2KNWXq2Y<;?(gf(FgVp8Zp-oEjKzB%2Iqj;48GmY3h=bcdYJ}~&4tS`Q1sb=^emaW$IC$|R+r-8V- zf0$gGE(CS_n4s>oicVk)MfvVg#I>iDvf~Ov8bk}sSxluG!6#^Z_zhB&U^`eIi1@j( z^CK$z^stBHtaDDHxn+R;3u+>Lil^}fj?7eaGB z&5nl^STqcaBxI@v>%zG|j))G(rVa4aY=B@^2{TFkW~YP!8!9TG#(-nOf^^X-%m9{Z zCC?iC`G-^RcBSCuk=Z`(FaUUe?hf3{0C>>$?Vs z`2Uud9M+T&KB6o4o9kvdi^Q=Bw!asPdxbe#W-Oaa#_NP(qpyF@bVxv5D5))srkU#m zj_KA+#7sqDn*Ipf!F5Byco4HOSd!Ui$l94|IbW%Ny(s1>f4|Mv^#NfB31N~kya9!k zWCGL-$0ZQztBate^fd>R!hXY_N9ZjYp3V~4_V z#eB)Kjr8yW=+oG)BuNdZG?jaZlw+l_ma8aET(s+-x+=F-t#Qoiuu1i`^x8Sj>b^U} zs^z<()YMFP7CmjUC@M=&lA5W7t&cxTlzJAts*%PBDAPuqcV5o7HEnqjif_7xGt)F% zGx2b4w{@!tE)$p=l3&?Bf#`+!-RLOleeRk3 z7#pF|w@6_sBmn1nECqdunmG^}pr5(ZJQVvAt$6p3H(16~;vO>?sTE`Y+mq5YP&PBo zvq!7#W$Gewy`;%6o^!Dtjz~x)T}Bdk*BS#=EY=ODD&B=V6TD2z^hj1m5^d6s)D*wk zu$z~D7QuZ2b?5`p)E8e2_L38v3WE{V`bVk;6fl#o2`) z99JsWhh?$oVRn@$S#)uK&8DL8>An0&S<%V8hnGD7Z^;Y(%6;^9!7kDQ5bjR_V+~wp zfx4m3z6CWmmZ<8gDGUyg3>t8wgJ5NkkiEm^(sedCicP^&3D%}6LtIUq>mXCAt{9eF zNXL$kGcoUTf_Lhm`t;hD-SE)m=iBnxRU(NyL}f6~1uH)`K!hmYZjLI%H}AmEF5RZt z06$wn63GHnApHXZZJ}s^s)j9(BM6e*7IBK6Bq(!)d~zR#rbxK9NVIlgquoMq z=eGZ9NR!SEqP6=9UQg#@!rtbbSBUM#ynF);zKX+|!Zm}*{H z+j=d?aZ2!?@EL7C~%B?6ouCKLnO$uWn;Y6Xz zX8dSwj732u(o*U3F$F=7xwxm>E-B+SVZH;O-4XPuPkLSt_?S0)lb7EEg)Mglk0#eS z9@jl(OnH4juMxY+*r03VDfPx_IM!Lmc(5hOI;`?d37f>jPP$?9jQQIQU@i4vuG6MagEoJrQ=RD7xt@8E;c zeGV*+Pt+t$@pt!|McETOE$9k=_C!70uhwRS9X#b%ZK z%q(TIUXSS^F0`4Cx?Rk07C6wI4!UVPeI~-fxY6`YH$kABdOuiRtl73MqG|~AzZ@iL&^s?24iS;RK_pdlWkhcF z@Wv-Om(Aealfg)D^adlXh9Nvf~Uf@y;g3Y)i(YP zEXDnb1V}1pJT5ZWyw=1i+0fni9yINurD=EqH^ciOwLUGi)C%Da)tyt=zq2P7pV5-G zR7!oq28-Fgn5pW|nlu^b!S1Z#r7!Wtr{5J5PQ>pd+2P7RSD?>(U7-|Y z7ZQ5lhYIl_IF<9?T9^IPK<(Hp;l5bl5tF9>X-zG14_7PfsA>6<$~A338iYRT{a@r_ zuXBaT=`T5x3=s&3=RYx6NgG>No4?5KFBVjE(swfcivcIpPQFx5l+O;fiGsOrl5teR z_Cm+;PW}O0Dwe_(4Z@XZ)O0W-v2X><&L*<~*q3dg;bQW3g7)a#3KiQP>+qj|qo*Hk z?57>f2?f@`=Fj^nkDKeRkN2d$Z@2eNKpHo}ksj-$`QKb6n?*$^*%Fb3_Kbf1(*W9K>{L$mud2WHJ=j0^=g30Xhg8$#g^?36`p1fm;;1@0Lrx+8t`?vN0ZorM zSW?rhjCE8$C|@p^sXdx z|NOHHg+fL;HIlqyLp~SSdIF`TnSHehNCU9t89yr@)FY<~hu+X`tjg(aSVae$wDG*C zq$nY(Y494R)hD!i1|IIyP*&PD_c2FPgeY)&mX1qujB1VHPG9`yFQpLFVQ0>EKS@Bp zAfP5`C(sWGLI?AC{XEjLKR4FVNw(4+9b?kba95ukgR1H?w<8F7)G+6&(zUhIE5Ef% z=fFkL3QKA~M@h{nzjRq!Y_t!%U66#L8!(2-GgFxkD1=JRRqk=n%G(yHKn%^&$dW>; zSjAcjETMz1%205se$iH_)ZCpfg_LwvnsZQAUCS#^FExp8O4CrJb6>JquNV@qPq~3A zZ<6dOU#6|8+fcgiA#~MDmcpIEaUO02L5#T$HV0$EMD94HT_eXLZ2Zi&(! z&5E>%&|FZ`)CN10tM%tLSPD*~r#--K(H-CZqIOb99_;m|D5wdgJ<1iOJz@h2Zkq?} z%8_KXb&hf=2Wza(Wgc;3v3TN*;HTU*q2?#z&tLn_U0Nt!y>Oo>+2T)He6%XuP;fgn z-G!#h$Y2`9>Jtf}hbVrm6D70|ERzLAU>3zoWhJmjWfgM^))T+2u$~5>HF9jQDkrXR z=IzX36)V75PrFjkQ%TO+iqKGCQ-DDXbaE;C#}!-CoWQx&v*vHfyI>$HNRbpvm<`O( zlx9NBWD6_e&J%Ous4yp~s6)Ghni!I6)0W;9(9$y1wWu`$gs<$9Mcf$L*piP zPR0Av*2%ul`W;?-1_-5Zy0~}?`e@Y5A&0H!^ApyVTT}BiOm4GeFo$_oPlDEyeGBbh z1h3q&Dx~GmUS|3@4V36&$2uO8!Yp&^pD7J5&TN{?xphf*-js1fP?B|`>p_K>lh{ij zP(?H%e}AIP?_i^f&Li=FDSQ`2_NWxL+BB=nQr=$ zHojMlXNGauvvwPU>ZLq!`bX-5F4jBJ&So{kE5+ms9UEYD{66!|k~3vsP+mE}x!>%P za98bAU0!h0&ka4EoiDvBM#CP#dRNdXJcb*(%=<(g+M@<)DZ!@v1V>;54En?igcHR2 zhubQMq}VSOK)onqHfczM7YA@s=9*ow;k;8)&?J3@0JiGcP! zP#00KZ1t)GyZeRJ=f0^gc+58lc4Qh*S7RqPIC6GugG1gXe$LIQMRCo8cHf^qXgAa2 z`}t>u2Cq1CbSEpLr~E=c7~=Qkc9-vLE%(v9N*&HF`(d~(0`iukl5aQ9u4rUvc8%m) zr2GwZN4!s;{SB87lJB;veebPmqE}tSpT>+`t?<457Q9iV$th%i__Z1kOMAswFldD6 ztbOvO337S5o#ZZgN2G99_AVqPv!?Gmt3pzgD+Hp3QPQ`9qJ(g=kjvD+fUSS3upJn! zqoG7acIKEFRX~S}3|{EWT$kdz#zrDlJU(rPkxjws_iyLKU8+v|*oS_W*-guAb&Pj1 z35Z`3z<&Jb@2Mwz=KXucNYdY#SNO$tcVFr9KdKm|%^e-TXzs6M`PBper%ajkrIyUe zp$vVxVs9*>Vp4_1NC~Zg)WOCPmOxI1V34QlG4!aSFOH{QqSVq1^1)- z0P!Z?tT&E-ll(pwf0?=F=yOzik=@nh1Clxr9}Vij89z)ePDSCYAqw?lVI?v?+&*zH z)p$CScFI8rrwId~`}9YWPFu0cW1Sf@vRELs&cbntRU6QfPK-SO*mqu|u~}8AJ!Q$z znzu}50O=YbjwKCuSVBs6&CZR#0FTu)3{}qJJYX(>QPr4$RqWiwX3NT~;>cLn*_&1H zaKpIW)JVJ>b{uo2oq>oQt3y=zJjb%fU@wLqM{SyaC6x2snMx-}ivfU<1- znu1Lh;i$3Tf$Kh5Uk))G!D1UhE8pvx&nO~w^fG)BC&L!_hQk%^p`Kp@F{cz>80W&T ziOK=Sq3fdRu*V0=S53rcIfWFazI}Twj63CG(jOB;$*b`*#B9uEnBM`hDk*EwSRdwP8?5T?xGUKs=5N83XsR*)a4|ijz|c{4tIU+4j^A5C<#5 z*$c_d=5ml~%pGxw#?*q9N7aRwPux5EyqHVkdJO=5J>84!X6P>DS8PTTz>7C#FO?k#edkntG+fJk8ZMn?pmJSO@`x-QHq;7^h6GEXLXo1TCNhH z8ZDH{*NLAjo3WM`xeb=X{((uv3H(8&r8fJJg_uSs_%hOH%JDD?hu*2NvWGYD+j)&` zz#_1%O1wF^o5ryt?O0n;`lHbzp0wQ?rcbW(F1+h7_EZZ9{>rePvLAPVZ_R|n@;b$;UchU=0j<6k8G9QuQf@76oiE*4 zXOLQ&n3$NR#p4<5NJMVC*S);5x2)eRbaAM%VxWu9ohlT;pGEk7;002enCbQ>2r-us z3#bpXP9g|mE`65VrN`+3mC)M(eMj~~eOf)do<@l+fMiTR)XO}422*1SL{wyY(%oMpBgJagtiDf zz>O6(m;};>Hi=t8o{DVC@YigqS(Qh+ix3Rwa9aliH}a}IlOCW1@?%h_bRbq-W{KHF z%Vo?-j@{Xi@=~Lz5uZP27==UGE15|g^0gzD|3x)SCEXrx`*MP^FDLl%pOi~~Il;dc z^hrwp9sYeT7iZ)-ajKy@{a`kr0-5*_!XfBpXwEcFGJ;%kV$0Nx;apKrur zJN2J~CAv{Zjj%FolyurtW8RaFmpn&zKJWL>(0;;+q(%(Hx!GMW4AcfP0YJ*Vz!F4g z!ZhMyj$BdXL@MlF%KeInmPCt~9&A!;cRw)W!Hi@0DY(GD_f?jeV{=s=cJ6e}JktJw zQORnxxj3mBxfrH=x{`_^Z1ddDh}L#V7i}$njUFRVwOX?qOTKjfPMBO4y(WiU<)epb zvB9L=%jW#*SL|Nd_G?E*_h1^M-$PG6Pc_&QqF0O-FIOpa4)PAEPsyvB)GKasmBoEt z?_Q2~QCYGH+hW31x-B=@5_AN870vY#KB~3a*&{I=f);3Kv7q4Q7s)0)gVYx2#Iz9g(F2;=+Iy4 z6KI^8GJ6D@%tpS^8boU}zpi=+(5GfIR)35PzrbuXeL1Y1N%JK7PG|^2k3qIqHfX;G zQ}~JZ-UWx|60P5?d1e;AHx!_;#PG%d=^X(AR%i`l0jSpYOpXoKFW~7ip7|xvN;2^? zsYC9fanpO7rO=V7+KXqVc;Q5z%Bj})xHVrgoR04sA2 zl~DAwv=!(()DvH*=lyhIlU^hBkA0$e*7&fJpB0|oB7)rqGK#5##2T`@_I^|O2x4GO z;xh6ROcV<9>?e0)MI(y++$-ksV;G;Xe`lh76T#Htuia+(UrIXrf9?

L(tZ$0BqX1>24?V$S+&kLZ`AodQ4_)P#Q3*4xg8}lMV-FLwC*cN$< zt65Rf%7z41u^i=P*qO8>JqXPrinQFapR7qHAtp~&RZ85$>ob|Js;GS^y;S{XnGiBc zGa4IGvDl?x%gY`vNhv8wgZnP#UYI-w*^4YCZnxkF85@ldepk$&$#3EAhrJY0U)lR{F6sM3SONV^+$;Zx8BD&Eku3K zKNLZyBni3)pGzU0;n(X@1fX8wYGKYMpLmCu{N5-}epPDxClPFK#A@02WM3!myN%bkF z|GJ4GZ}3sL{3{qXemy+#Uk{4>Kf8v11;f8I&c76+B&AQ8udd<8gU7+BeWC`akUU~U zgXoxie>MS@rBoyY8O8Tc&8id!w+_ooxcr!1?#rc$-|SBBtH6S?)1e#P#S?jFZ8u-Bs&k`yLqW|{j+%c#A4AQ>+tj$Y z^CZajspu$F%73E68Lw5q7IVREED9r1Ijsg#@DzH>wKseye>hjsk^{n0g?3+gs@7`i zHx+-!sjLx^fS;fY!ERBU+Q zVJ!e0hJH%P)z!y%1^ZyG0>PN@5W~SV%f>}c?$H8r;Sy-ui>aruVTY=bHe}$e zi&Q4&XK!qT7-XjCrDaufT@>ieQ&4G(SShUob0Q>Gznep9fR783jGuUynAqc6$pYX; z7*O@@JW>O6lKIk0G00xsm|=*UVTQBB`u1f=6wGAj%nHK_;Aqmfa!eAykDmi-@u%6~ z;*c!pS1@V8r@IX9j&rW&d*}wpNs96O2Ute>%yt{yv>k!6zfT6pru{F1M3P z2WN1JDYqoTB#(`kE{H676QOoX`cnqHl1Yaru)>8Ky~VU{)r#{&s86Vz5X)v15ULHA zAZDb{99+s~qI6;-dQ5DBjHJP@GYTwn;Dv&9kE<0R!d z8tf1oq$kO`_sV(NHOSbMwr=To4r^X$`sBW4$gWUov|WY?xccQJN}1DOL|GEaD_!@& z15p?Pj+>7d`@LvNIu9*^hPN)pwcv|akvYYq)ks%`G>!+!pW{-iXPZsRp8 z35LR;DhseQKWYSD`%gO&k$Dj6_6q#vjWA}rZcWtQr=Xn*)kJ9kacA=esi*I<)1>w^ zO_+E>QvjP)qiSZg9M|GNeLtO2D7xT6vsj`88sd!94j^AqxFLi}@w9!Y*?nwWARE0P znuI_7A-saQ+%?MFA$gttMV-NAR^#tjl_e{R$N8t2NbOlX373>e7Ox=l=;y#;M7asp zRCz*CLnrm$esvSb5{T<$6CjY zmZ(i{Rs_<#pWW>(HPaaYj`%YqBra=Ey3R21O7vUbzOkJJO?V`4-D*u4$Me0Bx$K(lYo`JO}gnC zx`V}a7m-hLU9Xvb@K2ymioF)vj12<*^oAqRuG_4u%(ah?+go%$kOpfb`T96P+L$4> zQ#S+sA%VbH&mD1k5Ak7^^dZoC>`1L%i>ZXmooA!%GI)b+$D&ziKrb)a=-ds9xk#~& z7)3iem6I|r5+ZrTRe_W861x8JpD`DDIYZNm{$baw+$)X^Jtjnl0xlBgdnNY}x%5za zkQ8E6T<^$sKBPtL4(1zi_Rd(tVth*3Xs!ulflX+70?gb&jRTnI8l+*Aj9{|d%qLZ+ z>~V9Z;)`8-lds*Zgs~z1?Fg?Po7|FDl(Ce<*c^2=lFQ~ahwh6rqSjtM5+$GT>3WZW zj;u~w9xwAhOc<kF}~`CJ68 z?(S5vNJa;kriPlim33{N5`C{9?NWhzsna_~^|K2k4xz1`xcui*LXL-1#Y}Hi9`Oo!zQ>x-kgAX4LrPz63uZ+?uG*84@PKq-KgQlMNRwz=6Yes) zY}>YN+qP}nwr$(CZQFjUOI=-6J$2^XGvC~EZ+vrqWaOXB$k?%Suf5k=4>AveC1aJ! ziaW4IS%F$_Babi)kA8Y&u4F7E%99OPtm=vzw$$ zEz#9rvn`Iot_z-r3MtV>k)YvErZ<^Oa${`2>MYYODSr6?QZu+be-~MBjwPGdMvGd!b!elsdi4% z`37W*8+OGulab8YM?`KjJ8e+jM(tqLKSS@=jimq3)Ea2EB%88L8CaM+aG7;27b?5` z4zuUWBr)f)k2o&xg{iZ$IQkJ+SK>lpq4GEacu~eOW4yNFLU!Kgc{w4&D$4ecm0f}~ zTTzquRW@`f0}|IILl`!1P+;69g^upiPA6F{)U8)muWHzexRenBU$E^9X-uIY2%&1w z_=#5*(nmxJ9zF%styBwivi)?#KMG96-H@hD-H_&EZiRNsfk7mjBq{L%!E;Sqn!mVX*}kXhwH6eh;b42eD!*~upVG@ z#smUqz$ICm!Y8wY53gJeS|Iuard0=;k5i5Z_hSIs6tr)R4n*r*rE`>38Pw&lkv{_r!jNN=;#?WbMj|l>cU(9trCq; z%nN~r^y7!kH^GPOf3R}?dDhO=v^3BeP5hF|%4GNQYBSwz;x({21i4OQY->1G=KFyu z&6d`f2tT9Yl_Z8YACZaJ#v#-(gcyeqXMhYGXb=t>)M@fFa8tHp2x;ODX=Ap@a5I=U z0G80^$N0G4=U(>W%mrrThl0DjyQ-_I>+1Tdd_AuB3qpYAqY54upwa3}owa|x5iQ^1 zEf|iTZxKNGRpI>34EwkIQ2zHDEZ=(J@lRaOH>F|2Z%V_t56Km$PUYu^xA5#5Uj4I4RGqHD56xT%H{+P8Ag>e_3pN$4m8n>i%OyJFPNWaEnJ4McUZPa1QmOh?t8~n& z&RulPCors8wUaqMHECG=IhB(-tU2XvHP6#NrLVyKG%Ee*mQ5Ps%wW?mcnriTVRc4J`2YVM>$ixSF2Xi+Wn(RUZnV?mJ?GRdw%lhZ+t&3s7g!~g{%m&i<6 z5{ib-<==DYG93I(yhyv4jp*y3#*WNuDUf6`vTM%c&hiayf(%=x@4$kJ!W4MtYcE#1 zHM?3xw63;L%x3drtd?jot!8u3qeqctceX3m;tWetK+>~q7Be$h>n6riK(5@ujLgRS zvOym)k+VAtyV^mF)$29Y`nw&ijdg~jYpkx%*^ z8dz`C*g=I?;clyi5|!27e2AuSa$&%UyR(J3W!A=ZgHF9OuKA34I-1U~pyD!KuRkjA zbkN!?MfQOeN>DUPBxoy5IX}@vw`EEB->q!)8fRl_mqUVuRu|C@KD-;yl=yKc=ZT0% zB$fMwcC|HE*0f8+PVlWHi>M`zfsA(NQFET?LrM^pPcw`cK+Mo0%8*x8@65=CS_^$cG{GZQ#xv($7J z??R$P)nPLodI;P!IC3eEYEHh7TV@opr#*)6A-;EU2XuogHvC;;k1aI8asq7ovoP!* z?x%UoPrZjj<&&aWpsbr>J$Er-7!E(BmOyEv!-mbGQGeJm-U2J>74>o5x`1l;)+P&~ z>}f^=Rx(ZQ2bm+YE0u=ZYrAV@apyt=v1wb?R@`i_g64YyAwcOUl=C!i>=Lzb$`tjv zOO-P#A+)t-JbbotGMT}arNhJmmGl-lyUpMn=2UacVZxmiG!s!6H39@~&uVokS zG=5qWhfW-WOI9g4!R$n7!|ViL!|v3G?GN6HR0Pt_L5*>D#FEj5wM1DScz4Jv@Sxnl zB@MPPmdI{(2D?;*wd>3#tjAirmUnQoZrVv`xM3hARuJksF(Q)wd4P$88fGYOT1p6U z`AHSN!`St}}UMBT9o7i|G`r$ zrB=s$qV3d6$W9@?L!pl0lf%)xs%1ko^=QY$ty-57=55PvP(^6E7cc zGJ*>m2=;fOj?F~yBf@K@9qwX0hA803Xw+b0m}+#a(>RyR8}*Y<4b+kpp|OS+!whP( zH`v{%s>jsQI9rd$*vm)EkwOm#W_-rLTHcZRek)>AtF+~<(did)*oR1|&~1|e36d-d zgtm5cv1O0oqgWC%Et@P4Vhm}Ndl(Y#C^MD03g#PH-TFy+7!Osv1z^UWS9@%JhswEq~6kSr2DITo59+; ze=ZC}i2Q?CJ~Iyu?vn|=9iKV>4j8KbxhE4&!@SQ^dVa-gK@YfS9xT(0kpW*EDjYUkoj! zE49{7H&E}k%5(>sM4uGY)Q*&3>{aitqdNnRJkbOmD5Mp5rv-hxzOn80QsG=HJ_atI-EaP69cacR)Uvh{G5dTpYG7d zbtmRMq@Sexey)||UpnZ?;g_KMZq4IDCy5}@u!5&B^-=6yyY{}e4Hh3ee!ZWtL*s?G zxG(A!<9o!CL+q?u_utltPMk+hn?N2@?}xU0KlYg?Jco{Yf@|mSGC<(Zj^yHCvhmyx z?OxOYoxbptDK()tsJ42VzXdINAMWL$0Gcw?G(g8TMB)Khw_|v9`_ql#pRd2i*?CZl z7k1b!jQB=9-V@h%;Cnl7EKi;Y^&NhU0mWEcj8B|3L30Ku#-9389Q+(Yet0r$F=+3p z6AKOMAIi|OHyzlHZtOm73}|ntKtFaXF2Fy|M!gOh^L4^62kGUoWS1i{9gsds_GWBc zLw|TaLP64z3z9?=R2|T6Xh2W4_F*$cq>MtXMOy&=IPIJ`;!Tw?PqvI2b*U1)25^<2 zU_ZPoxg_V0tngA0J+mm?3;OYw{i2Zb4x}NedZug!>EoN3DC{1i)Z{Z4m*(y{ov2%- zk(w>+scOO}MN!exSc`TN)!B=NUX`zThWO~M*ohqq;J2hx9h9}|s#?@eR!=F{QTrq~ zTcY|>azkCe$|Q0XFUdpFT=lTcyW##i;-e{}ORB4D?t@SfqGo_cS z->?^rh$<&n9DL!CF+h?LMZRi)qju!meugvxX*&jfD!^1XB3?E?HnwHP8$;uX{Rvp# zh|)hM>XDv$ZGg=$1{+_bA~u-vXqlw6NH=nkpyWE0u}LQjF-3NhATL@9rRxMnpO%f7 z)EhZf{PF|mKIMFxnC?*78(}{Y)}iztV12}_OXffJ;ta!fcFIVjdchyHxH=t%ci`Xd zX2AUB?%?poD6Zv*&BA!6c5S#|xn~DK01#XvjT!w!;&`lDXSJT4_j$}!qSPrb37vc{ z9^NfC%QvPu@vlxaZ;mIbn-VHA6miwi8qJ~V;pTZkKqqOii<1Cs}0i?uUIss;hM4dKq^1O35y?Yp=l4i zf{M!@QHH~rJ&X~8uATV><23zZUbs-J^3}$IvV_ANLS08>k`Td7aU_S1sLsfi*C-m1 z-e#S%UGs4E!;CeBT@9}aaI)qR-6NU@kvS#0r`g&UWg?fC7|b^_HyCE!8}nyh^~o@< zpm7PDFs9yxp+byMS(JWm$NeL?DNrMCNE!I^ko-*csB+dsf4GAq{=6sfyf4wb>?v1v zmb`F*bN1KUx-`ra1+TJ37bXNP%`-Fd`vVQFTwWpX@;s(%nDQa#oWhgk#mYlY*!d>( zE&!|ySF!mIyfING+#%RDY3IBH_fW$}6~1%!G`suHub1kP@&DoAd5~7J55;5_noPI6eLf{t;@9Kf<{aO0`1WNKd?<)C-|?C?)3s z>wEq@8=I$Wc~Mt$o;g++5qR+(6wt9GI~pyrDJ%c?gPZe)owvy^J2S=+M^ z&WhIE`g;;J^xQLVeCtf7b%Dg#Z2gq9hp_%g)-%_`y*zb; zn9`f`mUPN-Ts&fFo(aNTsXPA|J!TJ{0hZp0^;MYHLOcD=r_~~^ymS8KLCSeU3;^QzJNqS z5{5rEAv#l(X?bvwxpU;2%pQftF`YFgrD1jt2^~Mt^~G>T*}A$yZc@(k9orlCGv&|1 zWWvVgiJsCAtamuAYT~nzs?TQFt<1LSEx!@e0~@yd6$b5!Zm(FpBl;(Cn>2vF?k zOm#TTjFwd2D-CyA!mqR^?#Uwm{NBemP>(pHmM}9;;8`c&+_o3#E5m)JzfwN?(f-a4 zyd%xZc^oQx3XT?vcCqCX&Qrk~nu;fxs@JUoyVoi5fqpi&bUhQ2y!Ok2pzsFR(M(|U zw3E+kH_zmTRQ9dUMZWRE%Zakiwc+lgv7Z%|YO9YxAy`y28`Aw;WU6HXBgU7fl@dnt z-fFBV)}H-gqP!1;V@Je$WcbYre|dRdp{xt!7sL3Eoa%IA`5CAA%;Wq8PktwPdULo! z8!sB}Qt8#jH9Sh}QiUtEPZ6H0b*7qEKGJ%ITZ|vH)5Q^2m<7o3#Z>AKc%z7_u`rXA zqrCy{-{8;9>dfllLu$^M5L z-hXs))h*qz%~ActwkIA(qOVBZl2v4lwbM>9l70Y`+T*elINFqt#>OaVWoja8RMsep z6Or3f=oBnA3vDbn*+HNZP?8LsH2MY)x%c13@(XfuGR}R?Nu<|07{$+Lc3$Uv^I!MQ z>6qWgd-=aG2Y^24g4{Bw9ueOR)(9h`scImD=86dD+MnSN4$6 z^U*o_mE-6Rk~Dp!ANp#5RE9n*LG(Vg`1)g6!(XtDzsov$Dvz|Gv1WU68J$CkshQhS zCrc|cdkW~UK}5NeaWj^F4MSgFM+@fJd{|LLM)}_O<{rj z+?*Lm?owq?IzC%U%9EBga~h-cJbIu=#C}XuWN>OLrc%M@Gu~kFEYUi4EC6l#PR2JS zQUkGKrrS#6H7}2l0F@S11DP`@pih0WRkRJl#F;u{c&ZC{^$Z+_*lB)r)-bPgRFE;* zl)@hK4`tEP=P=il02x7-C7p%l=B`vkYjw?YhdJU9!P!jcmY$OtC^12w?vy3<<=tlY zUwHJ_0lgWN9vf>1%WACBD{UT)1qHQSE2%z|JHvP{#INr13jM}oYv_5#xsnv9`)UAO zuwgyV4YZ;O)eSc3(mka6=aRohi!HH@I#xq7kng?Acdg7S4vDJb6cI5fw?2z%3yR+| zU5v@Hm}vy;${cBp&@D=HQ9j7NcFaOYL zj-wV=eYF{|XTkFNM2uz&T8uH~;)^Zo!=KP)EVyH6s9l1~4m}N%XzPpduPg|h-&lL` zAXspR0YMOKd2yO)eMFFJ4?sQ&!`dF&!|niH*!^*Ml##o0M(0*uK9&yzekFi$+mP9s z>W9d%Jb)PtVi&-Ha!o~Iyh@KRuKpQ@)I~L*d`{O8!kRObjO7=n+Gp36fe!66neh+7 zW*l^0tTKjLLzr`x4`_8&on?mjW-PzheTNox8Hg7Nt@*SbE-%kP2hWYmHu#Fn@Q^J(SsPUz*|EgOoZ6byg3ew88UGdZ>9B2Tq=jF72ZaR=4u%1A6Vm{O#?@dD!(#tmR;eP(Fu z{$0O%=Vmua7=Gjr8nY%>ul?w=FJ76O2js&17W_iq2*tb!i{pt#`qZB#im9Rl>?t?0c zicIC}et_4d+CpVPx)i4~$u6N-QX3H77ez z?ZdvXifFk|*F8~L(W$OWM~r`pSk5}#F?j_5u$Obu9lDWIknO^AGu+Blk7!9Sb;NjS zncZA?qtASdNtzQ>z7N871IsPAk^CC?iIL}+{K|F@BuG2>qQ;_RUYV#>hHO(HUPpk@ z(bn~4|F_jiZi}Sad;_7`#4}EmD<1EiIxa48QjUuR?rC}^HRocq`OQPM@aHVKP9E#q zy%6bmHygCpIddPjE}q_DPC`VH_2m;Eey&ZH)E6xGeStOK7H)#+9y!%-Hm|QF6w#A( zIC0Yw%9j$s-#odxG~C*^MZ?M<+&WJ+@?B_QPUyTg9DJGtQN#NIC&-XddRsf3n^AL6 zT@P|H;PvN;ZpL0iv$bRb7|J{0o!Hq+S>_NrH4@coZtBJu#g8#CbR7|#?6uxi8d+$g z87apN>EciJZ`%Zv2**_uiET9Vk{pny&My;+WfGDw4EVL#B!Wiw&M|A8f1A@ z(yFQS6jfbH{b8Z-S7D2?Ixl`j0{+ZnpT=;KzVMLW{B$`N?Gw^Fl0H6lT61%T2AU**!sX0u?|I(yoy&Xveg7XBL&+>n6jd1##6d>TxE*Vj=8lWiG$4=u{1UbAa5QD>5_ z;Te^42v7K6Mmu4IWT6Rnm>oxrl~b<~^e3vbj-GCdHLIB_>59}Ya+~OF68NiH=?}2o zP(X7EN=quQn&)fK>M&kqF|<_*H`}c zk=+x)GU>{Af#vx&s?`UKUsz})g^Pc&?Ka@t5$n$bqf6{r1>#mWx6Ep>9|A}VmWRnowVo`OyCr^fHsf# zQjQ3Ttp7y#iQY8l`zEUW)(@gGQdt(~rkxlkefskT(t%@i8=|p1Y9Dc5bc+z#n$s13 zGJk|V0+&Ekh(F};PJzQKKo+FG@KV8a<$gmNSD;7rd_nRdc%?9)p!|B-@P~kxQG}~B zi|{0}@}zKC(rlFUYp*dO1RuvPC^DQOkX4<+EwvBAC{IZQdYxoq1Za!MW7%p7gGr=j zzWnAq%)^O2$eItftC#TTSArUyL$U54-O7e|)4_7%Q^2tZ^0-d&3J1}qCzR4dWX!)4 zzIEKjgnYgMus^>6uw4Jm8ga6>GBtMjpNRJ6CP~W=37~||gMo_p@GA@#-3)+cVYnU> zE5=Y4kzl+EbEh%dhQokB{gqNDqx%5*qBusWV%!iprn$S!;oN_6E3?0+umADVs4ako z?P+t?m?};gev9JXQ#Q&KBpzkHPde_CGu-y z<{}RRAx=xlv#mVi+Ibrgx~ujW$h{?zPfhz)Kp7kmYS&_|97b&H&1;J-mzrBWAvY} zh8-I8hl_RK2+nnf&}!W0P+>5?#?7>npshe<1~&l_xqKd0_>dl_^RMRq@-Myz&|TKZBj1=Q()) zF{dBjv5)h=&Z)Aevx}+i|7=R9rG^Di!sa)sZCl&ctX4&LScQ-kMncgO(9o6W6)yd< z@Rk!vkja*X_N3H=BavGoR0@u0<}m-7|2v!0+2h~S2Q&a=lTH91OJsvms2MT~ zY=c@LO5i`mLpBd(vh|)I&^A3TQLtr>w=zoyzTd=^f@TPu&+*2MtqE$Avf>l>}V|3-8Fp2hzo3y<)hr_|NO(&oSD z!vEjTWBxbKTiShVl-U{n*B3#)3a8$`{~Pk}J@elZ=>Pqp|MQ}jrGv7KrNcjW%TN_< zZz8kG{#}XoeWf7qY?D)L)8?Q-b@Na&>i=)(@uNo zr;cH98T3$Iau8Hn*@vXi{A@YehxDE2zX~o+RY`)6-X{8~hMpc#C`|8y> zU8Mnv5A0dNCf{Ims*|l-^ z(MRp{qoGohB34|ggDI*p!Aw|MFyJ|v+<+E3brfrI)|+l3W~CQLPbnF@G0)P~Ly!1TJLp}xh8uW`Q+RB-v`MRYZ9Gam3cM%{ zb4Cb*f)0deR~wtNb*8w-LlIF>kc7DAv>T0D(a3@l`k4TFnrO+g9XH7;nYOHxjc4lq zMmaW6qpgAgy)MckYMhl?>sq;-1E)-1llUneeA!ya9KM$)DaNGu57Z5aE>=VST$#vb zFo=uRHr$0M{-ha>h(D_boS4zId;3B|Tpqo|?B?Z@I?G(?&Iei+-{9L_A9=h=Qfn-U z1wIUnQe9!z%_j$F_{rf&`ZFSott09gY~qrf@g3O=Y>vzAnXCyL!@(BqWa)Zqt!#_k zfZHuwS52|&&)aK;CHq9V-t9qt0au{$#6c*R#e5n3rje0hic7c7m{kW$p(_`wB=Gw7 z4k`1Hi;Mc@yA7dp@r~?@rfw)TkjAW++|pkfOG}0N|2guek}j8Zen(!+@7?qt_7ndX zB=BG6WJ31#F3#Vk3=aQr8T)3`{=p9nBHlKzE0I@v`{vJ}h8pd6vby&VgFhzH|q;=aonunAXL6G2y(X^CtAhWr*jI zGjpY@raZDQkg*aMq}Ni6cRF z{oWv}5`nhSAv>usX}m^GHt`f(t8@zHc?K|y5Zi=4G*UG1Sza{$Dpj%X8 zzEXaKT5N6F5j4J|w#qlZP!zS7BT)9b+!ZSJdToqJts1c!)fwih4d31vfb{}W)EgcA zH2pZ^8_k$9+WD2n`6q5XbOy8>3pcYH9 z07eUB+p}YD@AH!}p!iKv><2QF-Y^&xx^PAc1F13A{nUeCDg&{hnix#FiO!fe(^&%Qcux!h znu*S!s$&nnkeotYsDthh1dq(iQrE|#f_=xVgfiiL&-5eAcC-> z5L0l|DVEM$#ulf{bj+Y~7iD)j<~O8CYM8GW)dQGq)!mck)FqoL^X zwNdZb3->hFrbHFm?hLvut-*uK?zXn3q1z|UX{RZ;-WiLoOjnle!xs+W0-8D)kjU#R z+S|A^HkRg$Ij%N4v~k`jyHffKaC~=wg=9)V5h=|kLQ@;^W!o2^K+xG&2n`XCd>OY5Ydi= zgHH=lgy++erK8&+YeTl7VNyVm9-GfONlSlVb3)V9NW5tT!cJ8d7X)!b-$fb!s76{t z@d=Vg-5K_sqHA@Zx-L_}wVnc@L@GL9_K~Zl(h5@AR#FAiKad8~KeWCo@mgXIQ#~u{ zgYFwNz}2b6Vu@CP0XoqJ+dm8px(5W5-Jpis97F`+KM)TuP*X8H@zwiVKDKGVp59pI zifNHZr|B+PG|7|Y<*tqap0CvG7tbR1R>jn70t1X`XJixiMVcHf%Ez*=xm1(CrTSDt z0cle!+{8*Ja&EOZ4@$qhBuKQ$U95Q%rc7tg$VRhk?3=pE&n+T3upZg^ZJc9~c2es% zh7>+|mrmA-p&v}|OtxqmHIBgUxL~^0+cpfkSK2mhh+4b=^F1Xgd2)}U*Yp+H?ls#z zrLxWg_hm}AfK2XYWr!rzW4g;+^^&bW%LmbtRai9f3PjU${r@n`JThy-cphbcwn)rq9{A$Ht`lmYKxOacy z6v2R(?gHhD5@&kB-Eg?4!hAoD7~(h>(R!s1c1Hx#s9vGPePUR|of32bS`J5U5w{F) z>0<^ktO2UHg<0{oxkdOQ;}coZDQph8p6ruj*_?uqURCMTac;>T#v+l1Tc~%^k-Vd@ zkc5y35jVNc49vZpZx;gG$h{%yslDI%Lqga1&&;mN{Ush1c7p>7e-(zp}6E7f-XmJb4nhk zb8zS+{IVbL$QVF8pf8}~kQ|dHJAEATmmnrb_wLG}-yHe>W|A&Y|;muy-d^t^<&)g5SJfaTH@P1%euONny=mxo+C z4N&w#biWY41r8k~468tvuYVh&XN&d#%QtIf9;iVXfWY)#j=l`&B~lqDT@28+Y!0E+MkfC}}H*#(WKKdJJq=O$vNYCb(ZG@p{fJgu;h z21oHQ(14?LeT>n5)s;uD@5&ohU!@wX8w*lB6i@GEH0pM>YTG+RAIWZD;4#F1&F%Jp zXZUml2sH0!lYJT?&sA!qwez6cXzJEd(1ZC~kT5kZSp7(@=H2$Azb_*W&6aA|9iwCL zdX7Q=42;@dspHDwYE?miGX#L^3xD&%BI&fN9^;`v4OjQXPBaBmOF1;#C)8XA(WFlH zycro;DS2?(G&6wkr6rqC>rqDv3nfGw3hmN_9Al>TgvmGsL8_hXx09};l9Ow@)F5@y z#VH5WigLDwZE4nh^7&@g{1FV^UZ%_LJ-s<{HN*2R$OPg@R~Z`c-ET*2}XB@9xvAjrK&hS=f|R8Gr9 zr|0TGOsI7RD+4+2{ZiwdVD@2zmg~g@^D--YL;6UYGSM8i$NbQr4!c7T9rg!8;TM0E zT#@?&S=t>GQm)*ua|?TLT2ktj#`|R<_*FAkOu2Pz$wEc%-=Y9V*$&dg+wIei3b*O8 z2|m$!jJG!J!ZGbbIa!(Af~oSyZV+~M1qGvelMzPNE_%5?c2>;MeeG2^N?JDKjFYCy z7SbPWH-$cWF9~fX%9~v99L!G(wi!PFp>rB!9xj7=Cv|F+7CsGNwY0Q_J%FID%C^CBZQfJ9K(HK%k31j~e#&?hQ zNuD6gRkVckU)v+53-fc} z7ZCzYN-5RG4H7;>>Hg?LU9&5_aua?A0)0dpew1#MMlu)LHe(M;OHjHIUl7|%%)YPo z0cBk;AOY00%Fe6heoN*$(b<)Cd#^8Iu;-2v@>cE-OB$icUF9EEoaC&q8z9}jMTT2I z8`9;jT%z0;dy4!8U;GW{i`)3!c6&oWY`J3669C!tM<5nQFFrFRglU8f)5Op$GtR-3 zn!+SPCw|04sv?%YZ(a7#L?vsdr7ss@WKAw&A*}-1S|9~cL%uA+E~>N6QklFE>8W|% zyX-qAUGTY1hQ-+um`2|&ji0cY*(qN!zp{YpDO-r>jPk*yuVSay<)cUt`t@&FPF_&$ zcHwu1(SQ`I-l8~vYyUxm@D1UEdFJ$f5Sw^HPH7b!9 zzYT3gKMF((N(v0#4f_jPfVZ=ApN^jQJe-X$`A?X+vWjLn_%31KXE*}5_}d8 zw_B1+a#6T1?>M{ronLbHIlEsMf93muJ7AH5h%;i99<~JX^;EAgEB1uHralD*!aJ@F zV2ruuFe9i2Q1C?^^kmVy921eb=tLDD43@-AgL^rQ3IO9%+vi_&R2^dpr}x{bCVPej z7G0-0o64uyWNtr*loIvslyo0%)KSDDKjfThe0hcqs)(C-MH1>bNGBDRTW~scy_{w} zp^aq8Qb!h9Lwielq%C1b8=?Z=&U)ST&PHbS)8Xzjh2DF?d{iAv)Eh)wsUnf>UtXN( zL7=$%YrZ#|^c{MYmhn!zV#t*(jdmYdCpwqpZ{v&L8KIuKn`@IIZfp!uo}c;7J57N` zAxyZ-uA4=Gzl~Ovycz%MW9ZL7N+nRo&1cfNn9(1H5eM;V_4Z_qVann7F>5f>%{rf= zPBZFaV@_Sobl?Fy&KXyzFDV*FIdhS5`Uc~S^Gjo)aiTHgn#<0C=9o-a-}@}xDor;D zZyZ|fvf;+=3MZd>SR1F^F`RJEZo+|MdyJYQAEauKu%WDol~ayrGU3zzbHKsnHKZ*z zFiwUkL@DZ>!*x05ql&EBq@_Vqv83&?@~q5?lVmffQZ+V-=qL+!u4Xs2Z2zdCQ3U7B&QR9_Iggy} z(om{Y9eU;IPe`+p1ifLx-XWh?wI)xU9ik+m#g&pGdB5Bi<`PR*?92lE0+TkRuXI)z z5LP!N2+tTc%cB6B1F-!fj#}>S!vnpgVU~3!*U1ej^)vjUH4s-bd^%B=ItQqDCGbrEzNQi(dJ`J}-U=2{7-d zK8k^Rlq2N#0G?9&1?HSle2vlkj^KWSBYTwx`2?9TU_DX#J+f+qLiZCqY1TXHFxXZqYMuD@RU$TgcnCC{_(vwZ-*uX)~go#%PK z@}2Km_5aQ~(<3cXeJN6|F8X_1@L%@xTzs}$_*E|a^_URF_qcF;Pfhoe?FTFwvjm1o z8onf@OY@jC2tVcMaZS;|T!Ks(wOgPpRzRnFS-^RZ4E!9dsnj9sFt609a|jJbb1Dt@ z<=Gal2jDEupxUSwWu6zp<<&RnAA;d&4gKVG0iu6g(DsST(4)z6R)zDpfaQ}v{5ARt zyhwvMtF%b-YazR5XLz+oh=mn;y-Mf2a8>7?2v8qX;19y?b>Z5laGHvzH;Nu9S`B8} zI)qN$GbXIQ1VL3lnof^6TS~rvPVg4V?Dl2Bb*K2z4E{5vy<(@@K_cN@U>R!>aUIRnb zL*)=787*cs#zb31zBC49x$`=fkQbMAef)L2$dR{)6BAz!t5U_B#1zZG`^neKSS22oJ#5B=gl%U=WeqL9REF2g zZnfCb0?quf?Ztj$VXvDSWoK`0L=Zxem2q}!XWLoT-kYMOx)!7fcgT35uC~0pySEme z`{wGWTkGr7>+Kb^n;W?BZH6ZP(9tQX%-7zF>vc2}LuWDI(9kh1G#7B99r4x6;_-V+k&c{nPUrR zAXJGRiMe~aup{0qzmLNjS_BC4cB#sXjckx{%_c&^xy{M61xEb>KW_AG5VFXUOjAG4 z^>Qlm9A#1N{4snY=(AmWzatb!ngqiqPbBZ7>Uhb3)dTkSGcL#&SH>iMO-IJBPua`u zo)LWZ>=NZLr758j{%(|uQuZ)pXq_4c!!>s|aDM9#`~1bzK3J1^^D#<2bNCccH7~-X}Ggi!pIIF>uFx%aPARGQsnC8ZQc8lrQ5o~smqOg>Ti^GNme94*w z)JZy{_{#$jxGQ&`M z!OMvZMHR>8*^>eS%o*6hJwn!l8VOOjZQJvh)@tnHVW&*GYPuxqXw}%M!(f-SQf`=L z5;=5w2;%82VMH6Xi&-K3W)o&K^+vJCepWZ-rW%+Dc6X3(){z$@4zjYxQ|}8UIojeC zYZpQ1dU{fy=oTr<4VX?$q)LP}IUmpiez^O&N3E_qPpchGTi5ZM6-2ScWlQq%V&R2Euz zO|Q0Hx>lY1Q1cW5xHv5!0OGU~PVEqSuy#fD72d#O`N!C;o=m+YioGu-wH2k6!t<~K zSr`E=W9)!g==~x9VV~-8{4ZN9{~-A9zJpRe%NGg$+MDuI-dH|b@BD)~>pPCGUNNzY zMDg||0@XGQgw`YCt5C&A{_+J}mvV9Wg{6V%2n#YSRN{AP#PY?1FF1#|vO_%e+#`|2*~wGAJaeRX6=IzFNeWhz6gJc8+(03Ph4y6ELAm=AkN7TOgMUEw*N{= z_)EIDQx5q22oUR+_b*tazu9+pX|n1c*IB-}{DqIj z-?E|ks{o3AGRNb;+iKcHkZvYJvFsW&83RAPs1Oh@IWy%l#5x2oUP6ZCtv+b|q>jsf zZ_9XO;V!>n`UxH1LvH8)L4?8raIvasEhkpQoJ`%!5rBs!0Tu(s_D{`4opB;57)pkX z4$A^8CsD3U5*!|bHIEqsn~{q+Ddj$ME@Gq4JXtgVz&7l{Ok!@?EA{B3P~NAqb9)4? zkQo30A^EbHfQ@87G5&EQTd`frrwL)&Yw?%-W@uy^Gn23%j?Y!Iea2xw<-f;esq zf%w5WN@E1}zyXtYv}}`U^B>W`>XPmdLj%4{P298|SisrE;7HvXX;A}Ffi8B#3Lr;1 zHt6zVb`8{#+e$*k?w8|O{Uh|&AG}|DG1PFo1i?Y*cQm$ZwtGcVgMwtBUDa{~L1KT-{jET4w60>{KZ27vXrHJ;fW{6| z=|Y4!&UX020wU1>1iRgB@Q#m~1^Z^9CG1LqDhYBrnx%IEdIty z!46iOoKlKs)c}newDG)rWUikD%j`)p z_w9Ph&e40=(2eBy;T!}*1p1f1SAUDP9iWy^u^Ubdj21Kn{46;GR+hwLO=4D11@c~V zI8x&(D({K~Df2E)Nx_yQvYfh4;MbMJ@Z}=Dt3_>iim~QZ*hZIlEs0mEb z_54+&*?wMD`2#vsQRN3KvoT>hWofI_Vf(^C1ff-Ike@h@saEf7g}<9T`W;HAne-Nd z>RR+&SP35w)xKn8^U$7))PsM!jKwYZ*RzEcG-OlTrX3}9a{q%#Un5E5W{{hp>w~;` zGky+3(vJvQyGwBo`tCpmo0mo((?nM8vf9aXrrY1Ve}~TuVkB(zeds^jEfI}xGBCM2 zL1|#tycSaWCurP+0MiActG3LCas@_@tao@(R1ANlwB$4K53egNE_;!&(%@Qo$>h`^1S_!hN6 z)vZtG$8fN!|BXBJ=SI>e(LAU(y(i*PHvgQ2llulxS8>qsimv7yL}0q_E5WiAz7)(f zC(ahFvG8&HN9+6^jGyLHM~$)7auppeWh_^zKk&C_MQ~8;N??OlyH~azgz5fe^>~7F zl3HnPN3z-kN)I$4@`CLCMQx3sG~V8hPS^}XDXZrQA>}mQPw%7&!sd(Pp^P=tgp-s^ zjl}1-KRPNWXgV_K^HkP__SR`S-|OF0bR-N5>I%ODj&1JUeAQ3$9i;B~$S6}*^tK?= z**%aCiH7y?xdY?{LgVP}S0HOh%0%LI$wRx;$T|~Y8R)Vdwa}kGWv8?SJVm^>r6+%I z#lj1aR94{@MP;t-scEYQWc#xFA30^}?|BeX*W#9OL;Q9#WqaaM546j5j29((^_8Nu z4uq}ESLr~r*O7E7$D{!k9W>`!SLoyA53i9QwRB{!pHe8um|aDE`Cg0O*{jmor)^t)3`>V>SWN-2VJcFmj^1?~tT=JrP`fVh*t zXHarp=8HEcR#vFe+1a%XXuK+)oFs`GDD}#Z+TJ}Ri`FvKO@ek2ayn}yaOi%(8p%2$ zpEu)v0Jym@f}U|-;}CbR=9{#<^z28PzkkTNvyKvJDZe+^VS2bES3N@Jq!-*}{oQlz z@8bgC_KnDnT4}d#&Cpr!%Yb?E!brx0!eVOw~;lLwUoz#Np%d$o%9scc3&zPm`%G((Le|6o1 zM(VhOw)!f84zG^)tZ1?Egv)d8cdNi+T${=5kV+j;Wf%2{3g@FHp^Gf*qO0q!u$=m9 zCaY`4mRqJ;FTH5`a$affE5dJrk~k`HTP_7nGTY@B9o9vvnbytaID;^b=Tzp7Q#DmD zC(XEN)Ktn39z5|G!wsVNnHi) z%^q94!lL|hF`IijA^9NR0F$@h7k5R^ljOW(;Td9grRN0Mb)l_l7##{2nPQ@?;VjXv zaLZG}yuf$r$<79rVPpXg?6iiieX|r#&`p#Con2i%S8*8F}(E) zI5E6c3tG*<;m~6>!&H!GJ6zEuhH7mkAzovdhLy;)q z{H2*8I^Pb}xC4s^6Y}6bJvMu=8>g&I)7!N!5QG$xseeU#CC?ZM-TbjsHwHgDGrsD= z{%f;@Sod+Ch66Ko2WF~;Ty)v>&x^aovCbCbD7>qF*!?BXmOV3(s|nxsb*Lx_2lpB7 zokUnzrk;P=T-&kUHO}td+Zdj!3n&NR?K~cRU zAXU!DCp?51{J4w^`cV#ye}(`SQhGQkkMu}O3M*BWt4UsC^jCFUy;wTINYmhD$AT;4 z?Xd{HaJjP`raZ39qAm;%beDbrLpbRf(mkKbANan7XsL>_pE2oo^$TgdidjRP!5-`% zv0d!|iKN$c0(T|L0C~XD0aS8t{*&#LnhE;1Kb<9&=c2B+9JeLvJr*AyyRh%@jHej=AetOMSlz^=!kxX>>B{2B1uIrQyfd8KjJ+DBy!h)~*(!|&L4^Q_07SQ~E zcemVP`{9CwFvPFu7pyVGCLhH?LhEVb2{7U+Z_>o25#+3<|8%1T^5dh}*4(kfJGry} zm%r#hU+__Z;;*4fMrX=Bkc@7|v^*B;HAl0((IBPPii%X9+u3DDF6%bI&6?Eu$8&aWVqHIM7mK6?Uvq$1|(-T|)IV<>e?!(rY zqkmO1MRaLeTR=)io(0GVtQT@s6rN%C6;nS3@eu;P#ry4q;^O@1ZKCJyp_Jo)Ty^QW z+vweTx_DLm{P-XSBj~Sl<%_b^$=}odJ!S2wAcxenmzFGX1t&Qp8Vxz2VT`uQsQYtdn&_0xVivIcxZ_hnrRtwq4cZSj1c-SG9 z7vHBCA=fd0O1<4*=lu$6pn~_pVKyL@ztw1swbZi0B?spLo56ZKu5;7ZeUml1Ws1?u zqMf1p{5myAzeX$lAi{jIUqo1g4!zWLMm9cfWcnw`k6*BR^?$2(&yW?>w;G$EmTA@a z6?y#K$C~ZT8+v{87n5Dm&H6Pb_EQ@V0IWmG9cG=O;(;5aMWWrIPzz4Q`mhK;qQp~a z+BbQrEQ+w{SeiuG-~Po5f=^EvlouB@_|4xQXH@A~KgpFHrwu%dwuCR)=B&C(y6J4J zvoGk9;lLs9%iA-IJGU#RgnZZR+@{5lYl8(e1h6&>Vc_mvg0d@);X zji4T|n#lB!>pfL|8tQYkw?U2bD`W{na&;*|znjmalA&f;*U++_aBYerq;&C8Kw7mI z7tsG*?7*5j&dU)Lje;^{D_h`%(dK|pB*A*1(Jj)w^mZ9HB|vGLkF1GEFhu&rH=r=8 zMxO42e{Si6$m+Zj`_mXb&w5Q(i|Yxyg?juUrY}78uo@~3v84|8dfgbPd0iQJRdMj< zncCNGdMEcsxu#o#B5+XD{tsg*;j-eF8`mp~K8O1J!Z0+>0=7O=4M}E?)H)ENE;P*F z$Ox?ril_^p0g7xhDUf(q652l|562VFlC8^r8?lQv;TMvn+*8I}&+hIQYh2 z1}uQQaag&!-+DZ@|C+C$bN6W;S-Z@)d1|en+XGvjbOxCa-qAF*LA=6s(Jg+g;82f$ z(Vb)8I)AH@cdjGFAR5Rqd0wiNCu!xtqWbcTx&5kslzTb^7A78~Xzw1($UV6S^VWiP zFd{Rimd-0CZC_Bu(WxBFW7+k{cOW7DxBBkJdJ;VsJ4Z@lERQr%3eVv&$%)b%<~ zCl^Y4NgO}js@u{|o~KTgH}>!* z_iDNqX2(As7T0xivMH|3SC1ivm8Q}6Ffcd7owUKN5lHAtzMM4<0v+ykUT!QiowO;`@%JGv+K$bBx@*S7C8GJVqQ_K>12}M`f_Ys=S zKFh}HM9#6Izb$Y{wYzItTy+l5U2oL%boCJn?R3?jP@n$zSIwlmyGq30Cw4QBO|14` zW5c);AN*J3&eMFAk$SR~2k|&+&Bc$e>s%c{`?d~85S-UWjA>DS5+;UKZ}5oVa5O(N zqqc@>)nee)+4MUjH?FGv%hm2{IlIF-QX}ym-7ok4Z9{V+ZHVZQl$A*x!(q%<2~iVv znUa+BX35&lCb#9VE-~Y^W_f;Xhl%vgjwdjzMy$FsSIj&ok}L+X`4>J=9BkN&nu^E*gbhj3(+D>C4E z@Fwq_=N)^bKFSHTzZk?-gNU$@l}r}dwGyh_fNi=9b|n}J>&;G!lzilbWF4B}BBq4f zYIOl?b)PSh#XTPp4IS5ZR_2C!E)Z`zH0OW%4;&~z7UAyA-X|sh9@~>cQW^COA9hV4 zXcA6qUo9P{bW1_2`eo6%hgbN%(G-F1xTvq!sc?4wN6Q4`e9Hku zFwvlAcRY?6h^Fj$R8zCNEDq8`=uZB8D-xn)tA<^bFFy}4$vA}Xq0jAsv1&5!h!yRA zU()KLJya5MQ`q&LKdH#fwq&(bNFS{sKlEh_{N%{XCGO+po#(+WCLmKW6&5iOHny>g z3*VFN?mx!16V5{zyuMWDVP8U*|BGT$(%IO|)?EF|OI*sq&RovH!N%=>i_c?K*A>>k zyg1+~++zY4Q)J;VWN0axhoIKx;l&G$gvj(#go^pZskEVj8^}is3Jw26LzYYVos0HX zRPvmK$dVxM8(Tc?pHFe0Z3uq){{#OK3i-ra#@+;*=ui8)y6hsRv z4Fxx1c1+fr!VI{L3DFMwXKrfl#Q8hfP@ajgEau&QMCxd{g#!T^;ATXW)nUg&$-n25 zruy3V!!;{?OTobo|0GAxe`Acn3GV@W=&n;~&9 zQM>NWW~R@OYORkJAo+eq1!4vzmf9K%plR4(tB@TR&FSbDoRgJ8qVcH#;7lQub*nq&?Z>7WM=oeEVjkaG zT#f)=o!M2DO5hLR+op>t0CixJCIeXH*+z{-XS|%jx)y(j&}Wo|3!l7{o)HU3m7LYyhv*xF&tq z%IN7N;D4raue&&hm0xM=`qv`+TK@;_xAcGKuK(2|75~ar2Yw)geNLSmVxV@x89bQu zpViVKKnlkwjS&&c|-X6`~xdnh}Ps)Hs z4VbUL^{XNLf7_|Oi>tA%?SG5zax}esF*FH3d(JH^Gvr7Rp*n=t7frH!U;!y1gJB^i zY_M$KL_}mW&XKaDEi9K-wZR|q*L32&m+2n_8lq$xRznJ7p8}V>w+d@?uB!eS3#u<} zIaqi!b!w}a2;_BfUUhGMy#4dPx>)_>yZ`ai?Rk`}d0>~ce-PfY-b?Csd(28yX22L% zI7XI>OjIHYTk_@Xk;Gu^F52^Gn6E1&+?4MxDS2G_#PQ&yXPXP^<-p|2nLTb@AAQEY zI*UQ9Pmm{Kat}wuazpjSyXCdnrD&|C1c5DIb1TnzF}f4KIV6D)CJ!?&l&{T)e4U%3HTSYqsQ zo@zWB1o}ceQSV)<4G<)jM|@@YpL+XHuWsr5AYh^Q{K=wSV99D~4RRU52FufmMBMmd z_H}L#qe(}|I9ZyPRD6kT>Ivj&2Y?qVZq<4bG_co_DP`sE*_Xw8D;+7QR$Uq(rr+u> z8bHUWbV19i#)@@G4bCco@Xb<8u~wVDz9S`#k@ciJtlu@uP1U0X?yov8v9U3VOig2t zL9?n$P3=1U_Emi$#slR>N5wH-=J&T=EdUHA}_Z zZIl3nvMP*AZS9{cDqFanrA~S5BqxtNm9tlu;^`)3X&V4tMAkJ4gEIPl= zoV!Gyx0N{3DpD@)pv^iS*dl2FwANu;1;%EDl}JQ7MbxLMAp>)UwNwe{=V}O-5C*>F zu?Ny+F64jZn<+fKjF01}8h5H_3pey|;%bI;SFg$w8;IC<8l|3#Lz2;mNNik6sVTG3 z+Su^rIE#40C4a-587$U~%KedEEw1%r6wdvoMwpmlXH$xPnNQN#f%Z7|p)nC>WsuO= z4zyqapLS<8(UJ~Qi9d|dQijb_xhA2)v>la)<1md5s^R1N&PiuA$^k|A<+2C?OiHbj z>Bn$~t)>Y(Zb`8hW7q9xQ=s>Rv81V+UiuZJc<23HplI88isqRCId89fb`Kt|CxVIg znWcwprwXnotO>3s&Oypkte^9yJjlUVVxSe%_xlzmje|mYOVPH^vjA=?6xd0vaj0Oz zwJ4OJNiFdnHJX3rw&inskjryukl`*fRQ#SMod5J|KroJRsVXa5_$q7whSQ{gOi*s0 z1LeCy|JBWRsDPn7jCb4s(p|JZiZ8+*ExC@Vj)MF|*Vp{B(ziccSn`G1Br9bV(v!C2 z6#?eqpJBc9o@lJ#^p-`-=`4i&wFe>2)nlPK1p9yPFzJCzBQbpkcR>={YtamIw)3nt z(QEF;+)4`>8^_LU)_Q3 zC5_7lgi_6y>U%m)m@}Ku4C}=l^J=<<7c;99ec3p{aR+v=diuJR7uZi%aQv$oP?dn?@6Yu_+*^>T0ptf(oobdL;6)N-I!TO`zg^Xbv3#L0I~sn@WGk-^SmPh5>W+LB<+1PU}AKa?FCWF|qMNELOgdxR{ zbqE7@jVe+FklzdcD$!(A$&}}H*HQFTJ+AOrJYnhh}Yvta(B zQ_bW4Rr;R~&6PAKwgLWXS{Bnln(vUI+~g#kl{r+_zbngT`Y3`^Qf=!PxN4IYX#iW4 zucW7@LLJA9Zh3(rj~&SyN_pjO8H&)|(v%!BnMWySBJV=eSkB3YSTCyIeJ{i;(oc%_hk{$_l;v>nWSB)oVeg+blh=HB5JSlG_r7@P z3q;aFoZjD_qS@zygYqCn=;Zxjo!?NK!%J$ z52lOP`8G3feEj+HTp@Tnn9X~nG=;tS+z}u{mQX_J0kxtr)O30YD%oo)L@wy`jpQYM z@M>Me=95k1p*FW~rHiV1CIfVc{K8r|#Kt(ApkXKsDG$_>76UGNhHExFCw#Ky9*B-z zNq2ga*xax!HMf_|Vp-86r{;~YgQKqu7%szk8$hpvi_2I`OVbG1doP(`gn}=W<8%Gn z%81#&WjkH4GV;4u43EtSW>K_Ta3Zj!XF?;SO3V#q=<=>Tc^@?A`i;&`-cYj|;^ zEo#Jl5zSr~_V-4}y8pnufXLa80vZY4z2ko7fj>DR)#z=wWuS1$$W!L?(y}YC+yQ|G z@L&`2upy3f>~*IquAjkVNU>}c10(fq#HdbK$~Q3l6|=@-eBbo>B9(6xV`*)sae58*f zym~RRVx;xoCG3`JV`xo z!lFw)=t2Hy)e!IFs?0~7osWk(d%^wxq&>_XD4+U#y&-VF%4z?XH^i4w`TxpF{`XhZ z%G}iEzf!T(l>g;W9<~K+)$g!{UvhW{E0Lis(S^%I8OF&%kr!gJ&fMOpM=&=Aj@wuL zBX?*6i51Qb$uhkwkFYkaD_UDE+)rh1c;(&Y=B$3)J&iJfQSx!1NGgPtK!$c9OtJuu zX(pV$bfuJpRR|K(dp@^j}i&HeJOh@|7lWo8^$*o~Xqo z5Sb+!EtJ&e@6F+h&+_1ETbg7LfP5GZjvIUIN3ibCOldAv z)>YdO|NH$x7AC8dr=<2ekiY1%fN*r~e5h6Yaw<{XIErujKV~tiyrvV_DV0AzEknC- zR^xKM3i<1UkvqBj3C{wDvytOd+YtDSGu!gEMg+!&|8BQrT*|p)(dwQLEy+ zMtMzij3zo40)CA!BKZF~yWg?#lWhqD3@qR)gh~D{uZaJO;{OWV8XZ_)J@r3=)T|kt zUS1pXr6-`!Z}w2QR7nP%d?ecf90;K_7C3d!UZ`N(TZoWNN^Q~RjVhQG{Y<%E1PpV^4 z-m-K+$A~-+VDABs^Q@U*)YvhY4Znn2^w>732H?NRK(5QSS$V@D7yz2BVX4)f5A04~$WbxGOam22>t&uD)JB8-~yiQW6ik;FGblY_I>SvB_z2?PS z*Qm&qbKI{H1V@YGWzpx`!v)WeLT02};JJo*#f$a*FH?IIad-^(;9XC#YTWN6;Z6+S zm4O1KH=#V@FJw7Pha0!9Vb%ZIM$)a`VRMoiN&C|$YA3~ZC*8ayZRY^fyuP6$n%2IU z$#XceYZeqLTXw(m$_z|33I$B4k~NZO>pP6)H_}R{E$i%USGy{l{-jOE;%CloYPEU+ zRFxOn4;7lIOh!7abb23YKD+_-?O z0FP9otcAh+oSj;=f#$&*ExUHpd&e#bSF%#8*&ItcL2H$Sa)?pt0Xtf+t)z$_u^wZi z44oE}r4kIZGy3!Mc8q$B&6JqtnHZ>Znn!Zh@6rgIu|yU+zG8q`q9%B18|T|oN3zMq z`l&D;U!OL~%>vo&q0>Y==~zLiCZk4v%s_7!9DxQ~id1LLE93gf*gg&2$|hB#j8;?3 z5v4S;oM6rT{Y;I+#FdmNw z){d%tNM<<#GN%n9ox7B=3#;u7unZ~tLB_vRZ52a&2=IM)2VkXm=L+Iqq~uk#Dug|x z>S84e+A7EiOY5lj*!q?6HDkNh~0g;0Jy(al!ZHHDtur9T$y-~)94HelX1NHjXWIM7UAe}$?jiz z9?P4`I0JM=G5K{3_%2jPLC^_Mlw?-kYYgb7`qGa3@dn|^1fRMwiyM@Ch z;CB&o7&&?c5e>h`IM;Wnha0QKnEp=$hA8TJgR-07N~U5(>9vJzeoFsSRBkDq=x(YgEMpb=l4TDD`2 zwVJpWGTA_u7}?ecW7s6%rUs&NXD3+n;jB86`X?8(l3MBo6)PdakI6V6a}22{)8ilT zM~T*mU}__xSy|6XSrJ^%lDAR3Lft%+yxC|ZUvSO_nqMX!_ul3;R#*{~4DA=h$bP)%8Yv9X zyp><|e8=_ttI}ZAwOd#dlnSjck#6%273{E$kJuCGu=I@O)&6ID{nWF5@gLb16sj|&Sb~+du4e4O_%_o`Ix4NRrAsyr1_}MuP94s>de8cH-OUkVPk3+K z&jW)It9QiU-ti~AuJkL`XMca8Oh4$SyJ=`-5WU<{cIh+XVH#e4d&zive_UHC!pN>W z3TB;Mn5i)9Qn)#6@lo4QpI3jFYc0~+jS)4AFz8fVC;lD^+idw^S~Qhq>Tg(!3$yLD zzktzoFrU@6s4wwCMz}edpF5i5Q1IMmEJQHzp(LAt)pgN3&O!&d?3W@6U4)I^2V{;- z6A(?zd93hS*uQmnh4T)nHnE{wVhh(=MMD(h(P4+^p83Om6t<*cUW>l(qJzr%5vp@K zN27ka(L{JX=1~e2^)F^i=TYj&;<7jyUUR2Bek^A8+3Up*&Xwc{)1nRR5CT8vG>ExV zHnF3UqXJOAno_?bnhCX-&kwI~Ti8t4`n0%Up>!U`ZvK^w2+0Cs-b9%w%4`$+To|k= zKtgc&l}P`*8IS>8DOe?EB84^kx4BQp3<7P{Pq}&p%xF_81pg!l2|u=&I{AuUgmF5n zJQCTLv}%}xbFGYtKfbba{CBo)lWW%Z>i(_NvLhoQZ*5-@2l&x>e+I~0Nld3UI9tdL zRzu8}i;X!h8LHVvN?C+|M81e>Jr38%&*9LYQec9Ax>?NN+9(_>XSRv&6hlCYB`>Qm z1&ygi{Y()OU4@D_jd_-7vDILR{>o|7-k)Sjdxkjgvi{@S>6GqiF|o`*Otr;P)kLHN zZkpts;0zw_6;?f(@4S1FN=m!4^mv~W+lJA`&7RH%2$)49z0A+8@0BCHtj|yH--AEL z0tW6G%X-+J+5a{5*WKaM0QDznf;V?L5&uQw+yegDNDP`hA;0XPYc6e0;Xv6|i|^F2WB)Z$LR|HR4 zTQsRAby9(^Z@yATyOgcfQw7cKyr^3Tz7lc7+JEwwzA7)|2x+PtEb>nD(tpxJQm)Kn zW9K_*r!L%~N*vS8<5T=iv|o!zTe9k_2jC_j*7ik^M_ zaf%k{WX{-;0*`t`G!&`eW;gChVXnJ-Rn)To8vW-?>>a%QU1v`ZC=U)f8iA@%JG0mZ zDqH;~mgBnrCP~1II<=V9;EBL)J+xzCoiRBaeH&J6rL!{4zIY8tZka?_FBeQeNO3q6 zyG_alW54Ba&wQf{&F1v-r1R6ID)PTsqjIBc+5MHkcW5Fnvi~{-FjKe)t1bl}Y;z@< z=!%zvpRua>>t_x}^}z0<7MI!H2v6|XAyR9!t50q-A)xk0nflgF4*OQlCGK==4S|wc zRMsSscNhRzHMBU8TdcHN!q^I}x0iXJ%uehac|Zs_B$p@CnF)HeXPpB_Za}F{<@6-4 zl%kml@}kHQ(ypD8FsPJ2=14xXJE|b20RUIgs!2|R3>LUMGF6X*B_I|$`Qg=;zm7C z{mEDy9dTmPbued7mlO@phdmAmJ7p@GR1bjCkMw6*G7#4+`k>fk1czdJUB!e@Q(~6# zwo%@p@V5RL0ABU2LH7Asq^quDUho@H>eTZH9f*no9fY0T zD_-9px3e}A!>>kv5wk91%C9R1J_Nh!*&Kk$J3KNxC}c_@zlgpJZ+5L)Nw|^p=2ue}CJtm;uj*Iqr)K})kA$xtNUEvX;4!Px*^&9T_`IN{D z{6~QY=Nau6EzpvufB^hflc#XIsSq0Y9(nf$d~6ZwK}fal92)fr%T3=q{0mP-EyP_G z)UR5h@IX}3Qll2b0oCAcBF>b*@Etu*aTLPU<%C>KoOrk=x?pN!#f_Og-w+;xbFgjQ zXp`et%lDBBh~OcFnMKMUoox0YwBNy`N0q~bSPh@+enQ=4RUw1) zpovN`QoV>vZ#5LvC;cl|6jPr}O5tu!Ipoyib8iXqy}TeJ;4+_7r<1kV0v5?Kv>fYp zg>9L`;XwXa&W7-jf|9~uP2iyF5`5AJ`Q~p4eBU$MCC00`rcSF>`&0fbd^_eqR+}mK z4n*PMMa&FOcc)vTUR zlDUAn-mh`ahi_`f`=39JYTNVjsTa_Y3b1GOIi)6dY)D}xeshB0T8Eov5%UhWd1)u}kjEQ|LDo{tqKKrYIfVz~@dp!! zMOnah@vp)%_-jDTUG09l+;{CkDCH|Q{NqX*uHa1YxFShy*1+;J`gywKaz|2Q{lG8x zP?KBur`}r`!WLKXY_K;C8$EWG>jY3UIh{+BLv0=2)KH%P}6xE2kg)%(-uA6lC?u8}{K(#P*c zE9C8t*u%j2r_{;Rpe1A{9nNXU;b_N0vNgyK!EZVut~}+R2rcbsHilqsOviYh-pYX= zHw@53nlmwYI5W5KP>&`dBZe0Jn?nAdC^HY1wlR6$u^PbpB#AS&5L6zqrXN&7*N2Q` z+Rae1EwS)H=aVSIkr8Ek^1jy2iS2o7mqm~Mr&g5=jjt7VxwglQ^`h#Mx+x2v|9ZAwE$i_9918MjJxTMr?n!bZ6n$}y11u8I9COTU`Z$Fi z!AeAQLMw^gp_{+0QTEJrhL424pVDp%wpku~XRlD3iv{vQ!lAf!_jyqd_h}+Tr1XG| z`*FT*NbPqvHCUsYAkFnM`@l4u_QH&bszpUK#M~XLJt{%?00GXY?u_{gj3Hvs!=N(I z(=AuWPijyoU!r?aFTsa8pLB&cx}$*%;K$e*XqF{~*rA-qn)h^!(-;e}O#B$|S~c+U zN4vyOK0vmtx$5K!?g*+J@G1NmlEI=pyZXZ69tAv=@`t%ag_Hk{LP~OH9iE)I= zaJ69b4kuCkV0V zo(M0#>phpQ_)@j;h%m{-a*LGi(72TP)ws2w*@4|C-3+;=5DmC4s7Lp95%n%@Ko zfdr3-a7m*dys9iIci$A=4NPJ`HfJ;hujLgU)ZRuJI`n;Pw|yksu!#LQnJ#dJysgNb z@@qwR^wrk(jbq4H?d!lNyy72~Dnn87KxsgQ!)|*m(DRM+eC$wh7KnS-mho3|KE)7h zK3k;qZ;K1Lj6uEXLYUYi)1FN}F@-xJ z@@3Hb84sl|j{4$3J}aTY@cbX@pzB_qM~APljrjju6P0tY{C@ zpUCOz_NFmALMv1*blCcwUD3?U6tYs+N%cmJ98D%3)%)Xu^uvzF zS5O!sc#X6?EwsYkvPo6A%O8&y8sCCQH<%f2togVwW&{M;PR!a(ZT_A+jVAbf{@5kL zB@Z(hb$3U{T_}SKA_CoQVU-;j>2J=L#lZ~aQCFg-d<9rzs$_gO&d5N6eFSc z1ml8)P*FSi+k@!^M9nDWR5e@ATD8oxtDu=36Iv2!;dZzidIS(PCtEuXAtlBb1;H%Z zwnC^Ek*D)EX4#Q>R$$WA2sxC_t(!!6Tr?C#@{3}n{<^o;9id1RA&-Pig1e-2B1XpG zliNjgmd3c&%A}s>qf{_j#!Z`fu0xIwm4L0)OF=u(OEmp;bLCIaZX$&J_^Z%4Sq4GZ zPn6sV_#+6pJmDN_lx@1;Zw6Md_p0w9h6mHtzpuIEwNn>OnuRSC2=>fP^Hqgc)xu^4 z<3!s`cORHJh#?!nKI`Et7{3C27+EuH)Gw1f)aoP|B3y?fuVfvpYYmmukx0ya-)TQX zR{ggy5cNf4X|g)nl#jC9p>7|09_S7>1D2GTRBUTW zAkQ=JMRogZqG#v;^=11O6@rPPwvJkr{bW-Qg8`q8GoD#K`&Y+S#%&B>SGRL>;ZunM@49!}Uy zN|bBCJ%sO;@3wl0>0gbl3L@1^O60ONObz8ZI7nder>(udj-jt`;yj^nTQ$L9`OU9W zX4alF#$|GiR47%x@s&LV>2Sz2R6?;2R~5k6V>)nz!o_*1Y!$p>BC5&?hJg_MiE6UBy>RkVZj`9UWbRkN-Hk!S`=BS3t3uyX6)7SF#)71*}`~Ogz z1rap5H6~dhBJ83;q-Y<5V35C2&F^JI-it(=5D#v!fAi9p#UwV~2tZQI+W(Dv?1t9? zfh*xpxxO{-(VGB>!Q&0%^YW_F!@aZS#ucP|YaD#>wd1Fv&Z*SR&mc;asi}1G) z_H>`!akh-Zxq9#io(7%;a$)w+{QH)Y$?UK1Dt^4)up!Szcxnu}kn$0afcfJL#IL+S z5gF_Y30j;{lNrG6m~$Ay?)*V9fZuU@3=kd40=LhazjFrau>(Y>SJNtOz>8x_X-BlA zIpl{i>OarVGj1v(4?^1`R}aQB&WCRQzS~;7R{tDZG=HhgrW@B`W|#cdyj%YBky)P= zpxuOZkW>S6%q7U{VsB#G(^FMsH5QuGXhb(sY+!-R8Bmv6Sx3WzSW<1MPPN1!&PurYky(@`bP9tz z52}LH9Q?+FF5jR6-;|+GVdRA!qtd;}*-h&iIw3Tq3qF9sDIb1FFxGbo&fbG5n8$3F zyY&PWL{ys^dTO}oZ#@sIX^BKW*bon=;te9j5k+T%wJ zNJtoN1~YVj4~YRrlZl)b&kJqp+Z`DqT!la$x&&IxgOQw#yZd-nBP3!7FijBXD|IsU8Zl^ zc6?MKpJQ+7ka|tZQLfchD$PD|;K(9FiLE|eUZX#EZxhG!S-63C$jWX1Yd!6-Yxi-u zjULIr|0-Q%D9jz}IF~S%>0(jOqZ(Ln<$9PxiySr&2Oic7vb<8q=46)Ln%Z|<*z5&> z3f~Zw@m;vR(bESB<=Jqkxn(=#hQw42l(7)h`vMQQTttz9XW6^|^8EK7qhju4r_c*b zJIi`)MB$w@9epwdIfnEBR+?~);yd6C(LeMC& zn&&N*?-g&BBJcV;8&UoZi4Lmxcj16ojlxR~zMrf=O_^i1wGb9X-0@6_rpjPYemIin zmJb+;lHe;Yp=8G)Q(L1bzH*}I>}uAqhj4;g)PlvD9_e_ScR{Ipq|$8NvAvLD8MYr}xl=bU~)f%B3E>r3Bu9_t|ThF3C5~BdOve zEbk^r&r#PT&?^V1cb{72yEWH}TXEE}w>t!cY~rA+hNOTK8FAtIEoszp!qqptS&;r$ zaYV-NX96-h$6aR@1xz6_E0^N49mU)-v#bwtGJm)ibygzJ8!7|WIrcb`$XH~^!a#s& z{Db-0IOTFq#9!^j!n_F}#Z_nX{YzBK8XLPVmc&X`fT7!@$U-@2KM9soGbmOSAmqV z{nr$L^MBo_u^Joyf0E^=eo{Rt0{{e$IFA(#*kP@SQd6lWT2-#>` zP1)7_@IO!9lk>Zt?#CU?cuhiLF&)+XEM9B)cS(gvQT!X3`wL*{fArTS;Ak`J<84du zALKPz4}3nlG8Fo^MH0L|oK2-4xIY!~Oux~1sw!+It)&D3p;+N8AgqKI`ld6v71wy8I!eP0o~=RVcFQR2Gr(eP_JbSytoQ$Yt}l*4r@A8Me94y z8cTDWhqlq^qoAhbOzGBXv^Wa4vUz$(7B!mX`T=x_ueKRRDfg&Uc-e1+z4x$jyW_Pm zp?U;-R#xt^Z8Ev~`m`iL4*c#65Nn)q#=Y0l1AuD&+{|8-Gsij3LUZXpM0Bx0u7WWm zH|%yE@-#XEph2}-$-thl+S;__ciBxSSzHveP%~v}5I%u!z_l_KoW{KRx2=eB33umE zIYFtu^5=wGU`Jab8#}cnYry@9p5UE#U|VVvx_4l49JQ;jQdp(uw=$^A$EA$LM%vmE zvdEOaIcp5qX8wX{mYf0;#51~imYYPn4=k&#DsKTxo{_Mg*;S495?OBY?#gv=edYC* z^O@-sd-qa+U24xvcbL0@C7_6o!$`)sVr-jSJE4XQUQ$?L7}2(}Eixqv;L8AdJAVqc zq}RPgpnDb@E_;?6K58r3h4-!4rT4Ab#rLHLX?eMOfluJk=3i1@Gt1i#iA=O`M0@x! z(HtJP9BMHXEzuD93m|B&woj0g6T?f#^)>J>|I4C5?Gam>n9!8CT%~aT;=oco5d6U8 zMXl(=W;$ND_8+DD*?|5bJ!;8ebESXMUKBAf7YBwNVJibGaJ*(2G`F%wx)grqVPjudiaq^Kl&g$8A2 zWMxMr@_$c}d+;_B`#kUX-t|4VKH&_f^^EP0&=DPLW)H)UzBG%%Tra*5 z%$kyZe3I&S#gfie^z5)!twG={3Cuh)FdeA!Kj<-9** zvT*5%Tb`|QbE!iW-XcOuy39>D3oe6x{>&<#E$o8Ac|j)wq#kQzz|ATd=Z0K!p2$QE zPu?jL8Lb^y3_CQE{*}sTDe!2!dtlFjq&YLY@2#4>XS`}v#PLrpvc4*@q^O{mmnr5D zmyJq~t?8>FWU5vZdE(%4cuZuao0GNjp3~Dt*SLaxI#g_u>hu@k&9Ho*#CZP~lFJHj z(e!SYlLigyc?&5-YxlE{uuk$9b&l6d`uIlpg_z15dPo*iU&|Khx2*A5Fp;8iK_bdP z?T6|^7@lcx2j0T@x>X7|kuuBSB7<^zeY~R~4McconTxA2flHC0_jFxmSTv-~?zVT| zG_|yDqa9lkF*B6_{j=T>=M8r<0s;@z#h)3BQ4NLl@`Xr__o7;~M&dL3J8fP&zLfDfy z);ckcTev{@OUlZ`bCo(-3? z1u1xD`PKgSg?RqeVVsF<1SLF;XYA@Bsa&cY!I48ZJn1V<3d!?s=St?TLo zC0cNr`qD*M#s6f~X>SCNVkva^9A2ZP>CoJ9bvgXe_c}WdX-)pHM5m7O zrHt#g$F0AO+nGA;7dSJ?)|Mo~cf{z2L)Rz!`fpi73Zv)H=a5K)*$5sf_IZypi($P5 zsPwUc4~P-J1@^3C6-r9{V-u0Z&Sl7vNfmuMY4yy*cL>_)BmQF!8Om9Dej%cHxbIzA zhtV0d{=%cr?;bpBPjt@4w=#<>k5ee=TiWAXM2~tUGfm z$s&!Dm0R^V$}fOR*B^kGaipi~rx~A2cS0;t&khV1a4u38*XRUP~f za!rZMtay8bsLt6yFYl@>-y^31(*P!L^^s@mslZy(SMsv9bVoX`O#yBgEcjCmGpyc* zeH$Dw6vB5P*;jor+JOX@;6K#+xc)Z9B8M=x2a@Wx-{snPGpRmOC$zpsqW*JCh@M2Y z#K+M(>=#d^>Of9C`))h<=Bsy)6zaMJ&x-t%&+UcpLjV`jo4R2025 zXaG8EA!0lQa)|dx-@{O)qP6`$rhCkoQqZ`^SW8g-kOwrwsK8 z3ms*AIcyj}-1x&A&vSq{r=QMyp3CHdWH35!sad#!Sm>^|-|afB+Q;|Iq@LFgqIp#Z zD1%H+3I?6RGnk&IFo|u+E0dCxXz4yI^1i!QTu7uvIEH>i3rR{srcST`LIRwdV1P;W z+%AN1NIf@xxvVLiSX`8ILA8MzNqE&7>%jMzGt9wm78bo9<;h*W84i29^w!>V>{N+S zd`5Zmz^G;f=icvoOZfK5#1ctx*~UwD=ab4DGQXehQ!XYnak*dee%YN$_ZPL%KZuz$ zD;$PpT;HM^$KwtQm@7uvT`i6>Hae1CoRVM2)NL<2-k2PiX=eAx+-6j#JI?M}(tuBW zkF%jjLR)O`gI2fcPBxF^HeI|DWwQWHVR!;;{BXXHskxh8F@BMDn`oEi-NHt;CLymW z=KSv5)3dyzec0T5B*`g-MQ<;gz=nIWKUi9ko<|4I(-E0k$QncH>E4l z**1w&#={&zv4Tvhgz#c29`m|;lU-jmaXFMC11 z*dlXDMEOG>VoLMc>!rApwOu2prKSi*!w%`yzGmS+k(zm*CsLK*wv{S_0WX^8A-rKy zbk^Gf_92^7iB_uUF)EE+ET4d|X|>d&mdN?x@vxKAQk`O+r4Qdu>XGy(a(19g;=jU} zFX{O*_NG>!$@jh!U369Lnc+D~qch3uT+_Amyi}*k#LAAwh}k8IPK5a-WZ81ufD>l> z$4cF}GSz>ce`3FAic}6W4Z7m9KGO?(eWqi@L|5Hq0@L|&2flN1PVl}XgQ2q*_n2s3 zt5KtowNkTYB5b;SVuoXA@i5irXO)A&%7?V`1@HGCB&)Wgk+l|^XXChq;u(nyPB}b3 zY>m5jkxpZgi)zfbgv&ec4Zqdvm+D<?Im*mXweS9H+V>)zF#Zp3)bhl$PbISY{5=_z!8&*Jv~NYtI-g!>fDs zmvL5O^U%!^VaKA9gvKw|5?-jk>~%CVGvctKmP$kpnpfN{D8@X*Aazi$txfa%vd-|E z>kYmV66W!lNekJPom29LdZ%(I+ZLZYTXzTg*to~m?7vp%{V<~>H+2}PQ?PPAq`36R z<%wR8v6UkS>Wt#hzGk#44W<%9S=nBfB);6clKwnxY}T*w21Qc3_?IJ@4gYzC7s;WP zVQNI(M=S=JT#xsZy7G`cR(BP9*je0bfeN8JN5~zY(DDs0t{LpHOIbN);?T-69Pf3R zSNe*&p2%AwXHL>__g+xd4Hlc_vu<25H?(`nafS%)3UPP7_4;gk-9ckt8SJRTv5v0M z_Hww`qPudL?ajIR&X*;$y-`<)6dxx1U~5eGS13CB!lX;3w7n&lDDiArbAhSycd}+b zya_3p@A`$kQy;|NJZ~s44Hqo7Hwt}X86NK=(ey>lgWTtGL6k@Gy;PbO!M%1~Wcn2k zUFP|*5d>t-X*RU8g%>|(wwj*~#l4z^Aatf^DWd1Wj#Q*AY0D^V@sC`M zjJc6qXu0I7Y*2;;gGu!plAFzG=J;1%eIOdn zQA>J&e05UN*7I5@yRhK|lbBSfJ+5Uq;!&HV@xfPZrgD}kE*1DSq^=%{o%|LChhl#0 zlMb<^a6ixzpd{kNZr|3jTGeEzuo}-eLT-)Q$#b{!vKx8Tg}swCni>{#%vDY$Ww$84 zew3c9BBovqb}_&BRo#^!G(1Eg((BScRZ}C)Oz?y`T5wOrv);)b^4XR8 zhJo7+<^7)qB>I;46!GySzdneZ>n_E1oWZY;kf94#)s)kWjuJN1c+wbVoNQcmnv}{> zN0pF+Sl3E}UQ$}slSZeLJrwT>Sr}#V(dVaezCQl2|4LN`7L7v&siYR|r7M(*JYfR$ zst3=YaDw$FSc{g}KHO&QiKxuhEzF{f%RJLKe3p*7=oo`WNP)M(9X1zIQPP0XHhY3c znrP{$4#Ol$A0s|4S7Gx2L23dv*Gv2o;h((XVn+9+$qvm}s%zi6nI-_s6?mG! zj{DV;qesJb&owKeEK?=J>UcAlYckA7Sl+I&IN=yasrZOkejir*kE@SN`fk<8Fgx*$ zy&fE6?}G)d_N`){P~U@1jRVA|2*69)KSe_}!~?+`Yb{Y=O~_+@!j<&oVQQMnhoIRU zA0CyF1OFfkK44n*JD~!2!SCPM;PRSk%1XL=0&rz00wxPs&-_eapJy#$h!eqY%nS0{ z!aGg58JIJPF3_ci%n)QSVpa2H`vIe$RD43;#IRfDV&Ibit z+?>HW4{2wOfC6Fw)}4x}i1maDxcE1qi@BS*qcxD2gE@h3#4cgU*D-&3z7D|tVZWt= z-Cy2+*Cm@P4GN_TPUtaVyVesbVDazF@)j8VJ4>XZv!f%}&eO1SvIgr}4`A*3#vat< z_MoByL(qW6L7SFZ#|Gc1fFN)L2PxY+{B8tJp+pxRyz*87)vXR}*=&ahXjBlQKguuf zX6x<<6fQulE^C*KH8~W%ptpaC0l?b=_{~*U4?5Vt;dgM4t_{&UZ1C2j?b>b+5}{IF_CUyvz-@QZPMlJ)r_tS$9kH%RPv#2_nMb zRLj5;chJ72*U`Z@Dqt4$@_+k$%|8m(HqLG!qT4P^DdfvGf&){gKnGCX#H0!;W=AGP zbA&Z`-__a)VTS}kKFjWGk z%|>yE?t*EJ!qeQ%dPk$;xIQ+P0;()PCBDgjJm6Buj{f^awNoVx+9<|lg3%-$G(*f) zll6oOkN|yamn1uyl2*N-lnqRI1cvs_JxLTeahEK=THV$Sz*gQhKNb*p0fNoda#-&F zB-qJgW^g}!TtM|0bS2QZekW7_tKu%GcJ!4?lObt0z_$mZ4rbQ0o=^curCs3bJK6sq z9fu-aW-l#>z~ca(B;4yv;2RZ?tGYAU)^)Kz{L|4oPj zdOf_?de|#yS)p2v8-N||+XL=O*%3+y)oI(HbM)Ds?q8~HPzIP(vs*G`iddbWq}! z(2!VjP&{Z1w+%eUq^ '} + 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 new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/gateway/EaglercraftXVelocity/gradlew.bat @@ -0,0 +1,89 @@ +@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/settings.gradle b/gateway/EaglercraftXVelocity/settings.gradle new file mode 100644 index 00000000..cd54735f --- /dev/null +++ b/gateway/EaglercraftXVelocity/settings.gradle @@ -0,0 +1,2 @@ +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 index 52a113f9..598a2d86 100644 --- 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 @@ -7,6 +7,7 @@ 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; @@ -19,6 +20,7 @@ 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.proxy.VelocityServer; import com.velocitypowered.proxy.network.ConnectionManager; import com.velocitypowered.proxy.network.TransportType; @@ -33,7 +35,10 @@ 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; @@ -45,6 +50,7 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVeloci 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; @@ -53,6 +59,7 @@ 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; /** * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. @@ -102,6 +109,7 @@ public class EaglerXVelocity { 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; @@ -116,16 +124,16 @@ public class EaglerXVelocity { dataDirAsPath = dataDirIn; dataDir = dataDirIn.toFile(); - openChannels = new LinkedList(); + 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().toString()); + 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().toString()); + EaglerXVelocity.logger().error("Eaglercraft could not bind port: {}", ch.channel().attr(EaglerPipeline.LOCAL_ADDRESS).get()); EaglerXVelocity.logger().error("Reason: {}", ch.cause().toString()); } } @@ -162,11 +170,17 @@ public class EaglerXVelocity { } 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()) { @@ -178,9 +192,12 @@ public class EaglerXVelocity { EaglerCommand.register(this, new CommandEaglerPurge(authConf.getEaglerCommandName())); } } - proxy.getChannelRegistrar().register(SkinService.CHANNEL, CapeServiceOffline.CHANNEL, - EaglerPipeline.UPDATE_CERT_CHANNEL, VoiceService.CHANNEL, - EaglerPacketEventListener.FNAW_SKIN_ENABLE_CHANNEL, EaglerPacketEventListener.GET_DOMAIN_CHANNEL); + 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(EaglerPacketEventListener.GET_DOMAIN_CHANNEL); if(closeInactiveConnections != null) { closeInactiveConnections.cancel(); @@ -253,11 +270,32 @@ public class EaglerXVelocity { }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; @@ -266,6 +304,10 @@ public class EaglerXVelocity { skinServiceTasks.cancel(); skinServiceTasks = null; } + if(updateServiceTasks != null) { + updateServiceTasks.cancel(); + updateServiceTasks = null; + } skinService.shutdown(); skinService = null; capeService.shutdown(); @@ -334,7 +376,7 @@ public class EaglerXVelocity { synchronized(openChannels) { for(Channel c : openChannels) { c.close().syncUninterruptibly(); - EaglerXVelocity.logger().info("Eaglercraft listener closed: " + c.attr(EaglerPipeline.LOCAL_ADDRESS).get().toString()); + EaglerXVelocity.logger().info("Eaglercraft listener closed: " + c.attr(EaglerPipeline.LOCAL_ADDRESS).get()); } openChannels.clear(); } 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 index b4746c16..78f912ea 100644 --- 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 @@ -17,13 +17,13 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity; */ public class EaglerXVelocityVersion { - public static final String NATIVE_VELOCITY_BUILD = "3.3.0-SNAPSHOT:9d25d309:b400"; + public static final String NATIVE_VELOCITY_BUILD = "3.3.0-SNAPSHOT:2016d148:b436"; 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.0.6"; + public static final String VERSION = "1.1.0"; public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" }; } 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 index fb3d151b..7ea705f3 100644 --- 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 @@ -1,9 +1,54 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; -import com.velocitypowered.api.proxy.Player; +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; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. @@ -22,8 +67,1001 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayer */ public class EaglerXVelocityAPIHelper { + public static EaglerXVelocity getEaglerXVelocity() { + return EaglerXVelocity.getEagler(); + } + public static EaglerPlayerData getEaglerHandle(Player player) { - return EaglerPipeline.getEaglerHandle(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; } } 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 new file mode 100644 index 00000000..ed4c9627 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumVoiceState.java @@ -0,0 +1,22 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; + +/** + * 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. + * + */ +public enum EnumVoiceState { + SERVER_DISABLE, + DISABLED, + ENABLED; +} 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 new file mode 100644 index 00000000..a20eae1b --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/EnumWebViewState.java @@ -0,0 +1,23 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; + +/** + * 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. + * + */ +public enum EnumWebViewState { + NOT_SUPPORTED, + SERVER_DISABLE, + CHANNEL_CLOSED, + CHANNEL_OPEN; +} 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 new file mode 100644 index 00000000..fb49b771 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/JSONLegacySerializer.java @@ -0,0 +1,27 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api; + +import com.velocitypowered.proxy.protocol.util.VelocityLegacyHoverEventSerializer; + +import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; + +/** + * 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. + * + */ +public class JSONLegacySerializer { + + public static final JSONComponentSerializer instance = JSONComponentSerializer.builder() + .legacyHoverEventSerializer(VelocityLegacyHoverEventSerializer.INSTANCE).build(); + +} 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 new file mode 100644 index 00000000..93dc533e --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/NotificationBadgeBuilder.java @@ -0,0 +1,361 @@ +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; + +/** + * 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. + * + */ +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) : ""; + System.out.println(bodyComp); + 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; + } + +} 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 new file mode 100644 index 00000000..2673c649 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftClientBrandEvent.java @@ -0,0 +1,87 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event; + +import java.net.InetAddress; + +import net.kyori.adventure.text.Component; + +/** + * 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. + * + */ +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; + } + +} 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 new file mode 100644 index 00000000..399db419 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftHandleAuthCookieEvent.java @@ -0,0 +1,205 @@ +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; + +/** + * 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. + * + */ +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; + } +} 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 index a489c804..4397606e 100644 --- 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 @@ -1,6 +1,7 @@ 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; @@ -28,17 +29,19 @@ public class EaglercraftHandleAuthPasswordEvent { } private final EaglerListenerConfig listener; - private final InetAddress authRemoteAddress; - private final String authOrigin; + 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 CharSequence authProfileUsername; + private String authProfileUsername; private UUID authProfileUUID; private String authRequestedServerRespose; private String authDeniedMessage = "Password Incorrect!"; @@ -50,10 +53,10 @@ public class EaglercraftHandleAuthPasswordEvent { private volatile boolean hasContinue = false; public EaglercraftHandleAuthPasswordEvent(EaglerListenerConfig listener, InetAddress authRemoteAddress, - String authOrigin, byte[] authUsername, byte[] authSaltingData, CharSequence authProfileUsername, - UUID authProfileUUID, byte[] authPasswordData, EaglercraftIsAuthRequiredEvent.AuthMethod eventAuthMethod, - String eventAuthMessage, Object authAttachment, String authRequestedServerRespose, - Consumer continueThread) { + 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; @@ -62,6 +65,8 @@ public class EaglercraftHandleAuthPasswordEvent { this.authProfileUsername = authProfileUsername; this.authProfileUUID = authProfileUUID; this.authPasswordData = authPasswordData; + this.enableCookies = enableCookies; + this.cookieData = cookieData; this.eventAuthMethod = eventAuthMethod; this.eventAuthMessage = eventAuthMessage; this.authAttachment = authAttachment; @@ -89,11 +94,23 @@ public class EaglercraftHandleAuthPasswordEvent { return authSaltingData; } - public CharSequence getProfileUsername() { + 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(CharSequence username) { + public void setProfileUsername(String username) { this.authProfileUsername = username; } 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 index 3bfd6b47..13f50d2d 100644 --- 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 @@ -6,7 +6,7 @@ import java.util.function.Consumer; import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerListenerConfig; /** - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. + * 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 @@ -52,6 +52,7 @@ public class EaglercraftIsAuthRequiredEvent { 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; @@ -116,6 +117,14 @@ public class EaglercraftIsAuthRequiredEvent { 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; } 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 index 2b99a607..392e0bb9 100644 --- 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 @@ -2,6 +2,8 @@ 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; + /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * @@ -19,13 +21,15 @@ import java.util.UUID; */ 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) { + public EaglercraftRegisterCapeEvent(String username, UUID uuid, Object authAttachment) { this.username = username; this.uuid = uuid; + this.authAttachment = authAttachment; } public String getUsername() { @@ -45,10 +49,13 @@ public class EaglercraftRegisterCapeEvent { 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[1 + tex.length]; + customTex = new byte[1174]; customTex[0] = (byte)2; - System.arraycopy(tex, 0, customTex, 1, tex.length); + EaglerXVelocityAPIHelper.convertCape32x32RGBAto23x17RGB(tex, 0, customTex, 1); } public void setForceUseCustomByPacket(byte[] packet) { @@ -58,4 +65,8 @@ public class EaglercraftRegisterCapeEvent { 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 index 38f172bd..6ebbd0f8 100644 --- 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 @@ -21,30 +21,29 @@ 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; - private String customURL = null; - public EaglercraftRegisterSkinEvent(String username, UUID uuid) { + 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; - customURL = null; } public void setForceUseLoginResultObjectTextures(boolean b) { useMojangProfileProperty = null; useLoginResultTextures = b; customTex = null; - customURL = null; } public void setForceUsePreset(int p) { @@ -56,9 +55,11 @@ public class EaglercraftRegisterSkinEvent { customTex[2] = (byte)(p >>> 16); customTex[3] = (byte)(p >>> 8); customTex[4] = (byte)(p & 0xFF); - customURL = null; } + /** + * @param tex raw 64x64 pixel RGBA texture (16384 bytes long) + */ public void setForceUseCustom(int model, byte[] tex) { useMojangProfileProperty = null; useLoginResultTextures = false; @@ -66,21 +67,12 @@ public class EaglercraftRegisterSkinEvent { customTex[0] = (byte)2; customTex[1] = (byte)model; System.arraycopy(tex, 0, customTex, 2, tex.length); - customURL = null; } public void setForceUseCustomByPacket(byte[] packet) { useMojangProfileProperty = null; useLoginResultTextures = false; customTex = packet; - customURL = null; - } - - public void setForceUseURL(String url) { - useMojangProfileProperty = null; - useLoginResultTextures = false; - customTex = null; - customURL = url; } public String getUsername() { @@ -103,8 +95,8 @@ public class EaglercraftRegisterSkinEvent { return customTex; } - public String getForceSetUseURL() { - return customURL; + public T getAuthAttachment() { + return (T)authAttachment; } } 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 new file mode 100644 index 00000000..7a94d102 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftRevokeSessionQueryEvent.java @@ -0,0 +1,90 @@ +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; + +/** + * 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. + * + */ +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; + } +} 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 new file mode 100644 index 00000000..70de8845 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftVoiceStatusChangeEvent.java @@ -0,0 +1,64 @@ +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; + +/** + * 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. + * + */ +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; + } + +} 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 new file mode 100644 index 00000000..6b23d5ae --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebSocketOpenEvent.java @@ -0,0 +1,66 @@ +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; + +/** + * 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. + * + */ +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; + } + +} 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 new file mode 100644 index 00000000..5505e294 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewChannelEvent.java @@ -0,0 +1,56 @@ +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; + +/** + * 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. + * + */ +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; + } + +} 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 new file mode 100644 index 00000000..a89d5821 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/api/event/EaglercraftWebViewMessageEvent.java @@ -0,0 +1,119 @@ +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; + +/** + * 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. + * + */ +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; + } + +} 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 index 4e2f0d47..d6647f17 100644 --- 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 @@ -3,6 +3,7 @@ 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; /** @@ -31,7 +32,7 @@ public interface MOTDConnection { long getConnectionTimestamp(); public default long getConnectionAge() { - return System.currentTimeMillis() - getConnectionTimestamp(); + return EaglerXVelocityAPIHelper.steadyTimeMillis() - getConnectionTimestamp(); } void sendToUser(); 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 index 3d8e1cda..2c74e8b8 100644 --- 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 @@ -5,6 +5,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; + /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. * @@ -28,7 +30,7 @@ public class AuthLoadingCache { private V instance; private CacheEntry(V instance) { - this.lastHit = System.currentTimeMillis(); + this.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); this.instance = instance; } @@ -49,7 +51,7 @@ public class AuthLoadingCache { private long cacheTimer; public AuthLoadingCache(CacheLoader provider, long cacheTTL) { - this.cacheMap = new HashMap(); + this.cacheMap = new HashMap<>(); this.provider = provider; this.cacheTTL = cacheTTL; } @@ -66,7 +68,7 @@ public class AuthLoadingCache { } return loaded; }else { - etr.lastHit = System.currentTimeMillis(); + etr.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); return etr.instance; } } @@ -90,7 +92,7 @@ public class AuthLoadingCache { } public void tick() { - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); if(millis - cacheTimer > (cacheTTL / 2L)) { cacheTimer = millis; synchronized(cacheMap) { 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 index 30d65d5f..a7489cb4 100644 --- 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 @@ -246,7 +246,7 @@ public class DefaultAuthSystem { 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.authLoadingCache = new AuthLoadingCache<>(new AccountLoader(), 120000l); this.secureRandom = new SecureRandom(); } @@ -338,7 +338,7 @@ public class DefaultAuthSystem { } } }catch(SQLException ex) { - EaglerXVelocity.logger().error("Could not update last login for \"{}\"", info.mojangUUID.toString(), ex); + EaglerXVelocity.logger().error("Could not update last login for \"{}\"", info.mojangUUID, ex); } event.setLoginAllowed(); @@ -538,7 +538,7 @@ public class DefaultAuthSystem { if(!playerName.equals(username)) { EaglerXVelocity.logger().info( "Player \"{}\" changed their username from \"{}\" to \"{}\", updating authentication database...", - uuid.toString(), username, playerName); + uuid, username, playerName); synchronized(updateMojangUsername) { updateMojangUsername.setString(1, playerName); updateMojangUsername.setString(2, uuidString); @@ -558,7 +558,7 @@ public class DefaultAuthSystem { } } }catch(SQLException ex) { - EaglerXVelocity.logger().error("Could not look up UUID \"{}\" in auth database!", uuid.toString(), ex); + EaglerXVelocity.logger().error("Could not look up UUID \"{}\" in auth database!", uuid, ex); } } if(isRegistered) { 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 new file mode 100644 index 00000000..4f215992 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/command/CommandClientBrand.java @@ -0,0 +1,82 @@ +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; + +/** + * 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. + * + */ +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)); + } + +} 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 index ca558bb2..1bb40f9e 100644 --- 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 @@ -47,8 +47,9 @@ public class CommandDomain extends EaglerCommand { var1.sendMessage(Component.text("That user is not using Eaglercraft", NamedTextColor.RED)); return; } - if(eagPlayer.origin != null) { - var1.sendMessage(Component.text("Domain of " + var2[0] + " is '" + eagPlayer.origin + "'", NamedTextColor.BLUE)); + 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)); } 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 index bac3809c..07dcf924 100644 --- 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 @@ -69,8 +69,14 @@ public class EaglerListenerConfig { for(int i = 0, l = serverMOTD.size(); i < l; ++i) { serverMOTD.set(i, ChatColor.translateAlternateColorCodes('&', serverMOTD.get(i))); } - boolean allowMOTD = config.getBoolean("allow_motd", false); - boolean allowQuery = config.getBoolean("allow_query", false); + boolean allowMOTD = config.getBoolean("allow_motd", true); + boolean allowQuery = config.getBoolean("allow_query", true); + 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); int cacheTTL = 7200; boolean cacheAnimation = false; @@ -97,8 +103,8 @@ public class EaglerListenerConfig { page404 = null; } List defaultIndex = Arrays.asList("index.html", "index.htm"); - List indexPageRaw = httpServerConf.getList("page_index_name", defaultIndex); - List indexPage = new ArrayList(indexPageRaw.size()); + 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); @@ -146,7 +152,8 @@ public class EaglerListenerConfig { cacheTrending, cachePortfolios); return new EaglerListenerConfig(hostv4, hostv6, maxPlayer, forwardIp, forwardIpHeader, redirectLegacyClientsTo, serverIcon, serverMOTD, allowMOTD, allowQuery, - cacheConfig, httpServer, enableVoiceChat, ratelimitIp, ratelimitLogin, ratelimitMOTD, ratelimitQuery); + allowV3, allowV4, defragSendDelay, cacheConfig, httpServer, enableVoiceChat, ratelimitIp, + ratelimitLogin, ratelimitMOTD, ratelimitQuery); } private final InetSocketAddress address; @@ -159,6 +166,9 @@ public class EaglerListenerConfig { private final List serverMOTD; private final boolean allowMOTD; private final boolean allowQuery; + private final boolean allowV3; + private final boolean allowV4; + private final int defragSendDelay; private final MOTDCacheConfiguration motdCacheConfig; private final HttpWebServer webServer; private boolean serverIconSet = false; @@ -170,9 +180,9 @@ public class EaglerListenerConfig { 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, MOTDCacheConfiguration motdCacheConfig, HttpWebServer webServer, + boolean forwardIp, String forwardIpHeader, String redirectLegacyClientsTo, String serverIcon, + List serverMOTD, boolean allowMOTD, boolean allowQuery, boolean allowV3, boolean allowV4, + int defragSendDelay, MOTDCacheConfiguration motdCacheConfig, HttpWebServer webServer, boolean enableVoiceChat, EaglerRateLimiter ratelimitIp, EaglerRateLimiter ratelimitLogin, EaglerRateLimiter ratelimitMOTD, EaglerRateLimiter ratelimitQuery) { this.address = address; @@ -185,6 +195,9 @@ public class EaglerListenerConfig { this.serverMOTD = serverMOTD; this.allowMOTD = allowMOTD; this.allowQuery = allowQuery; + this.allowV3 = allowV3; + this.allowV4 = allowV4; + this.defragSendDelay = defragSendDelay; this.motdCacheConfig = motdCacheConfig; this.webServer = webServer; this.enableVoiceChat = enableVoiceChat; @@ -247,7 +260,19 @@ public class EaglerListenerConfig { public boolean isAllowQuery() { return allowQuery; } - + + public boolean isAllowV3() { + return allowV3; + } + + public boolean isAllowV4() { + return allowV4; + } + + public int getDefragSendDelay() { + return defragSendDelay; + } + public HttpWebServer getWebServer() { return webServer; } 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 new file mode 100644 index 00000000..a71ef172 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/EaglerPauseMenuConfig.java @@ -0,0 +1,251 @@ +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; + +/** + * 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. + * + */ +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; + } + +} 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 index 24291dfb..015052aa 100644 --- 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 @@ -7,6 +7,7 @@ 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; /** @@ -95,7 +96,7 @@ public class EaglerRateLimiter { protected long cooldownTimestamp = 0l; protected RateLimitStatus rateLimit() { - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); tick(millis); if(lockoutTimestamp != 0l) { return RateLimitStatus.LOCKED_OUT; @@ -136,7 +137,7 @@ public class EaglerRateLimiter { } } - private final Map ratelimiters = new HashMap(); + private final Map ratelimiters = new HashMap<>(); public RateLimitStatus rateLimit(String addr) { addr = addr.toLowerCase(); @@ -156,7 +157,7 @@ public class EaglerRateLimiter { } public void tick() { - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); synchronized(ratelimiters) { Iterator itr = ratelimiters.values().iterator(); while(itr.hasNext()) { @@ -181,7 +182,7 @@ public class EaglerRateLimiter { int limitLockout = config.getInt("limit_lockout", -1); int lockoutDuration = config.getInt("lockout_duration", -1); Collection exc = (Collection) config.getList("exceptions"); - List exceptions = new ArrayList(); + List exceptions = new ArrayList<>(); for(String str : exc) { exceptions.add(str.toLowerCase()); } 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 index 1400187f..93c7e6e9 100644 --- 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 @@ -3,10 +3,13 @@ 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; @@ -27,6 +30,7 @@ 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; @@ -50,7 +54,7 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.web.HttpCont public class EaglerVelocityConfig { public static EaglerVelocityConfig loadConfig(File directory) throws IOException { - Map contentTypes = new HashMap(); + Map contentTypes = new HashMap<>(); try(InputStream is = new FileInputStream(getConfigFile(directory, "http_mime_types.json"))) { loadMimeTypes(is, contentTypes); @@ -68,6 +72,7 @@ public class EaglerVelocityConfig { 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!"); @@ -85,7 +90,7 @@ public class EaglerVelocityConfig { Configuration listenerYml = prov.load(getConfigFile(directory, "listeners.yml")); Iterator listeners = listenerYml.getKeys().iterator(); - Map serverListeners = new HashMap(); + Map serverListeners = new HashMap<>(); boolean voiceChat = false; while(listeners.hasNext()) { @@ -119,6 +124,43 @@ public class EaglerVelocityConfig { } } + 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); @@ -144,9 +186,10 @@ public class EaglerVelocityConfig { eaglerPlayersVanillaSkin = null; } boolean enableIsEaglerPlayerProperty = configYml.getBoolean("enable_is_eagler_player_property", true); - Set disableVoiceOnServers = new HashSet((Collection)configYml.getList("disable_voice_chat_on_servers")); + 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")); + Set disableFNAWSkinsOnServers = new HashSet<>((Collection)configYml.getList("disable_fnaw_skins_on_servers")); + boolean enableBackendRPCAPI = configYml.getBoolean("enable_backend_rpc_api", false); final EaglerVelocityConfig ret = new EaglerVelocityConfig(serverName, serverUUID, websocketKeepAliveTimeout, websocketHandshakeTimeout, builtinHttpServerTimeout, websocketCompressionLevel, serverListeners, @@ -154,7 +197,7 @@ public class EaglerVelocityConfig { skinRateLimitPlayer, skinRateLimitGlobal, skinCacheURI, keepObjectsDays, keepProfilesDays, maxObjects, maxProfiles, antagonistsRateLimit, sqliteDriverClass, sqliteDriverPath, eaglerPlayersVanillaSkin, enableIsEaglerPlayerProperty, authConfig, updatesConfig, iceServers, voiceChat, disableVoiceOnServers, - disableFNAWSkinsEverywhere, disableFNAWSkinsOnServers); + disableFNAWSkinsEverywhere, disableFNAWSkinsOnServers, enableBackendRPCAPI, pauseMenuConfig); if(eaglerPlayersVanillaSkin != null) { VanillaDefaultSkinProfileLoader.lookupVanillaSkinUser(ret); @@ -181,6 +224,26 @@ public class EaglerVelocityConfig { 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()) { @@ -192,7 +255,7 @@ public class EaglerVelocityConfig { EaglerXVelocity.logger().warn("MIME type '{}' defines no extensions!", mime); continue; } - HashSet exts = new HashSet(); + HashSet exts = new HashSet<>(); for(int i = 0, l = arr.size(); i < l; ++i) { exts.add(arr.get(i).getAsString()); } @@ -211,13 +274,13 @@ public class EaglerVelocityConfig { contentTypes.put(s, typeObj); } }catch(Throwable t) { - EaglerXVelocity.logger().warn("Exception parsing MIME type '{}' - {}", mime, t.toString()); + EaglerXVelocity.logger().warn("Exception parsing MIME type '{}' - {}", mime, t); } } } private static Collection loadICEServers(Configuration config) { - Collection ret = new ArrayList(config.getList("voice_stun_servers")); + 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()) { @@ -228,18 +291,9 @@ public class EaglerVelocityConfig { return ret; } - @SuppressWarnings("deprecation") private static JsonObject parseJsonObject(InputStream file) throws IOException { - StringBuilder str = new StringBuilder(); - byte[] buffer = new byte[8192]; - - int i; - while((i = file.read(buffer)) > 0) { - str.append(new String(buffer, 0, i, "UTF-8")); - } - try { - return JsonParser.parseString(str.toString()).getAsJsonObject(); + return JsonParser.parseReader(new InputStreamReader(file, StandardCharsets.UTF_8)).getAsJsonObject(); }catch(JsonSyntaxException ex) { throw new IOException("Invalid JSONObject", ex); } @@ -279,6 +333,8 @@ public class EaglerVelocityConfig { private final boolean disableFNAWSkinsEverywhere; private final Set disableFNAWSkinsOnServers; private boolean isCrackedFlag; + private final boolean enableBackendRPCAPI; + private final EaglerPauseMenuConfig pauseMenuConf; Property[] eaglerPlayersVanillaSkinCached = new Property[] { isEaglerProperty }; public String getServerName() { @@ -444,6 +500,14 @@ public class EaglerVelocityConfig { return disableFNAWSkinsOnServers; } + public boolean getEnableBackendRPCAPI() { + return enableBackendRPCAPI; + } + + public EaglerPauseMenuConfig getPauseMenuConf() { + return pauseMenuConf; + } + private EaglerVelocityConfig(String serverName, UUID serverUUID, long websocketKeepAliveTimeout, long websocketHandshakeTimeout, long builtinHttpServerTimeout, int httpWebsocketCompressionLevel, Map serverListeners, Map contentTypes, @@ -453,7 +517,8 @@ public class EaglerVelocityConfig { String sqliteDriverClass, String sqliteDriverPath, String eaglerPlayersVanillaSkin, boolean enableIsEaglerPlayerProperty, EaglerAuthConfig authConfig, EaglerUpdateConfig updateConfig, Collection iceServers, boolean enableVoiceChat, Set disableVoiceOnServers, - boolean disableFNAWSkinsEverywhere, Set disableFNAWSkinsOnServers) { + boolean disableFNAWSkinsEverywhere, Set disableFNAWSkinsOnServers, boolean enableBackendRPCAPI, + EaglerPauseMenuConfig pauseMenuConf) { this.serverName = serverName; this.serverUUID = serverUUID; this.serverListeners = serverListeners; @@ -485,6 +550,8 @@ public class EaglerVelocityConfig { this.disableVoiceOnServers = disableVoiceOnServers; this.disableFNAWSkinsEverywhere = disableFNAWSkinsEverywhere; this.disableFNAWSkinsOnServers = disableFNAWSkinsOnServers; + this.enableBackendRPCAPI = enableBackendRPCAPI; + this.pauseMenuConf = pauseMenuConf; } } 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 new file mode 100644 index 00000000..88c91d60 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/ServerInfoTemplateParser.java @@ -0,0 +1,258 @@ +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; + +/** + * 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. + * + */ +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 + ")"); + } + } + +} 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 new file mode 100644 index 00000000..6be45930 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/TestOutputStream.java @@ -0,0 +1,31 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * 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. + * + */ +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 { + } + +} 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 index b74fd1d8..ff477fe3 100644 --- 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 @@ -1,6 +1,5 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.handlers; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.UUID; @@ -12,8 +11,9 @@ 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.ServerConnectedEvent; +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; @@ -25,18 +25,18 @@ import com.velocitypowered.api.util.GameProfile.Property; 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.CapePackets; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins.CapeServiceOffline; 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.plugin.gateway_velocity.voice.VoiceService; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceSignalPackets; +import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketEnableFNAWSkinsEAG; /** * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. @@ -55,9 +55,10 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice.VoiceSignalPa */ public class EaglerPacketEventListener { - public static final ChannelIdentifier FNAW_SKIN_ENABLE_CHANNEL = new LegacyChannelIdentifier("EAG|FNAWSEn-1.8"); 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) { @@ -66,46 +67,51 @@ public class EaglerPacketEventListener { @Subscribe(order = PostOrder.FIRST) public void onPluginMessage(final PluginMessageEvent event) { + ChannelIdentifier tagObj = event.getIdentifier(); + if(!(tagObj instanceof LegacyChannelIdentifier)) { + return; + } + String tag = tagObj.getId(); if(event.getSource() instanceof ConnectedPlayer) { final ConnectedPlayer player = (ConnectedPlayer)event.getSource(); EaglerPlayerData eagPlayer = EaglerPipeline.getEaglerHandle(player); if(eagPlayer != null) { - if(SkinService.CHANNEL.equals(event.getIdentifier())) { - EaglerXVelocity.proxy().getScheduler().buildTask(plugin, new Runnable() { - @Override - public void run() { - try { - SkinPackets.processPacket(event.getData(), player, plugin.getSkinService()); - } catch (IOException e) { - player.disconnect(Component.text("Skin packet error!")); - EaglerXVelocity.logger().error("Eagler user \"{}\" raised an exception handling skins!", player.getUsername(), e); - } - } - }).schedule(); - }else if(CapeServiceOffline.CHANNEL.equals(event.getIdentifier())) { + GameProtocolMessageController msgController = eagPlayer.getEaglerMessageController(); + if(msgController != null) { try { - CapePackets.processPacket(event.getData(), player, plugin.getCapeService()); - } catch (IOException e) { - player.disconnect(Component.text("Cape packet error!")); - EaglerXVelocity.logger().error("Eagler user \"{}\" raised an exception handling capes!", player.getUsername(), e); - } - }else if(VoiceService.CHANNEL.equals(event.getIdentifier())) { - VoiceService svc = plugin.getVoiceService(); - if(svc != null && eagPlayer.getEaglerListenerConfig().getEnableVoiceChat()) { - try { - VoiceSignalPackets.processPacket(event.getData(), player, svc); - } catch (IOException e) { - player.disconnect(Component.text("Voice signal packet error!")); - EaglerXVelocity.logger().error("Eagler user \"{}\" raised an exception handling voice signals!", player.getUsername(), e); + 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)) { + player.disconnect(Component.text("Nope!")); + event.setResult(ForwardResult.handled()); + return; + } + if(EaglerBackendRPCProtocol.CHANNEL_NAME_READY.equals(tag)) { + event.setResult(ForwardResult.handled()); + return; + } } }else if(event.getSource() instanceof ServerConnection && event.getTarget() instanceof ConnectedPlayer) { ConnectedPlayer player = (ConnectedPlayer)event.getTarget(); - if(GET_DOMAIN_CHANNEL.equals(event.getIdentifier())) { - EaglerPlayerData eagPlayerData = EaglerPipeline.getEaglerHandle(player); - if(eagPlayerData != null) { + EaglerPlayerData eagPlayerData = EaglerPipeline.getEaglerHandle(player); + if(eagPlayerData != null) { + if(EaglerBackendRPCProtocol.CHANNEL_NAME.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 }); @@ -113,6 +119,15 @@ public class EaglerPacketEventListener { ((ServerConnection)event.getSource()).sendPluginMessage(GET_DOMAIN_CHANNEL, domain.getBytes(StandardCharsets.UTF_8)); } } + }else { + if(EaglerBackendRPCProtocol.CHANNEL_NAME.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); + } + } } } } @@ -165,28 +180,32 @@ public class EaglerPacketEventListener { ConnectedPlayer player = (ConnectedPlayer)event.getPlayer(); EaglerPlayerData eagData = EaglerPipeline.getEaglerHandle(player); if(eagData != null && eagData.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handlePlayerLoggedOut(player); + plugin.getVoiceService().handlePlayerLoggedOut(eagData); } } } @Subscribe - public void onServerConnected(ServerConnectedEvent event) { - if(event.getPlayer() instanceof ConnectedPlayer) { - ConnectedPlayer player = (ConnectedPlayer)event.getPlayer(); - EaglerPlayerData eagData = EaglerPipeline.getEaglerHandle(player); - if(eagData != null) { - ServerInfo sv = event.getServer().getServerInfo(); + public void onServerConnected(ServerPostConnectEvent event) { + try { + ConnectedPlayer player = (ConnectedPlayer) event.getPlayer(); + ServerConnection server = player.getConnectedServer(); + BackendRPCSessionHandler.sendPluginMessage(server, EaglerBackendRPCProtocol.CHANNEL_NAME_READY, 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 != eagData.currentFNAWSkinEnableStatus) { - eagData.currentFNAWSkinEnableStatus = fnawSkins; - player.sendPluginMessage(FNAW_SKIN_ENABLE_CHANNEL, new byte[] { fnawSkins ? (byte)1 : (byte)0 }); + if(fnawSkins != playerObj.currentFNAWSkinEnableStatus.getAndSet(fnawSkins)) { + playerObj.sendEaglerMessage(new SPacketEnableFNAWSkinsEAG(fnawSkins, false)); } - if(eagData.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerConnected(player, sv); + 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); } } @@ -195,9 +214,16 @@ public class EaglerPacketEventListener { if(event.getPreviousServer() != null && (event.getPlayer() instanceof ConnectedPlayer)) { ConnectedPlayer player = (ConnectedPlayer)event.getPlayer(); EaglerPlayerData eagData = EaglerPipeline.getEaglerHandle(player); - if(eagData != null && eagData.getEaglerListenerConfig().getEnableVoiceChat()) { - plugin.getVoiceService().handleServerDisconnected(player, event.getPreviousServer().getServerInfo()); + if(eagData != null) { + BackendRPCSessionHandler rpcHandler = eagData.getRPCSessionHandler(); + if(rpcHandler != null) { + rpcHandler.handleConnectionLost(); + } + if(eagData.getEaglerListenerConfig().getEnableVoiceChat()) { + plugin.getVoiceService().handleServerDisconnected(eagData, event.getPreviousServer().getServerInfo()); + } } } } + } 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 new file mode 100644 index 00000000..4cb24c7b --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrBuilder.java @@ -0,0 +1,3136 @@ +/* + * 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)}. + *

+ * 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 new file mode 100644 index 00000000..a20457a6 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrMatcher.java @@ -0,0 +1,437 @@ +/* + * 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 new file mode 100644 index 00000000..cd501532 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/repackage/lang3/StrTokenizer.java @@ -0,0 +1,1124 @@ +/* + * 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 index 5682fd45..294151af 100644 --- 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 @@ -3,6 +3,7 @@ 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; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. @@ -35,11 +36,12 @@ public class EaglerConnectionInstance { 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 = System.currentTimeMillis(); + this.lastClientPongPacket = EaglerXVelocityAPIHelper.steadyTimeMillis(); } } 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 index 3a87ff6d..821cf3ef 100644 --- 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 @@ -6,6 +6,7 @@ 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; @@ -31,7 +32,7 @@ public class EaglerMinecraftDecoder extends MessageToMessageDecoder 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 ChannelIdentifier UPDATE_CERT_CHANNEL = new LegacyChannelIdentifier("EAG|UpdateCert-1.8"); + public static final Collection openChannels = new LinkedList<>(); public static final TimerTask closeInactive = new TimerTask() { @@ -75,7 +77,7 @@ public class EaglerPipeline { long httpTimeout = conf.getBuiltinHttpServerTimeout(); List channelsList; synchronized(openChannels) { - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); Iterator channelIterator = openChannels.iterator(); while(channelIterator.hasNext()) { Channel c = channelIterator.next(); @@ -83,7 +85,15 @@ public class EaglerPipeline { long handshakeTimeoutForConnection = 500l; if(i.isRegularHttp) handshakeTimeoutForConnection = httpTimeout; else if(i.isWebSocket) handshakeTimeoutForConnection = handshakeTimeout; - if(i == null || (!i.hasBeenForwarded && millis - i.creationTime > handshakeTimeoutForConnection) + 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(); @@ -103,7 +113,7 @@ public class EaglerPipeline { } } } - channelsList = new ArrayList(openChannels); + channelsList = new ArrayList<>(openChannels); } for(EaglerListenerConfig lst : conf.getServerListeners()) { HttpWebServer srv = lst.getWebServer(); @@ -111,47 +121,88 @@ public class EaglerPipeline { try { srv.flushCache(); }catch(Throwable t) { - log.error("Failed to flush web server cache for: {}", lst.getAddress().toString()); + log.error("Failed to flush web server cache for: {}", lst.getAddress()); t.printStackTrace(); } } } - if(!conf.getUpdateConfig().isBlockAllClientUpdates()) { - int sizeTracker = 0; - for(Channel c : channelsList) { - EaglerConnectionInstance conn = c.attr(EaglerPipeline.CONNECTION_INSTANCE).get(); - if(conn.userConnection == null) { - continue; - } - EaglerPlayerData i = conn.eaglerData; - ClientCertificateHolder certHolder = null; + 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.size() > 0) { - Iterator itr = i.certificatesToSend.iterator(); - certHolder = itr.next(); - itr.remove(); - } - } - if(certHolder != null) { - int identityHash = certHolder.hashCode(); - boolean bb; - synchronized(i.certificatesSent) { - bb = i.certificatesSent.add(identityHash); - } - if(bb) { - conn.userConnection.sendPluginMessage(UPDATE_CERT_CHANNEL, certHolder.data); - sizeTracker += certHolder.data.length; - if(sizeTracker > (conf.getUpdateConfig().getCertPacketDataRateLimit() / 4)) { - break; - } + if(!i.certificatesToSend.isEmpty()) { + certToSend = true; } } } - EaglerUpdateSvc.updateTick(); + 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.toString()); - t.printStackTrace(); + log.error("Exception in thread \"{}\"!", Thread.currentThread().getName(), t); } } }; 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 index 6947daf8..f179153e 100644 --- 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 @@ -1,9 +1,41 @@ 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; /** * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. @@ -31,6 +63,15 @@ public class EaglerPlayerData { } } + 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; @@ -38,32 +79,387 @@ public class EaglerPlayerData { 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 boolean currentFNAWSkinEnableStatus = true; + 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(EaglerListenerConfig listener, String origin, ClientCertificateHolder clientCertificate) { + 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.certificatesToSend = new HashSet(); - this.certificatesSent = new HashSet(); + 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; + } + } 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 index 5539b66e..f19501a1 100644 --- 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 @@ -24,6 +24,7 @@ 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; @@ -45,8 +46,8 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayer */ public class EaglerUpdateSvc { - private static final List certs = new ArrayList(); - private static final Map certsCache = new HashMap(); + private static final List certs = new ArrayList<>(); + private static final Map certsCache = new HashMap<>(); private static class CachedClientCertificate { private final ClientCertificateHolder cert; @@ -62,7 +63,7 @@ public class EaglerUpdateSvc { public static void updateTick() { Logger log = EaglerXVelocity.logger(); - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); EaglerUpdateConfig conf = EaglerXVelocity.getEagler().getConfig().getUpdateConfig(); if(conf.isDownloadLatestCerts() && millis - lastDownload > (long)conf.getCheckForUpdatesEvery() * 1000l) { lastDownload = millis; @@ -73,7 +74,7 @@ public class EaglerUpdateSvc { log.error("Uncaught exception downloading certificates!"); t.printStackTrace(); } - millis = System.currentTimeMillis(); + millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); } if(conf.isEnableEagcertFolder() && millis - lastEnumerate > 5000l) { lastEnumerate = millis; @@ -96,7 +97,7 @@ public class EaglerUpdateSvc { return; } } - Set filenames = new HashSet(); + Set filenames = new HashSet<>(); for(String str : conf.getDownloadCertURLs()) { try { URL url = new URL(str); @@ -176,7 +177,7 @@ public class EaglerUpdateSvc { } boolean dirty = false; File[] dirList = eagcert.listFiles(); - Set existingFiles = new HashSet(); + Set existingFiles = new HashSet<>(); for(int i = 0; i < dirList.length; ++i) { File f = dirList[i]; String n = f.getName(); 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 index 620b87e0..91943d9f 100644 --- 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 @@ -21,6 +21,7 @@ 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; @@ -68,12 +69,12 @@ public class HttpHandshakeHandler extends ChannelInboundHandlerAdapter { try { ctx.channel().attr(EaglerPipeline.REAL_ADDRESS).set(InetAddress.getByName(rateLimitHost)); } catch (UnknownHostException ex) { - EaglerXVelocity.logger().warn("[" + ctx.channel().remoteAddress() + "]: Connected with an invalid '" + conf.getForwardIpHeader() + "' header, disconnecting..."); + EaglerXVelocity.logger().warn("[{}]: Connected with an invalid '{}' header, disconnecting...", ctx.channel().remoteAddress(), conf.getForwardIpHeader()); ctx.close(); return; } } else { - EaglerXVelocity.logger().warn("[" + ctx.channel().remoteAddress() + "]: Connected without a '" + conf.getForwardIpHeader() + "' header, disconnecting..."); + EaglerXVelocity.logger().warn("[{}]: Connected without a '{}' header, disconnecting...", ctx.channel().remoteAddress(), conf.getForwardIpHeader()); ctx.close(); return; } @@ -103,10 +104,23 @@ public class HttpHandshakeHandler extends ChannelInboundHandlerAdapter { if (origin != null) { ctx.channel().attr(EaglerPipeline.ORIGIN).set(origin); } - - //TODO: origin blacklist + 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)); } @@ -172,7 +186,7 @@ public class HttpHandshakeHandler extends ChannelInboundHandlerAdapter { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { if (ctx.channel().isActive()) { - EaglerXVelocity.logger().warn("[Pre][" + ctx.channel().remoteAddress() + "]: Exception Caught: " + cause.toString(), cause); + EaglerXVelocity.logger().warn("[Pre][{}]: Exception Caught: {}", ctx.channel().remoteAddress(), cause.toString(), cause); ctx.close(); } } 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 index 1063e8d4..d720699a 100644 --- 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 @@ -72,6 +72,7 @@ public abstract class HttpServerQueryHandler extends ChannelInboundHandlerAdapte 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; @@ -188,6 +189,14 @@ public abstract class HttpServerQueryHandler extends ChannelInboundHandlerAdapte 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())); } @@ -220,6 +229,14 @@ public abstract class HttpServerQueryHandler extends ChannelInboundHandlerAdapte 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); 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 index 93459865..a3904c66 100644 --- 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 @@ -12,10 +12,12 @@ 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; @@ -34,6 +36,8 @@ 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.ConnectionType; +import com.velocitypowered.proxy.connection.ConnectionTypes; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.client.*; import com.velocitypowered.proxy.network.Connections; @@ -60,11 +64,14 @@ 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.json.JSONComponentSerializer; 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; @@ -75,11 +82,14 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.event.Eaglercra 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.*; @@ -143,16 +153,18 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { private int clientProtocolVersion = -1; private boolean isProtocolExchanged = false; private int gameProtocolVersion = -1; - private CharSequence clientBrandString; - private CharSequence clientVersionString; - private CharSequence clientUsername; + private String clientBrandString; + private String clientVersionString; + private String clientUsername; private UUID clientUUID; - private CharSequence clientRequestedServer; + 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 final Map profileData = new HashMap<>(); private boolean hasFirstPacket = false; private boolean hasBinaryConnection = false; private boolean connectionClosed = false; @@ -161,6 +173,9 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { 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; } @@ -218,7 +233,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if (i >= conf.getMaxPlayer()) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } } @@ -293,12 +308,12 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { 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); + .addListener(ChannelFutureListener.CLOSE); return; - }else if(buffer.readUnsignedByte() != minecraftProtocolVersion) { + }else if(buffer.readUnsignedByte() != minecraftProtocolVersion || !conf.isAllowV3()) { clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; connectionClosed = true; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); buf.writeByte(1); buf.writeByte(1); @@ -310,32 +325,37 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { return; } }else if(eaglerLegacyProtocolVersion == 2) { - int minProtVers = Integer.MAX_VALUE; - int maxProtVers = -1; - boolean hasV2InList = false; - boolean hasV3InList = false; - - int minGameVers = Integer.MAX_VALUE; - int maxGameVers = -1; - boolean has47InList = false; + //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 minSupportedProtVers = Integer.MAX_VALUE; + int maxSupportedProtVers = Integer.MIN_VALUE; int cnt = buffer.readUnsignedShort(); for(int i = 0; i < cnt; ++i) { int j = buffer.readUnsignedShort(); - if(j == 2) { - hasV2InList = true; + if(j > maxAvailableProtVers) { + maxAvailableProtVers = j; } - if(j == 3) { - hasV3InList = true; + if(j < minAvailableProtVers) { + minAvailableProtVers = j; } - if(j > maxProtVers) { - maxProtVers = j; - } - if(j < minProtVers) { - minProtVers = j; + if(j >= minServerSupported && j <= maxServerSupported) { + if(j > maxSupportedProtVers) { + maxSupportedProtVers = j; + } + if(j < minSupportedProtVers) { + minSupportedProtVers = j; + } } } + int minGameVers = Integer.MAX_VALUE; + int maxGameVers = -1; + boolean has47InList = false; + cnt = buffer.readUnsignedShort(); for(int i = 0; i < cnt; ++i) { int j = buffer.readUnsignedShort(); @@ -350,34 +370,41 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } } - if(minProtVers == Integer.MAX_VALUE || minGameVers == Integer.MAX_VALUE) { + if(maxAvailableProtVers == Integer.MIN_VALUE || maxGameVers == Integer.MIN_VALUE) { throw new IOException(); } boolean versMisMatch = false; boolean isServerProbablyOutdated = false; boolean isClientProbablyOutdated = false; - if(!hasV2InList && !hasV3InList) { + if(maxSupportedProtVers == Integer.MIN_VALUE) { + clientProtocolVersion = maxAvailableProtVers < 3 ? 2 : 3; versMisMatch = true; - isServerProbablyOutdated = minProtVers > 3 && maxProtVers > 3; //make sure to update VersionQueryHandler too - isClientProbablyOutdated = minProtVers < 2 && maxProtVers < 2; + isServerProbablyOutdated = minAvailableProtVers > maxServerSupported && maxAvailableProtVers > maxServerSupported; + isClientProbablyOutdated = minAvailableProtVers < minServerSupported && maxAvailableProtVers < minServerSupported; }else if(!has47InList) { + clientProtocolVersion = 3; versMisMatch = true; isServerProbablyOutdated = minGameVers > minecraftProtocolVersion && maxGameVers > minecraftProtocolVersion; isClientProbablyOutdated = minGameVers < minecraftProtocolVersion && maxGameVers < minecraftProtocolVersion; + }else { + clientProtocolVersion = maxSupportedProtVers; } - clientProtocolVersion = hasV3InList ? 3 : 2; - if(versMisMatch) { clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; connectionClosed = true; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH); - buf.writeShort(2); - buf.writeShort(2); // want v2 or v3 - buf.writeShort(3); + 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(1); buf.writeShort(minecraftProtocolVersion); // want game version 47 @@ -390,14 +417,14 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } }else { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Legacy protocol version should always be '2' on post-snapshot clients") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } int strlen = buffer.readUnsignedByte(); - CharSequence eaglerBrand = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII); + String eaglerBrand = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); strlen = buffer.readUnsignedByte(); - CharSequence eaglerVersionString = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII); + String eaglerVersionString = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); if(eaglerLegacyProtocolVersion >= 2) { clientAuth = buffer.readBoolean(); @@ -427,6 +454,19 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } } + 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; @@ -434,7 +474,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { clientBrandString = eaglerBrand; clientVersionString = eaglerVersionString; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_VERSION); if(final_useSnapshotFallbackProtocol) { @@ -460,7 +500,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if(meth == -1) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); EaglerXVelocity.logger().error("[{}]: Disconnecting, unsupported AuthMethod: {}", localAddrString, authRequireEvent.getUseAuthType()); return; } @@ -488,28 +528,28 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { clientAuth, clientAuthUsername, (reqAuthEvent) -> { if(authRequireEvent.shouldKickUser()) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, authRequireEvent.getKickMessage()) - .addListener(ChannelFutureListener.CLOSE); + .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.toString()); + .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); + .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); + .addListener(ChannelFutureListener.CLOSE); EaglerXVelocity.logger().error("[{}]: Disconnecting, no authentication method provided by handler", localAddrString); return; } @@ -517,7 +557,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { int typeId = getAuthMethodId(type); if(typeId == -1) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Unsupported authentication method resolved") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); EaglerXVelocity.logger().error("[{}]: Disconnecting, unsupported AuthMethod: {}", localAddrString, type); return; } @@ -531,7 +571,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { }else { if(authRequireEvent.getUseAuthType() == null) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "IsAuthRequiredEvent was not fully handled") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); EaglerXVelocity.logger().error("[{}]: Disconnecting, no authentication method provided by handler", localAddrString); return; } @@ -568,24 +608,23 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { clientLoginState = HandshakePacketTypes.STATE_STALLING; int strlen = buffer.readUnsignedByte(); - clientUsername = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII); + clientUsername = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII).toString(); - String usrs = clientUsername.toString(); - if(!usrs.equals(usrs.replaceAll("[^A-Za-z0-9_]", "_").trim())) { + if(!clientUsername.equals(clientUsername.replaceAll("[^A-Za-z0-9_]", "_"))) { sendLoginDenied(ctx, "Invalid characters in username") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } if(clientUsername.length() < 3) { sendLoginDenied(ctx, "Username must be at least 3 characters") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } if(clientUsername.length() > 16) { sendLoginDenied(ctx, "Username must be under 16 characters") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } @@ -603,11 +642,28 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { clientUUID = UUID.nameUUIDFromBytes(uuidHashGenerator); strlen = buffer.readUnsignedByte(); - clientRequestedServer = buffer.readCharSequence(strlen, StandardCharsets.US_ASCII); + 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"); } @@ -615,15 +671,14 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { Runnable continueThread = () -> { final VelocityServer bungee = EaglerXVelocity.proxy(); - String usernameStr = clientUsername.toString(); - if (bungee.getPlayer(usernameStr).isPresent()) { + if (bungee.getPlayer(clientUsername).isPresent()) { sendLoginDenied(ctx, LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); return; } clientLoginState = HandshakePacketTypes.STATE_CLIENT_LOGIN; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ALLOW_LOGIN); buf.writeByte(clientUsername.length()); buf.writeCharSequence(clientUsername, StandardCharsets.US_ASCII); @@ -635,53 +690,112 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { EaglerXVelocity eaglerXBungee = EaglerXVelocity.getEagler(); EaglerAuthConfig authConfig = eaglerXBungee.getConfig().getAuthConfig(); - if(authConfig.isEnableAuthentication() && clientAuth) { - if(clientAuthPassword.length == 0) { - sendLoginDenied(ctx, "Client provided no authentication code") - .addListener(ChannelFutureListener.CLOSE); - return; - }else { - try { - EaglercraftHandleAuthPasswordEvent handleEvent = new EaglercraftHandleAuthPasswordEvent( - conf, remoteAddress, authRequireEvent.getOriginHeader(), clientAuthUsername, - authRequireEvent.getSaltingData(), clientUsername, clientUUID, clientAuthPassword, - authRequireEvent.getUseAuthType(), authRequireEvent.getAuthMessage(), - (Object) authRequireEvent.getAuthAttachment(), clientRequestedServer.toString(), - (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(); - + 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(authConfig.isUseBuiltInAuthentication()) { - DefaultAuthSystem authSystem = eaglerXBungee.getAuthService(); - if(authSystem != null) { - authSystem.handleAuthPasswordEvent(handleEvent); - } + 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 { - handleEvent = eaglerXBungee.getProxy().getEventManager().fire(handleEvent).join(); + sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Failed to handle authentication!") + .addListener(ChannelFutureListener.CLOSE); + return; } - - if(!handleEvent.isAsyncContinue()) { - handleEvent.doDirectContinue(); - } - }catch(Throwable t) { - throw new EventException(t); + }); + + 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 { @@ -691,35 +805,60 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { }else { clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; sendErrorWrong(ctx, op, "STATE_CLIENT_VERSION") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); } } break; case HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA: { if(clientLoginState == HandshakePacketTypes.STATE_CLIENT_LOGIN) { - - 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); + 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 { - sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_DUPLICATE_PROFILE_DATA, "Multiple profile data packets of the same type recieved") - .addListener(ChannelFutureListener.CLOSE); - return; + 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 { @@ -746,7 +885,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { default: clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_UNKNOWN_PACKET, "Unknown Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); break; } }catch(Throwable ex) { @@ -757,7 +896,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_INVALID_PACKET, op == -1 ? "Invalid Packet" : "Invalid Packet #" + op) - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); } } @@ -775,7 +914,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if (i >= conf.getMaxPlayer()) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full") - .addListener(ChannelFutureListener.CLOSE); + .addListener(ChannelFutureListener.CLOSE); connectionClosed = true; return; } @@ -794,6 +933,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if(addr != null) { baseAddress = new InetSocketAddress(addr, baseAddress.getPort()); } + final InetSocketAddress final_baseAddress = baseAddress; ProtocolVersion protocolVers = ProtocolVersion.getProtocolVersion(gameProtocolVersion); if(!protocolVers.isSupported()) { @@ -820,6 +960,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { throw new RuntimeException(e); } + con.setType(ConnectionTypes.VANILLA); + EaglerVelocityConfig eaglerConf = EaglerXVelocity.getEagler().getConfig(); EaglerUpdateConfig updateconf = eaglerConf.getUpdateConfig(); @@ -833,6 +975,30 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } 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); @@ -873,8 +1039,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { Optional disconnectReason = result.getReasonComponent(); if (disconnectReason.isPresent()) { sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - JSONComponentSerializer.json().serialize(GlobalTranslator.render(disconnectReason.get(), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); + GlobalTranslator.render(disconnectReason.get(), Locale.getDefault())) + .addListener(ChannelFutureListener.CLOSE); return; } @@ -897,7 +1063,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if (con.isClosed()) { return CompletableFuture.completedFuture(null); } else { - GameProfile gp = profileEvent.getGameProfile(); + GameProfile gp = profileRequestEvent.getGameProfile(); if(eaglerConf.getEnableIsEaglerPlayerProperty()) { gp = gp.addProperty(EaglerVelocityConfig.isEaglerProperty); } @@ -918,28 +1084,31 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { return CompletableFuture.completedFuture(null); } else { boolean doRegisterSkins = true; + boolean doForceSkins = false; - EaglercraftRegisterSkinEvent registerSkinEvent = bungee.getEventManager().fire(new EaglercraftRegisterSkinEvent(usernameStr, clientUUID)).join(); - + 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; - }else { - String customUrl = registerSkinEvent.getForceSetUseURL(); - if(customUrl != null) { - EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(customUrl, gp.getId()); - doRegisterSkins = false; - overrideEaglerToVanillaSkins = false; + if(clientProtocolVersion >= 4) { + doForceSkins = true; } } } @@ -947,11 +1116,13 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { 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()); } } } @@ -973,6 +1144,9 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } } doRegisterSkins = false; + if(clientProtocolVersion >= 4) { + doForceSkins = true; + } }catch(Throwable t) { } break; @@ -982,20 +1156,29 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { } if(doRegisterSkins) { - if(profileData.containsKey("skin_v1")) { + if(clientProtocolVersion >= 4 && profileData.containsKey("skin_v2")) { try { - SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v1"), - EaglerXVelocity.getEagler().getSkinService()); + SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v2"), + EaglerXVelocity.getEagler().getSkinService(), 4); } catch (Throwable ex) { SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService()); - EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid skin packet: " + ex.toString()); + 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)).join(); + EaglercraftRegisterCapeEvent registerCapeEvent = bungee.getEventManager().fire(new EaglercraftRegisterCapeEvent(usernameStr, + clientUUID, authRequireEvent != null ? authRequireEvent.getAuthAttachment() : null)).join(); byte[] forceCape = registerCapeEvent.getForceSetUseCustomPacket(); if(forceCape != null) { @@ -1008,18 +1191,44 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { EaglerXVelocity.getEagler().getCapeService()); } catch (Throwable ex) { CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService()); - EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid cape packet: " + ex.toString()); + EaglerXVelocity.logger().info("[{}]: Invalid cape packet: {}", ctx.channel().remoteAddress(), ex.toString()); } }else { CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService()); } - EaglerXVelocity.logger().info("{} has connected", player); - if(conf.getEnableVoiceChat()) { - EaglerXVelocity.getEagler().getVoiceService().handlePlayerLoggedIn(player); + 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); } - EaglerPlayerData epd = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().eaglerData = new EaglerPlayerData(conf, ctx.channel().attr(EaglerPipeline.ORIGIN).get(), cert); + 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) { @@ -1062,8 +1271,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { if (reason.isPresent()) { bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CANCELLED_BY_PROXY)); sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, - JSONComponentSerializer.json().serialize(GlobalTranslator.render(reason.get(), Locale.getDefault()))) - .addListener(ChannelFutureListener.CLOSE); + GlobalTranslator.render(reason.get(), Locale.getDefault())) + .addListener(ChannelFutureListener.CLOSE); return; } else { if (!bungee.registerConnection(player)) { @@ -1274,13 +1483,13 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { private ChannelFuture sendLoginDenied(ChannelHandlerContext ctx, String reason) { if((!isProtocolExchanged || clientProtocolVersion == 2) && reason.length() > 255) { - reason = reason.substring(0, 256); + reason = reason.substring(0, 255); }else if(reason.length() > 65535) { - reason = reason.substring(0, 65536); + reason = reason.substring(0, 65535); } clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; connectionClosed = true; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_DENY_LOGIN); byte[] msg = reason.getBytes(StandardCharsets.UTF_8); if(!isProtocolExchanged || clientProtocolVersion == 2) { @@ -1298,13 +1507,13 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { private ChannelFuture sendErrorCode(ChannelHandlerContext ctx, int code, String str) { if((!isProtocolExchanged || clientProtocolVersion == 2) && str.length() > 255) { - str = str.substring(0, 256); + str = str.substring(0, 255); }else if(str.length() > 65535) { - str = str.substring(0, 65536); + str = str.substring(0, 65535); } clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE; connectionClosed = true; - ByteBuf buf = Unpooled.buffer(); + ByteBuf buf = ctx.alloc().buffer(); buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_ERROR); buf.writeByte(code); byte[] msg = str.getBytes(StandardCharsets.UTF_8); @@ -1317,6 +1526,14 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter { 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()); 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 new file mode 100644 index 00000000..f8cc6b35 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/BackendRPCSessionHandler.java @@ -0,0 +1,307 @@ +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.api.event.EaglercraftVoiceStatusChangeEvent; +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; + +/** + * 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. + * + */ +public class BackendRPCSessionHandler { + + public static BackendRPCSessionHandler createForPlayer(EaglerPlayerData eaglerHandler) { + return new BackendRPCSessionHandler(eaglerHandler); + } + + protected final EaglerPlayerData eaglerHandler; + private ServerConnection currentServer = 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, EaglerBackendRPCProtocol.CHANNEL_NAME, ret); + } + + public void handleConnectionLost() { + if(currentServer != null) { + handleDestroyContext(); + } + } + + private void handleDestroyContext() { + currentServer = 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(); + } + 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, EaglerBackendRPCProtocol.CHANNEL_NAME, 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, EaglerBackendRPCProtocol.CHANNEL_NAME, 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))); + } + } + +} 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 new file mode 100644 index 00000000..d6abaace --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/EnumSubscribedEvent.java @@ -0,0 +1,22 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.backend_rpc_protocol; + +/** + * 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. + * + */ +public enum EnumSubscribedEvent { + WEBVIEW_OPEN_CLOSE, + WEBVIEW_MESSAGE, + TOGGLE_VOICE; +} 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 new file mode 100644 index 00000000..69104a4f --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/backend_rpc_protocol/ServerV1RPCProtocolHandler.java @@ -0,0 +1,439 @@ +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; + +/** + * 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. + * + */ +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); + } + +} 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 new file mode 100644 index 00000000..10238c3d --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/GameProtocolMessageController.java @@ -0,0 +1,302 @@ +package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol; + +import java.io.IOException; +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; + +/** + * 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. + * + */ +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 = 0, totalLen = 0; + while(!sendQueueV4.isEmpty()) { + do { + i = sendQueueV4.get(sendCount++).length; + totalLen += GamePacketOutputBuffer.getVarIntSize(i) + i; + }while(totalLen < 32760 && sendCount < sendQueueV4.size()); + if(totalLen >= 32760) { + --sendCount; + } + 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; + } + +} 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 new file mode 100644 index 00000000..4afb2915 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV3MessageHandler.java @@ -0,0 +1,87 @@ +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.*; + +/** + * 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. + * + */ +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); + } + } + +} 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 new file mode 100644 index 00000000..dd9106c1 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/protocol/ServerV4MessageHandler.java @@ -0,0 +1,180 @@ +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.*; + +/** + * 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. + * + */ +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!")); + } + } + +} 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 index 785ff5f7..ea076194 100644 --- 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 @@ -9,6 +9,7 @@ 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; @@ -46,7 +47,7 @@ public class MOTDQueryHandler extends EaglerQuerySimpleHandler implements MOTDCo @Override protected void begin(String queryType) { - creationTime = System.currentTimeMillis(); + creationTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); subType = queryType; returnType = "MOTD"; EaglerListenerConfig listener = getListener(); @@ -59,7 +60,7 @@ public class MOTDQueryHandler extends EaglerQuerySimpleHandler implements MOTDCo } maxPlayers = listener.getMaxPlayer(); onlinePlayers = EaglerXVelocity.proxy().getPlayerCount(); - players = new ArrayList(); + players = new ArrayList<>(); for(Player pp : EaglerXVelocity.proxy().getAllPlayers()) { players.add(pp.getUsername()); if(players.size() >= 9) { 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 index 19e26f11..8e78b1c8 100644 --- 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 @@ -7,6 +7,7 @@ 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; @@ -27,12 +28,13 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.HttpServerQu */ public class QueryManager { - private static final Map> queryTypes = new HashMap(); + 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) { @@ -77,7 +79,7 @@ public class QueryManager { json.addProperty("brand", "lax1dude"); json.addProperty("vers", EaglerXVelocityVersion.ID + "/" + EaglerXVelocityVersion.VERSION); json.addProperty("cracked", conf.isCracked()); - json.addProperty("time", System.currentTimeMillis()); + json.addProperty("time", EaglerXVelocityAPIHelper.steadyTimeMillis()); json.addProperty("uuid", conf.getServerUUID().toString()); return json; } 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 new file mode 100644 index 00000000..56de1c45 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/server/query/RevokeSessionQueryHandler.java @@ -0,0 +1,74 @@ +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; + +/** + * 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. + * + */ +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() { + } + +} 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 index 0af12957..49efcfd1 100644 --- 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 @@ -27,8 +27,13 @@ public class VersionQueryHandler extends EaglerQuerySimpleHandler { protected void begin(String queryType) { JsonObject responseObj = new JsonObject(); JsonArray handshakeVersions = new JsonArray(); - handshakeVersions.add(2); - handshakeVersions.add(3); + if(this.getListener().isAllowV3()) { + handshakeVersions.add(2); + handshakeVersions.add(3); + } + if(this.getListener().isAllowV4()) { + handshakeVersions.add(4); + } responseObj.add("handshakeVersions", handshakeVersions); JsonArray protocolVersions = new JsonArray(); protocolVersions.add(47); 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 index 0cff1de6..bbd858d6 100644 --- 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 @@ -27,7 +27,7 @@ public class HttpContentType { public final String cacheControlHeader; public final long fileBrowserCacheTTL; - public static final HttpContentType defaultType = new HttpContentType(new HashSet(), "application/octet-stream", null, 14400000l); + 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; 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 index deb289d9..356937e0 100644 --- 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 @@ -4,17 +4,18 @@ import java.io.File; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; 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 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; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -45,13 +46,13 @@ public class HttpWebServer { public HttpWebServer(File directory, Map contentTypes, List index, String page404) { this.directory = directory; this.contentTypes = contentTypes; - this.filesCache = new HashMap(); + this.filesCache = new HashMap<>(); this.index = index; this.page404 = page404; } public void flushCache() { - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); synchronized(cacheClearLock) { synchronized(filesCache) { Iterator itr = filesCache.values().iterator(); @@ -70,7 +71,7 @@ public class HttpWebServer { try { String[] pathSplit = path.split("(\\\\|\\/)+"); - List pathList = pathSplit.length == 0 ? null : new ArrayList(); + 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) { @@ -198,7 +199,7 @@ public class HttpWebServer { if(ct == null) { ct = HttpContentType.defaultType; } - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); return new HttpMemoryCache(path, requestCachePath, file, ct, millis, millis, path.lastModified()); }catch(Throwable t) { return null; @@ -209,7 +210,7 @@ public class HttpWebServer { if(file.fileObject == null) { return file; } - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); file.lastCacheHit = millis; if(millis - file.lastDiskReload > 4000l) { File f = file.fileObject; @@ -265,8 +266,8 @@ public class HttpWebServer { + "The requested resource " + " could not be found on this server!

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

").getBytes(StandardCharsets.UTF_8); - HttpContentType htmlContentType = new HttpContentType(new HashSet(Arrays.asList("html")), "text/html", "utf-8", 120000l); - long millis = System.currentTimeMillis(); + 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); } @@ -281,8 +282,8 @@ public class HttpWebServer { + "404 'Websocket Upgrade Failure' (rip)

+ * 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. + *

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(new HashSet(Arrays.asList("html")), "text/html", "utf-8", 14400000l); - long millis = System.currentTimeMillis(); + 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); } 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 index a9e0205b..8640ed7d 100644 --- 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 @@ -105,7 +105,7 @@ public class AsyncSkinProvider { byte[] loadedPixels = new byte[16384]; image.getRGB(0, 0, 64, 64, tmp, 0, 64); SkinRescaler.convertToBytes(tmp, loadedPixels); - SkinPackets.setAlphaForChest(loadedPixels, (byte)255, 0); + SkinPackets.setAlphaForChestV3(loadedPixels); doAccept(loadedPixels); return; }else if(srcWidth == 64 && srcHeight == 32) { @@ -113,7 +113,7 @@ public class AsyncSkinProvider { byte[] loadedPixels = new byte[16384]; image.getRGB(0, 0, 64, 32, tmp1, 0, 64); SkinRescaler.convert64x32To64x64(tmp1, loadedPixels); - SkinPackets.setAlphaForChest(loadedPixels, (byte)255, 0); + SkinPackets.setAlphaForChestV3(loadedPixels); doAccept(loadedPixels); return; }else { 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 index 62286f80..ac5e88c5 100644 --- 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 @@ -3,7 +3,9 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; import java.io.IOException; import java.util.UUID; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +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; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. @@ -24,56 +26,29 @@ public class CapePackets { public static final int PACKET_MY_CAPE_PRESET = 0x01; public static final int PACKET_MY_CAPE_CUSTOM = 0x02; - public static final int PACKET_GET_OTHER_CAPE = 0x03; - public static final int PACKET_OTHER_CAPE_PRESET = 0x04; - public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05; - - public static void processPacket(byte[] data, ConnectedPlayer sender, CapeServiceOffline capeService) throws IOException { - if(data.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - int packetId = (int)data[0] & 0xFF; - try { - switch(packetId) { - case PACKET_GET_OTHER_CAPE: - processGetOtherCape(data, sender, capeService); - break; - default: - throw new IOException("Unknown packet type " + packetId); - } - }catch(IOException ex) { - throw ex; - }catch(Throwable t) { - throw new IOException("Unhandled exception handling cape packet type " + packetId, t); - } - } - - private static void processGetOtherCape(byte[] data, ConnectedPlayer sender, CapeServiceOffline capeService) throws IOException { - if(data.length != 17) { - throw new IOException("Invalid length " + data.length + " for skin request packet"); - } - UUID searchUUID = SkinPackets.bytesToUUID(data, 1); - capeService.processGetOtherCape(searchUUID, sender); - } public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, CapeServiceOffline capeService) throws IOException { if(bs.length == 0) { throw new IOException("Zero-length packet recieved"); } - byte[] generatedPacket; + 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 = CapePackets.makePresetResponse(clientUUID, (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); + 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"); } - generatedPacket = CapePackets.makeCustomResponse(clientUUID, bs, 1, 1173); + 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); @@ -82,29 +57,8 @@ public class CapePackets { } public static void registerEaglerPlayerFallback(UUID clientUUID, CapeServiceOffline capeService) { - capeService.registerEaglercraftPlayer(clientUUID, CapePackets.makePresetResponse(clientUUID, 0)); + capeService.registerEaglercraftPlayer(clientUUID, new SPacketOtherCapePresetEAG( + clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), 0)); } - public static byte[] makePresetResponse(UUID uuid, int presetId) { - byte[] ret = new byte[1 + 16 + 4]; - ret[0] = (byte)PACKET_OTHER_CAPE_PRESET; - SkinPackets.UUIDToBytes(uuid, ret, 1); - ret[17] = (byte)(presetId >>> 24); - ret[18] = (byte)(presetId >>> 16); - ret[19] = (byte)(presetId >>> 8); - ret[20] = (byte)(presetId & 0xFF); - return ret; - } - - public static byte[] makeCustomResponse(UUID uuid, byte[] pixels) { - return makeCustomResponse(uuid, pixels, 0, pixels.length); - } - - public static byte[] makeCustomResponse(UUID uuid, byte[] pixels, int offset, int length) { - byte[] ret = new byte[1 + 16 + length]; - ret[0] = (byte)PACKET_OTHER_CAPE_CUSTOM; - SkinPackets.UUIDToBytes(uuid, ret, 1); - System.arraycopy(pixels, offset, ret, 17, length); - return ret; - } } 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 index e1ba31ab..6044c7de 100644 --- 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 @@ -4,11 +4,12 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import com.velocitypowered.api.proxy.messages.ChannelIdentifier; -import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -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.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; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. @@ -29,26 +30,41 @@ public class CapeServiceOffline { public static final int masterRateLimitPerPlayer = 250; - public static final ChannelIdentifier CHANNEL = new LegacyChannelIdentifier("EAG|Capes-1.8"); + private final Map capesCache = new HashMap<>(); - private final Map capesCache = new HashMap(); - - public void registerEaglercraftPlayer(UUID playerUUID, byte[] capePacket) { + public void registerEaglercraftPlayer(UUID playerUUID, GameMessagePacket capePacket) { synchronized(capesCache) { capesCache.put(playerUUID, capePacket); } } - public void processGetOtherCape(UUID searchUUID, ConnectedPlayer sender) { - if(EaglerPipeline.getEaglerHandle(sender).skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - byte[] maybeCape; + public void processGetOtherCape(UUID searchUUID, EaglerPlayerData sender) { + if(sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { + GameMessagePacket maybeCape; synchronized(capesCache) { maybeCape = capesCache.get(searchUUID); } if(maybeCape != null) { - sender.sendPluginMessage(CapeServiceOffline.CHANNEL, maybeCape); + sender.sendEaglerMessage(maybeCape); }else { - sender.sendPluginMessage(CapeServiceOffline.CHANNEL, CapePackets.makePresetResponse(searchUUID, 0)); + sender.sendEaglerMessage(new SPacketOtherCapePresetEAG(searchUUID.getMostSignificantBits(), + searchUUID.getLeastSignificantBits(), 0)); + } + } + } + + public void processForceCape(UUID clientUUID, EaglerPlayerData initialHandler) { + GameMessagePacket maybeCape; + synchronized(capesCache) { + 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)); } } } @@ -59,6 +75,37 @@ public class CapeServiceOffline { } } + public GameMessagePacket getCape(UUID clientUUID) { + synchronized(capesCache) { + 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() { synchronized(capesCache) { capesCache.clear(); 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 index 007d06ec..630691f1 100644 --- 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 @@ -2,10 +2,11 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; import java.util.UUID; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData; +import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; /** - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. + * 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 @@ -24,11 +25,11 @@ 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 ConnectedPlayer sender); + void processGetOtherSkin(final UUID searchUUID, final EaglerPlayerData sender); - void processGetOtherSkin(UUID searchUUID, String skinURL, ConnectedPlayer sender); + void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender); - void registerEaglercraftPlayer(UUID clientUUID, byte[] generatedPacket, int modelId); + void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId); void unregisterPlayer(UUID clientUUID); @@ -42,4 +43,8 @@ public interface ISkinService { void shutdown(); + void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler); + + SkinPacketVersionCache getSkin(UUID playerUUID); + } 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 index a427659c..1eb15813 100644 --- 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 @@ -15,6 +15,7 @@ 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; /** @@ -304,9 +305,10 @@ public class JDBCCacheProvider implements ICacheProvider { @Override public void flush() { - long millis = System.currentTimeMillis(); - if(millis - lastFlush > 1200000l) { // 30 minutes - lastFlush = millis; + 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); 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 index 1042a204..e706fd0c 100644 --- 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 @@ -1,5 +1,7 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; +import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; + /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. * @@ -21,13 +23,13 @@ public class SimpleRateLimiter { private int count; public SimpleRateLimiter() { - timer = System.currentTimeMillis(); + timer = EaglerXVelocityAPIHelper.steadyTimeMillis(); count = 0; } public boolean rateLimit(int maxPerMinute) { int t = 60000 / maxPerMinute; - long millis = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); int decr = (int)(millis - timer) / t; if(decr > 0) { timer += decr * t; 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 index 2e221800..03e15506 100644 --- 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 @@ -1,13 +1,13 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.util.UUID; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; - -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity; +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; /** * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. @@ -28,79 +28,13 @@ public class SkinPackets { public static final int PACKET_MY_SKIN_PRESET = 0x01; public static final int PACKET_MY_SKIN_CUSTOM = 0x02; - public static final int PACKET_GET_OTHER_SKIN = 0x03; - public static final int PACKET_OTHER_SKIN_PRESET = 0x04; - public static final int PACKET_OTHER_SKIN_CUSTOM = 0x05; - public static final int PACKET_GET_SKIN_BY_URL = 0x06; - public static void processPacket(byte[] data, ConnectedPlayer sender, ISkinService skinService) throws IOException { - if(data.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - int packetId = (int)data[0] & 0xFF; - try { - switch(packetId) { - case PACKET_GET_OTHER_SKIN: - processGetOtherSkin(data, sender, skinService); - break; - case PACKET_GET_SKIN_BY_URL: - processGetOtherSkinByURL(data, sender, skinService); - break; - default: - throw new IOException("Unknown packet type " + packetId); - } - }catch(IOException ex) { - throw ex; - }catch(Throwable t) { - throw new IOException("Unhandled exception handling packet type " + packetId, t); - } - } - - private static void processGetOtherSkin(byte[] data, ConnectedPlayer sender, ISkinService skinService) throws IOException { - if(data.length != 17) { - throw new IOException("Invalid length " + data.length + " for skin request packet"); - } - UUID searchUUID = bytesToUUID(data, 1); - skinService.processGetOtherSkin(searchUUID, sender); - } - - private static void processGetOtherSkinByURL(byte[] data, ConnectedPlayer sender, ISkinService skinService) throws IOException { - if(data.length < 20) { - throw new IOException("Invalid length " + data.length + " for skin request packet"); - } - UUID searchUUID = bytesToUUID(data, 1); - int urlLength = (data[17] << 8) | data[18]; - if(data.length < 19 + urlLength) { - throw new IOException("Invalid length " + data.length + " for skin request packet with " + urlLength + " length URL"); - } - String urlStr = bytesToAscii(data, 19, urlLength); - urlStr = SkinService.sanitizeTextureURL(urlStr); - if(urlStr == null) { - throw new IOException("Invalid URL for skin request packet"); - } - URL url; - try { - url = new URL(urlStr); - }catch(MalformedURLException t) { - throw new IOException("Invalid URL for skin request packet", t); - } - String host = url.getHost(); - if(EaglerXVelocity.getEagler().getConfig().isValidSkinHost(host)) { - UUID validUUID = createEaglerURLSkinUUID(urlStr); - if(!searchUUID.equals(validUUID)) { - throw new IOException("Invalid generated UUID from skin URL"); - } - skinService.processGetOtherSkin(searchUUID, urlStr, sender); - }else { - throw new IOException("Invalid host in skin packet: " + host); - } - } - - public static void registerEaglerPlayer(UUID clientUUID, byte[] bs, ISkinService skinService) throws IOException { + 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"); } - byte[] generatedPacket; + GameMessagePacket generatedPacketV3 = null; + GameMessagePacket generatedPacketV4 = null; int skinModel = -1; int packetType = (int)bs[0] & 0xFF; switch(packetType) { @@ -108,87 +42,60 @@ public class SkinPackets { if(bs.length != 5) { throw new IOException("Invalid length " + bs.length + " for preset skin packet"); } - generatedPacket = SkinPackets.makePresetResponse(clientUUID, (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); + 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(bs.length != 2 + 16384) { - throw new IOException("Invalid length " + bs.length + " for custom skin packet"); + 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); } - setAlphaForChest(bs, (byte)255, 2); - generatedPacket = SkinPackets.makeCustomResponse(clientUUID, (skinModel = (int)bs[1] & 0xFF), bs, 2, 16384); break; default: throw new IOException("Unknown skin packet type: " + packetType); } - skinService.registerEaglercraftPlayer(clientUUID, generatedPacket, skinModel); + skinService.registerEaglercraftPlayer(clientUUID, new SkinPacketVersionCache(generatedPacketV3, generatedPacketV4), skinModel); } public static void registerEaglerPlayerFallback(UUID clientUUID, ISkinService skinService) { int skinModel = (clientUUID.hashCode() & 1) != 0 ? 1 : 0; - byte[] generatedPacket = SkinPackets.makePresetResponse(clientUUID, skinModel); - skinService.registerEaglercraftPlayer(clientUUID, generatedPacket, skinModel); + skinService.registerEaglercraftPlayer(clientUUID, SkinPacketVersionCache.createPreset( + clientUUID.getMostSignificantBits(), clientUUID.getLeastSignificantBits(), skinModel), skinModel); } - public static void setAlphaForChest(byte[] skin64x64, byte alpha, int offset) { - if(skin64x64.length - offset != 16384) { + 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[offset + ((y << 8) | (x << 2))] = alpha; + skin64x64[(y << 8) | (x << 2)] = (byte)0xFF; } } } - public static byte[] makePresetResponse(UUID uuid) { - return makePresetResponse(uuid, (uuid.hashCode() & 1) != 0 ? 1 : 0); - } - - public static byte[] makePresetResponse(UUID uuid, int presetId) { - byte[] ret = new byte[1 + 16 + 4]; - ret[0] = (byte)PACKET_OTHER_SKIN_PRESET; - UUIDToBytes(uuid, ret, 1); - ret[17] = (byte)(presetId >>> 24); - ret[18] = (byte)(presetId >>> 16); - ret[19] = (byte)(presetId >>> 8); - ret[20] = (byte)(presetId & 0xFF); - return ret; - } - - public static byte[] makeCustomResponse(UUID uuid, int model, byte[] pixels) { - return makeCustomResponse(uuid, model, pixels, 0, pixels.length); - } - - public static byte[] makeCustomResponse(UUID uuid, int model, byte[] pixels, int offset, int length) { - byte[] ret = new byte[1 + 16 + 1 + length]; - ret[0] = (byte)PACKET_OTHER_SKIN_CUSTOM; - UUIDToBytes(uuid, ret, 1); - ret[17] = (byte)model; - System.arraycopy(pixels, offset, ret, 18, length); - return ret; - } - - public static UUID bytesToUUID(byte[] bytes, int off) { - long msb = (((long) bytes[off] & 0xFFl) << 56l) | (((long) bytes[off + 1] & 0xFFl) << 48l) - | (((long) bytes[off + 2] & 0xFFl) << 40l) | (((long) bytes[off + 3] & 0xFFl) << 32l) - | (((long) bytes[off + 4] & 0xFFl) << 24l) | (((long) bytes[off + 5] & 0xFFl) << 16l) - | (((long) bytes[off + 6] & 0xFFl) << 8l) | ((long) bytes[off + 7] & 0xFFl); - long lsb = (((long) bytes[off + 8] & 0xFFl) << 56l) | (((long) bytes[off + 9] & 0xFFl) << 48l) - | (((long) bytes[off + 10] & 0xFFl) << 40l) | (((long) bytes[off + 11] & 0xFFl) << 32l) - | (((long) bytes[off + 12] & 0xFFl) << 24l) | (((long) bytes[off + 13] & 0xFFl) << 16l) - | (((long) bytes[off + 14] & 0xFFl) << 8l) | ((long) bytes[off + 15] & 0xFFl); - return new UUID(msb, lsb); - } - - private static final String hex = "0123456789abcdef"; - - public static String bytesToString(byte[] bytes, int off, int len) { - char[] ret = new char[len << 1]; - for(int i = 0; i < len; ++i) { - ret[i * 2] = hex.charAt((bytes[off + i] >> 4) & 0xF); - ret[i * 2 + 1] = hex.charAt(bytes[off + i] & 0xF); + 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; + } } - return new String(ret); } public static String bytesToAscii(byte[] bytes, int off, int len) { @@ -203,27 +110,6 @@ public class SkinPackets { return bytesToAscii(bytes, 0, bytes.length); } - public static void UUIDToBytes(UUID uuid, byte[] bytes, int off) { - long msb = uuid.getMostSignificantBits(); - long lsb = uuid.getLeastSignificantBits(); - bytes[off] = (byte)(msb >>> 56l); - bytes[off + 1] = (byte)(msb >>> 48l); - bytes[off + 2] = (byte)(msb >>> 40l); - bytes[off + 3] = (byte)(msb >>> 32l); - bytes[off + 4] = (byte)(msb >>> 24l); - bytes[off + 5] = (byte)(msb >>> 16l); - bytes[off + 6] = (byte)(msb >>> 8l); - bytes[off + 7] = (byte)(msb & 0xFFl); - bytes[off + 8] = (byte)(lsb >>> 56l); - bytes[off + 9] = (byte)(lsb >>> 48l); - bytes[off + 10] = (byte)(lsb >>> 40l); - bytes[off + 11] = (byte)(lsb >>> 32l); - bytes[off + 12] = (byte)(lsb >>> 24l); - bytes[off + 13] = (byte)(lsb >>> 16l); - bytes[off + 14] = (byte)(lsb >>> 8l); - bytes[off + 15] = (byte)(lsb & 0xFFl); - } - public static byte[] asciiString(String string) { byte[] str = new byte[string.length()]; for(int i = 0; i < str.length; ++i) { @@ -240,21 +126,4 @@ public class SkinPackets { return "slim".equalsIgnoreCase(modelName) ? 1 : 0; } - public static byte[] rewriteUUID(UUID newUUID, byte[] pkt) { - byte[] ret = new byte[pkt.length]; - System.arraycopy(pkt, 0, ret, 0, pkt.length); - UUIDToBytes(newUUID, ret, 1); - return ret; - } - - public static byte[] rewriteUUIDModel(UUID newUUID, byte[] pkt, int model) { - byte[] ret = new byte[pkt.length]; - System.arraycopy(pkt, 0, ret, 0, pkt.length); - UUIDToBytes(newUUID, ret, 1); - if(ret[0] == (byte)PACKET_OTHER_SKIN_CUSTOM) { - ret[17] = (byte)model; - } - return ret; - } - } 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 index a1649f6e..b8bed998 100644 --- 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 @@ -18,8 +18,7 @@ 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.proxy.messages.ChannelIdentifier; -import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; +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; @@ -27,14 +26,17 @@ 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.EaglerPipeline; 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; /** - * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. + * 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 @@ -52,19 +54,17 @@ public class SkinService implements ISkinService { public static final int masterRateLimitPerPlayer = 250; - public static final ChannelIdentifier CHANNEL = new LegacyChannelIdentifier("EAG|Skins-1.8"); - - private final Map onlinePlayersCache = new HashMap(); + private final Map onlinePlayersCache = new HashMap<>(); private final Multimap onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build(); - private final Map onlinePlayersToTexturesMap = new HashMap(); - private final Map foreignSkinCache = new HashMap(); + private final Map onlinePlayersToTexturesMap = new HashMap<>(); + private final Map foreignSkinCache = new HashMap<>(); - private final Map pendingTextures = new HashMap(); - private final Map pendingUUIDs = new HashMap(); - private final Map pendingNameLookups = new HashMap(); + private final Map pendingTextures = new HashMap<>(); + private final Map pendingUUIDs = new HashMap<>(); + private final Map pendingNameLookups = new HashMap<>(); - private final Object2IntMap antagonists = new Object2IntOpenHashMap(); - private long antagonistCooldown = System.currentTimeMillis(); + private final Object2IntMap antagonists = new Object2IntOpenHashMap<>(); + private long antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis(); private final Consumer> antagonistLogger = new Consumer>() { @@ -93,26 +93,26 @@ public class SkinService implements ISkinService { protected static class CachedForeignSkin { protected final UUID uuid; - protected final byte[] data; + protected final SkinPacketVersionCache data; protected final int modelKnown; protected long lastHit; - protected CachedForeignSkin(UUID uuid, byte[] data, int modelKnown) { + protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) { this.uuid = uuid; this.data = data; this.modelKnown = modelKnown; - this.lastHit = System.currentTimeMillis(); + this.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); } } protected static class CachedPlayerSkin { - protected final byte[] data; + protected final SkinPacketVersionCache data; protected final UUID textureUUID; protected final int modelId; - protected CachedPlayerSkin(byte[] data, UUID textureUUID, int modelId) { + protected CachedPlayerSkin(SkinPacketVersionCache data, UUID textureUUID, int modelId) { this.data = data; this.textureUUID = textureUUID; this.modelId = modelId; @@ -136,12 +136,12 @@ public class SkinService implements ISkinService { Consumer> antagonistsCallback) { this.textureUUID = textureUUID; this.textureURL = textureURL; - this.antagonists = new LinkedHashSet(); + this.antagonists = new LinkedHashSet<>(); this.antagonists.add(caller); - this.callbacks = new LinkedList(); + this.callbacks = new LinkedList<>(); this.callbacks.add(callback); this.antagonistsCallback = antagonistsCallback; - this.initializedTime = System.currentTimeMillis(); + this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); this.finalized = false; } @@ -177,12 +177,12 @@ public class SkinService implements ISkinService { protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer callback, Consumer> antagonistsCallback) { this.profileUUID = profileUUID; - this.antagonists = new LinkedHashSet(); + this.antagonists = new LinkedHashSet<>(); this.antagonists.add(caller); - this.callbacks = new LinkedList(); + this.callbacks = new LinkedList<>(); this.callbacks.add(callback); this.antagonistsCallback = antagonistsCallback; - this.initializedTime = System.currentTimeMillis(); + this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); this.finalized = false; } @@ -218,12 +218,12 @@ public class SkinService implements ISkinService { protected PendingProfileNameLookup(String profileName, UUID caller, Consumer callback, Consumer> antagonistsCallback) { this.profileName = profileName; - this.antagonists = new LinkedHashSet(); + this.antagonists = new LinkedHashSet<>(); this.antagonists.add(caller); - this.callbacks = new LinkedList(); + this.callbacks = new LinkedList<>(); this.callbacks.add(callback); this.antagonistsCallback = antagonistsCallback; - this.initializedTime = System.currentTimeMillis(); + this.initializedTime = EaglerXVelocityAPIHelper.steadyTimeMillis(); this.finalized = false; } @@ -247,7 +247,7 @@ public class SkinService implements ISkinService { public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays, int maxObjects, int maxProfiles) { - antagonistCooldown = System.currentTimeMillis(); + antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis(); if(cacheProvider == null) { cacheProvider = JDBCCacheProvider.initialize(uri, driverClass, driverPath, keepObjectsDays, keepProfilesDays, maxObjects, maxProfiles); @@ -255,9 +255,8 @@ public class SkinService implements ISkinService { resetMaps(); } - public void processGetOtherSkin(final UUID searchUUID, final ConnectedPlayer sender) { - EaglerPlayerData eaglerHandler = EaglerPipeline.getEaglerHandle(sender); - if(!eaglerHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { + public void processGetOtherSkin(final UUID searchUUID, final EaglerPlayerData sender) { + if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { return; } @@ -267,7 +266,7 @@ public class SkinService implements ISkinService { } if(maybeCachedPacket != null) { - sender.sendPluginMessage(SkinService.CHANNEL, maybeCachedPacket.data); + sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol())); }else { Player player = EaglerXVelocity.proxy().getPlayer(searchUUID).orElse(null); UUID playerTexture; @@ -286,14 +285,16 @@ public class SkinService implements ISkinService { maybeCachedPacket = onlinePlayersCache.get(uuid); } if(maybeCachedPacket != null) { - byte[] rewritten = SkinPackets.rewriteUUID(searchUUID, maybeCachedPacket.data); + SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( + maybeCachedPacket.data, searchUUID.getMostSignificantBits(), + searchUUID.getLeastSignificantBits()); if(player != null) { synchronized(onlinePlayersCache) { onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten, maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); } } - sender.sendPluginMessage(SkinService.CHANNEL, rewritten); + sender.sendEaglerMessage(rewritten.get(sender.getEaglerProtocol())); return; } } @@ -306,87 +307,92 @@ public class SkinService implements ISkinService { if(player != null) { synchronized(onlinePlayersCache) { onlinePlayersCache.put(searchUUID, - new CachedPlayerSkin(SkinPackets.rewriteUUID(searchUUID, foreignSkin.data), + new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, + searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()), playerTexture, foreignSkin.modelKnown)); } synchronized(foreignSkinCache) { foreignSkinCache.remove(playerTexture); } }else { - foreignSkin.lastHit = System.currentTimeMillis(); + foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); } - sender.sendPluginMessage(SkinService.CHANNEL, foreignSkin.data); + sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); return; } } if(player != null && (player instanceof ConnectedPlayer)) { - if(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 = url.getAsString(); - urlStr = SkinService.sanitizeTextureURL(urlStr); - if(urlStr == null) { - break; + 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 = SkinService.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()); } - 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; + synchronized(foreignSkinCache) { + foreignSkin = foreignSkinCache.remove(skinUUID); + } + if(foreignSkin != null) { + registerTextureToPlayerAssociation(skinUUID, searchUUID); + SkinPacketVersionCache rewrite = SkinPacketVersionCache + .rewriteUUIDModel(foreignSkin.data, + searchUUID.getMostSignificantBits(), + searchUUID.getLeastSignificantBits(), model); + synchronized(onlinePlayersCache) { + onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model)); } - UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr); - - CachedForeignSkin foreignSkin; - synchronized(foreignSkinCache) { - foreignSkin = foreignSkinCache.remove(skinUUID); - } - if(foreignSkin != null) { - registerTextureToPlayerAssociation(skinUUID, searchUUID); - byte[] rewrite = SkinPackets.rewriteUUIDModel(searchUUID, foreignSkin.data, model); - synchronized(onlinePlayersCache) { - onlinePlayersCache.put(searchUUID, new CachedPlayerSkin( - rewrite, skinUUID, model)); - } - sender.sendPluginMessage(SkinService.CHANNEL, rewrite); - return; - } - - // download player skin, put in onlinePlayersCache, no limit - - if(!isLimitedAsAntagonist(player.getUniqueId())) { - processResolveURLTextureForOnline(sender, searchUUID, skinUUID, urlStr, 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) { } + }catch(Throwable t) { } } } } } if(!isLimitedAsAntagonist(player.getUniqueId())) { - if(player.isOnlineMode()) { - processResolveProfileTextureByUUIDForOnline(sender, searchUUID); - }else { - processResolveProfileTextureByNameForOnline(sender, player.getUsername(), searchUUID); - } + doAsync(() -> { + if(player.isOnlineMode()) { + processResolveProfileTextureByUUIDForOnline(sender, searchUUID); + }else { + processResolveProfileTextureByNameForOnline(sender, player.getUsername(), searchUUID); + } + }); } }else { CachedForeignSkin foreignSkin; @@ -394,23 +400,30 @@ public class SkinService implements ISkinService { foreignSkin = foreignSkinCache.get(searchUUID); } if(foreignSkin != null) { - foreignSkin.lastHit = System.currentTimeMillis(); - sender.sendPluginMessage(SkinService.CHANNEL, foreignSkin.data); + foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); + sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); }else { - if (eaglerHandler.skinUUIDLookupRateLimiter + if (sender.skinUUIDLookupRateLimiter .rateLimit(EaglerXVelocity.getEagler().getConfig().getUuidRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) { - processResolveProfileTextureByUUIDForeign(sender, searchUUID); + 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, ConnectedPlayer sender) { + public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) { EaglerVelocityConfig config = EaglerXVelocity.getEagler().getConfig(); - EaglerPlayerData eaglerHandler = EaglerPipeline.getEaglerHandle(sender); - if(!eaglerHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { + if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { return; } CachedForeignSkin foreignSkin; @@ -418,8 +431,8 @@ public class SkinService implements ISkinService { foreignSkin = foreignSkinCache.get(searchUUID); } if(foreignSkin != null) { - foreignSkin.lastHit = System.currentTimeMillis(); - sender.sendPluginMessage(SkinService.CHANNEL, foreignSkin.data); + foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis(); + sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol())); }else { Collection possiblePlayers; synchronized(onlinePlayersFromTexturesMap) { @@ -433,22 +446,26 @@ public class SkinService implements ISkinService { maybeCachedPacket = onlinePlayersCache.get(uuid); } if(maybeCachedPacket != null) { - byte[] rewritten = SkinPackets.rewriteUUID(searchUUID, maybeCachedPacket.data); - synchronized(onlinePlayersCache) { - onlinePlayersCache.put(searchUUID, maybeCachedPacket); - } - sender.sendPluginMessage(SkinService.CHANNEL, rewritten); + sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol(), + searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits())); return; } } } - if(eaglerHandler.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) { - processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL, -1); + if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds + sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(), + searchUUID.getLeastSignificantBits(), 0)); + return; + } + if(sender.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) { + doAsync(() -> { + processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL, -1); + }); } } } - private void processResolveURLTextureForOnline(final ConnectedPlayer initiator, final UUID onlineCacheUUID, + 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); @@ -463,32 +480,38 @@ public class SkinService implements ISkinService { skin = onlinePlayersCache.get(onlineCacheUUID); } if(skin != null) { - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } } }); } }else { - PendingTextureDownload newTask = new PendingTextureDownload( - skinUUID, urlStr, initiator.getUniqueId(), new Consumer() { + 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(SkinPackets.makeCustomResponse(onlineCacheUUID, modelId, t), skinUUID, modelId); - }else { - skin = new CachedPlayerSkin(SkinPackets.makePresetResponse(onlineCacheUUID), null, -1); + @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); + } + synchronized (onlinePlayersCache) { + onlinePlayersCache.put(onlineCacheUUID, skin); + } + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } - synchronized(onlinePlayersCache) { - onlinePlayersCache.put(onlineCacheUUID, skin); - } - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); - } - - }, antagonistLogger); + + }, antagonistLogger); try { AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); }catch(CancelException ex) { @@ -499,7 +522,7 @@ public class SkinService implements ISkinService { } } - private void processResolveURLTextureForForeign(final ConnectedPlayer initiator, final UUID foreignCacheUUID, + 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); @@ -514,30 +537,39 @@ public class SkinService implements ISkinService { skin = foreignSkinCache.get(foreignCacheUUID); } if(skin != null) { - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } } }); } }else { - PendingTextureDownload newTask = new PendingTextureDownload(skinUUID, urlStr, initiator.getUniqueId(), new Consumer() { + 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, SkinPackets.makeCustomResponse(foreignCacheUUID, modelId, t), modelId); - }else { - skin = new CachedForeignSkin(foreignCacheUUID, SkinPackets.makePresetResponse(foreignCacheUUID), -1); + @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); + } + synchronized (foreignSkinCache) { + foreignSkinCache.put(foreignCacheUUID, skin); + } + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } - synchronized(foreignSkinCache) { - foreignSkinCache.put(foreignCacheUUID, skin); - } - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); - } - - }, antagonistLogger); + + }, antagonistLogger); try { AsyncSkinProvider.downloadSkin(skinUUID, urlStr, cacheProvider, newTask); }catch(CancelException ex) { @@ -548,7 +580,7 @@ public class SkinService implements ISkinService { } } - private void processResolveProfileTextureByUUIDForOnline(final ConnectedPlayer initiator, final UUID playerUUID) { + private void processResolveProfileTextureByUUIDForOnline(final EaglerPlayerData initiator, final UUID playerUUID) { synchronized(pendingUUIDs) { PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); if(alreadyPending != null) { @@ -563,7 +595,7 @@ public class SkinService implements ISkinService { skin = onlinePlayersCache.get(playerUUID); } if(skin != null) { - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } }else { processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, @@ -581,16 +613,22 @@ public class SkinService implements ISkinService { public void accept(CacheFetchedProfile t) { if(t == null || t.texture == null) { CachedPlayerSkin skin; - if(t == null) { - skin = new CachedPlayerSkin(SkinPackets.makePresetResponse(playerUUID), null, -1); - }else { - skin = new CachedPlayerSkin(SkinPackets.makePresetResponse(playerUUID, - SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1); + 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); } synchronized(onlinePlayersCache) { onlinePlayersCache.put(playerUUID, skin); } - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); }else { processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture, SkinPackets.getModelId(t.model)); @@ -608,7 +646,7 @@ public class SkinService implements ISkinService { } } - private void processResolveProfileTextureByNameForOnline(final ConnectedPlayer initiator, final String playerName, final UUID mapUUID) { + private void processResolveProfileTextureByNameForOnline(final EaglerPlayerData initiator, final String playerName, final UUID mapUUID) { synchronized(pendingNameLookups) { PendingProfileNameLookup alreadyPending = pendingNameLookups.get(playerName); if(alreadyPending != null) { @@ -623,7 +661,7 @@ public class SkinService implements ISkinService { skin = onlinePlayersCache.get(t.uuid); } if(skin != null) { - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } }else { processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, @@ -641,16 +679,20 @@ public class SkinService implements ISkinService { public void accept(CacheFetchedProfile t) { if(t == null || t.texture == null) { CachedPlayerSkin skin; - if(t == null) { - skin = new CachedPlayerSkin(SkinPackets.makePresetResponse(mapUUID), null, -1); - }else { - skin = new CachedPlayerSkin(SkinPackets.makePresetResponse(mapUUID, + 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); } synchronized(onlinePlayersCache) { onlinePlayersCache.put(mapUUID, skin); } - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); }else { processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture, SkinPackets.getModelId(t.model)); @@ -668,7 +710,7 @@ public class SkinService implements ISkinService { } } - private void processResolveProfileTextureByUUIDForeign(final ConnectedPlayer initiator, final UUID playerUUID) { + private void processResolveProfileTextureByUUIDForeign(final EaglerPlayerData initiator, final UUID playerUUID) { synchronized(pendingUUIDs) { PendingProfileUUIDLookup alreadyPending = pendingUUIDs.get(playerUUID); if(alreadyPending != null) { @@ -683,7 +725,7 @@ public class SkinService implements ISkinService { skin = foreignSkinCache.get(playerUUID); } if(skin != null) { - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); } }else { processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, @@ -701,16 +743,22 @@ public class SkinService implements ISkinService { public void accept(CacheFetchedProfile t) { if(t == null || t.texture == null) { CachedForeignSkin skin; - if(t == null) { - skin = new CachedForeignSkin(playerUUID, SkinPackets.makePresetResponse(playerUUID), -1); - }else { - skin = new CachedForeignSkin(playerUUID, SkinPackets.makePresetResponse( - playerUUID, SkinPackets.getModelId(t.model) == 1 ? 1 : 0), -1); + 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); } synchronized(foreignSkinCache) { foreignSkinCache.put(playerUUID, skin); } - initiator.sendPluginMessage(SkinService.CHANNEL, skin.data); + initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol())); }else { processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture, SkinPackets.getModelId(t.model)); @@ -728,7 +776,7 @@ public class SkinService implements ISkinService { } } - public void registerEaglercraftPlayer(UUID clientUUID, byte[] generatedPacket, int modelId) { + public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { synchronized(foreignSkinCache) { foreignSkinCache.remove(clientUUID); } @@ -795,9 +843,463 @@ public class SkinService implements ISkinService { } } } + + public void processForceSkin(UUID playerUUID, EaglerPlayerData eaglerHandler) { + CachedPlayerSkin maybeCachedPacket; + synchronized(onlinePlayersCache) { + maybeCachedPacket = onlinePlayersCache.get(playerUUID); + } + + if(maybeCachedPacket != null) { + eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4()); + }else { + UUID playerTexture; + synchronized(onlinePlayersToTexturesMap) { + playerTexture = onlinePlayersToTexturesMap.get(playerUUID); + } + if(playerTexture != null) { + Collection possiblePlayers; + synchronized(onlinePlayersFromTexturesMap) { + possiblePlayers = onlinePlayersFromTexturesMap.get(playerTexture); + } + boolean playersExist = possiblePlayers.size() > 0; + if(playersExist) { + for(UUID uuid : possiblePlayers) { + synchronized(onlinePlayersCache) { + maybeCachedPacket = onlinePlayersCache.get(uuid); + } + if(maybeCachedPacket != null) { + SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID( + maybeCachedPacket.data, playerUUID.getMostSignificantBits(), + playerUUID.getLeastSignificantBits()); + synchronized(onlinePlayersCache) { + onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten, + maybeCachedPacket.textureUUID, maybeCachedPacket.modelId)); + } + eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4()); + return; + } + } + } + CachedForeignSkin foreignSkin; + synchronized(foreignSkinCache) { + foreignSkin = foreignSkinCache.get(playerTexture); + } + if(foreignSkin != null && foreignSkin.modelKnown != -1) { + synchronized(onlinePlayersCache) { + onlinePlayersCache.put(playerUUID, + new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data, + playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()), + playerTexture, foreignSkin.modelKnown)); + } + synchronized(foreignSkinCache) { + 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 = SkinService.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; + synchronized(foreignSkinCache) { + foreignSkin = foreignSkinCache.remove(skinUUID); + } + if(foreignSkin != null) { + registerTextureToPlayerAssociation(skinUUID, playerUUID); + SkinPacketVersionCache rewrite = SkinPacketVersionCache + .rewriteUUIDModel(foreignSkin.data, + playerUUID.getMostSignificantBits(), + playerUUID.getLeastSignificantBits(), model); + synchronized(onlinePlayersCache) { + 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; + synchronized(foreignSkinCache) { + 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; + synchronized(onlinePlayersCache) { + 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); + } + synchronized (onlinePlayersCache) { + 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; + synchronized(foreignSkinCache) { + 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); + } + synchronized (foreignSkinCache) { + 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; + synchronized(onlinePlayersCache) { + 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); + } + synchronized(onlinePlayersCache) { + 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; + synchronized(onlinePlayersCache) { + 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); + } + synchronized(onlinePlayersCache) { + 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; + synchronized(foreignSkinCache) { + 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); + } + synchronized(foreignSkinCache) { + 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 = System.currentTimeMillis(); + long millis = EaglerXVelocityAPIHelper.steadyTimeMillis(); synchronized(foreignSkinCache) { Iterator itr = foreignSkinCache.values().iterator(); @@ -872,6 +1374,14 @@ public class SkinService implements ISkinService { cacheProvider.flush(); } + public SkinPacketVersionCache getSkin(UUID playerUUID) { + CachedPlayerSkin skin; + synchronized(onlinePlayersCache) { + skin = onlinePlayersCache.get(playerUUID); + } + return skin != null ? skin.data : null; + } + public void shutdown() { resetMaps(); if(cacheProvider != null) { @@ -916,6 +1426,10 @@ public class SkinService implements ISkinService { } } + 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); 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 index 7c8b8cd9..6591dfc8 100644 --- 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 @@ -8,9 +8,10 @@ import java.util.UUID; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -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.pkt.server.SPacketOtherSkinPresetEAG; +import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -34,16 +35,16 @@ public class SkinServiceOffline implements ISkinService { private static class CachedSkin { protected final UUID uuid; - protected final byte[] packet; + protected final SkinPacketVersionCache packet; - protected CachedSkin(UUID uuid, byte[] packet) { + protected CachedSkin(UUID uuid, SkinPacketVersionCache packet) { this.uuid = uuid; this.packet = packet; } } - private final Map skinCache = new HashMap(); + private final Map skinCache = new HashMap<>(); private final Multimap onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build(); @@ -54,21 +55,20 @@ public class SkinServiceOffline implements ISkinService { } } - public void processGetOtherSkin(UUID searchUUID, ConnectedPlayer sender) { - if(EaglerPipeline.getEaglerHandle(sender).skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) { - CachedSkin cached; - synchronized(skinCache) { - cached = skinCache.get(searchUUID); - } - if(cached != null) { - sender.sendPluginMessage(SkinService.CHANNEL, cached.packet); - }else { - sender.sendPluginMessage(SkinService.CHANNEL, SkinPackets.makePresetResponse(searchUUID)); - } + public void processGetOtherSkin(UUID searchUUID, EaglerPlayerData sender) { + CachedSkin cached; + synchronized(skinCache) { + 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, ConnectedPlayer sender) { + public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) { Collection uuids; synchronized(onlinePlayersFromTexturesMap) { uuids = onlinePlayersFromTexturesMap.get(searchUUID); @@ -80,15 +80,23 @@ public class SkinServiceOffline implements ISkinService { while(uuidItr.hasNext()) { cached = skinCache.get(uuidItr.next()); if(cached != null) { - sender.sendPluginMessage(SkinService.CHANNEL, SkinPackets.rewriteUUID(searchUUID, cached.packet)); + sender.sendEaglerMessage(cached.packet.get(sender.getEaglerProtocol(), + searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits())); + return; } } } } - sender.sendPluginMessage(SkinService.CHANNEL, SkinPackets.makePresetResponse(searchUUID)); + 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, byte[] generatedPacket, int modelId) { + public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) { synchronized(skinCache) { skinCache.put(clientUUID, new CachedSkin(clientUUID, generatedPacket)); } @@ -106,6 +114,16 @@ public class SkinServiceOffline implements ISkinService { } } + public void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler) { + CachedSkin cached; + synchronized(skinCache) { + cached = skinCache.get(playerUUID); + } + if(cached != null) { + initialHandler.sendEaglerMessage(cached.packet.getForceClientV4()); + } + } + public void flush() { // no } @@ -116,4 +134,12 @@ public class SkinServiceOffline implements ISkinService { } } + public SkinPacketVersionCache getSkin(UUID playerUUID) { + CachedSkin cached; + synchronized(skinCache) { + cached = skinCache.get(playerUUID); + } + return cached != null ? cached.packet : null; + } + } 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 index eb8babba..9123e3b3 100644 --- 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 @@ -45,7 +45,7 @@ public class EaglerDrivers { 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.toString()); + 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!"); @@ -67,7 +67,7 @@ public class EaglerDrivers { driversJARs.put(address, classLoader); } - Class loadedDriver; + Class loadedDriver; try { loadedDriver = classLoader.loadClass(driverClass); }catch(ClassNotFoundException ex) { @@ -93,8 +93,8 @@ public class EaglerDrivers { return sqlDriver; } - private static final Map driversJARs = new HashMap(); - private static final Map driversDrivers = new HashMap(); + 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 { 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 index 1611c606..ac23c6ce 100644 --- 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 @@ -5,6 +5,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper; + /** * Copyright (c) 2022 ayunami2000. All Rights Reserved. * @@ -42,7 +44,7 @@ public class ExpiringSet extends HashSet { public void checkForExpirations() { Iterator iterator = this.timestamps.keySet().iterator(); - long now = System.currentTimeMillis(); + long now = EaglerXVelocityAPIHelper.steadyTimeMillis(); while (iterator.hasNext()) { T element = iterator.next(); if (super.contains(element)) { @@ -61,7 +63,7 @@ public class ExpiringSet extends HashSet { public boolean add(T o) { checkForExpirations(); boolean success = super.add(o); - if (success) timestamps.put(o, System.currentTimeMillis()); + if (success) timestamps.put(o, EaglerXVelocityAPIHelper.steadyTimeMillis()); return success; } 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 index 55ffbce8..808366c1 100644 --- 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 @@ -1,5 +1,7 @@ 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; @@ -8,9 +10,19 @@ import java.util.Set; import java.util.UUID; import com.velocitypowered.api.proxy.server.ServerInfo; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeline; +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.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; /** * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. @@ -30,9 +42,9 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPipeli public class VoiceServerImpl { private final ServerInfo server; - private final byte[] iceServersPacket; + private final GameMessagePacket iceServersPacket; - private final Map voicePlayers = new HashMap<>(); + private final Map voicePlayers = new HashMap<>(); private final Map> voiceRequests = new HashMap<>(); private final Set voicePairs = new HashSet<>(); @@ -71,27 +83,31 @@ public class VoiceServerImpl { } } - VoiceServerImpl(ServerInfo server, byte[] iceServersPacket) { + VoiceServerImpl(ServerInfo server, GameMessagePacket iceServersPacket) { this.server = server; this.iceServersPacket = iceServersPacket; } - public void handlePlayerLoggedIn(ConnectedPlayer player) { - player.sendPluginMessage(VoiceService.CHANNEL, 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(ConnectedPlayer player) { + public void handlePlayerLoggedOut(EaglerPlayerData player) { removeUser(player.getUniqueId()); } - void handleVoiceSignalPacketTypeRequest(UUID player, ConnectedPlayer sender) { + void handleVoiceSignalPacketTypeRequest(UUID player, EaglerPlayerData sender) { synchronized (voicePlayers) { UUID senderUUID = sender.getUniqueId(); if (senderUUID.equals(player)) return; // prevent duplicates if (!voicePlayers.containsKey(senderUUID)) return; - ConnectedPlayer targetPlayerCon = voicePlayers.get(player); + EaglerPlayerData targetPlayerCon = voicePlayers.get(player); if (targetPlayerCon == null) return; VoicePair newPair = new VoicePair(player, senderUUID); @@ -116,18 +132,32 @@ public class VoiceServerImpl { voiceRequests.remove(senderUUID); // send each other add data voicePairs.add(newPair); - targetPlayerCon.sendPluginMessage(VoiceService.CHANNEL, - VoiceSignalPackets.makeVoiceSignalPacketConnect(senderUUID, false)); - sender.sendPluginMessage(VoiceService.CHANNEL, - VoiceSignalPackets.makeVoiceSignalPacketConnect(player, true)); + 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(ConnectedPlayer sender) { - if(!EaglerPipeline.getEaglerHandle(sender).voiceConnectRateLimiter.rateLimit(VOICE_CONNECT_RATELIMIT)) { + 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); + } synchronized (voicePlayers) { if (voicePlayers.containsKey(sender.getUniqueId())) { return; @@ -137,87 +167,103 @@ public class VoiceServerImpl { if (hasNoOtherPlayers) { return; } - byte[] packetToBroadcast = VoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values()); - for (ConnectedPlayer userCon : voicePlayers.values()) { - userCon.sendPluginMessage(VoiceService.CHANNEL, packetToBroadcast); + 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())); + } + GameMessagePacket packetToBroadcast = new SPacketVoiceSignalGlobalEAG(userDatas); + for (EaglerPlayerData userCon : voicePlayers.values()) { + userCon.sendEaglerMessage(packetToBroadcast); } } } - void handleVoiceSignalPacketTypeICE(UUID player, String str, ConnectedPlayer sender) { - ConnectedPlayer pass; + 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) { - pass.sendPluginMessage(VoiceService.CHANNEL, - VoiceSignalPackets.makeVoiceSignalPacketICE(sender.getUniqueId(), str)); + UUID uuid = sender.getUniqueId(); + pass.sendEaglerMessage( + new SPacketVoiceSignalICEEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); } } - void handleVoiceSignalPacketTypeDesc(UUID player, String str, ConnectedPlayer sender) { - ConnectedPlayer pass; + 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) { - pass.sendPluginMessage(VoiceService.CHANNEL, - VoiceSignalPackets.makeVoiceSignalPacketDesc(sender.getUniqueId(), str)); + UUID uuid = sender.getUniqueId(); + pass.sendEaglerMessage( + new SPacketVoiceSignalDescEAG(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), str)); } } - void handleVoiceSignalPacketTypeDisconnect(UUID player, ConnectedPlayer sender) { - if (player != null) { - synchronized (voicePlayers) { - if (!voicePlayers.containsKey(player)) { - return; + void handleVoiceSignalPacketTypeDisconnect(EaglerPlayerData sender) { + removeUser(sender.getUniqueId()); + } + + void handleVoiceSignalPacketTypeDisconnectPeer(UUID player, EaglerPlayerData sender) { + 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; } - byte[] userDisconnectPacket = null; - 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(); - ConnectedPlayer conn = voicePlayers.get(target); - if (conn != null) { - if (userDisconnectPacket == null) { - userDisconnectPacket = VoiceSignalPackets.makeVoiceSignalPacketDisconnect(player); - } - conn.sendPluginMessage(VoiceService.CHANNEL, userDisconnectPacket); - } - sender.sendPluginMessage(VoiceService.CHANNEL, - VoiceSignalPackets.makeVoiceSignalPacketDisconnect(target)); + if (target != null) { + pairsItr.remove(); + EaglerPlayerData conn = voicePlayers.get(target); + if (conn != null) { + conn.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG(player.getMostSignificantBits(), + player.getLeastSignificantBits())); } + sender.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG(target.getMostSignificantBits(), + target.getLeastSignificantBits())); } } - } else { - removeUser(sender.getUniqueId()); } } public void removeUser(UUID user) { synchronized (voicePlayers) { - if (voicePlayers.remove(user) == null) { + EaglerPlayerData connRemove; + if ((connRemove = voicePlayers.remove(user)) == null) { return; + }else { + 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) { - byte[] voicePlayersPkt = VoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values()); - for (ConnectedPlayer userCon : voicePlayers.values()) { + 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())); + } + GameMessagePacket voicePlayersPkt = new SPacketVoiceSignalGlobalEAG(userDatas); + for (EaglerPlayerData userCon : voicePlayers.values()) { if (!user.equals(userCon.getUniqueId())) { - userCon.sendPluginMessage(VoiceService.CHANNEL, voicePlayersPkt); + userCon.sendEaglerMessage(voicePlayersPkt); } } } - byte[] userDisconnectPacket = null; Iterator pairsItr = voicePairs.iterator(); while (pairsItr.hasNext()) { VoicePair voicePair = pairsItr.next(); @@ -230,12 +276,10 @@ public class VoiceServerImpl { if (target != null) { pairsItr.remove(); if (voicePlayers.size() > 0) { - ConnectedPlayer conn = voicePlayers.get(target); + EaglerPlayerData conn = voicePlayers.get(target); if (conn != null) { - if (userDisconnectPacket == null) { - userDisconnectPacket = VoiceSignalPackets.makeVoiceSignalPacketDisconnect(user); - } - conn.sendPluginMessage(VoiceService.CHANNEL, userDisconnectPacket); + conn.sendEaglerMessage(new SPacketVoiceSignalDisconnectPeerEAG( + user.getMostSignificantBits(), user.getLeastSignificantBits())); } } } @@ -243,4 +287,13 @@ public class VoiceServerImpl { } } + EnumVoiceState getPlayerVoiceState(UUID uniqueId) { + synchronized (voicePlayers) { + if(voicePlayers.containsKey(uniqueId)) { + return EnumVoiceState.ENABLED; + } + } + return EnumVoiceState.DISABLED; + } + } 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 index a96aa564..a0c273ff 100644 --- 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 @@ -5,14 +5,18 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import com.velocitypowered.api.proxy.messages.ChannelIdentifier; -import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +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; /** * Copyright (c) 2024 lax1dude. All Rights Reserved. @@ -31,15 +35,13 @@ import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.config.EaglerVeloci */ public class VoiceService { - public static final ChannelIdentifier CHANNEL = new LegacyChannelIdentifier("EAG|Voice-1.8"); - - private final Map serverMap = new HashMap(); - private final byte[] disableVoicePacket; + private final Map serverMap = new HashMap<>(); + private final GameMessagePacket disableVoicePacket; public VoiceService(EaglerVelocityConfig conf) { - this.disableVoicePacket = VoiceSignalPackets.makeVoiceSignalPacketAllowed(false, null); + this.disableVoicePacket = new SPacketVoiceSignalAllowedEAG(false, null); String[] iceServers = conf.getICEServers().toArray(new String[conf.getICEServers().size()]); - byte[] iceServersPacket = VoiceSignalPackets.makeVoiceSignalPacketAllowed(true, iceServers); + SPacketVoiceSignalAllowedEAG iceServersPacket = new SPacketVoiceSignalAllowedEAG(true, iceServers); Collection servers = EaglerXVelocity.proxy().getAllServers(); for(RegisteredServer s : servers) { ServerInfo inf = s.getServerInfo(); @@ -49,33 +51,37 @@ public class VoiceService { } } - public void handlePlayerLoggedIn(ConnectedPlayer player) { + public void handlePlayerLoggedIn(EaglerPlayerData player) { } - public void handlePlayerLoggedOut(ConnectedPlayer player) { + public void handlePlayerLoggedOut(EaglerPlayerData player) { for(VoiceServerImpl svr : serverMap.values()) { svr.handlePlayerLoggedOut(player); } } - public void handleServerConnected(ConnectedPlayer player, ServerInfo server) { + public void handleServerConnected(EaglerPlayerData player, ServerInfo server) { VoiceServerImpl svr = serverMap.get(server.getName()); if(svr != null) { svr.handlePlayerLoggedIn(player); }else { - player.sendPluginMessage(CHANNEL, disableVoicePacket); + 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(ConnectedPlayer player, ServerInfo server) { + public void handleServerDisconnected(EaglerPlayerData player, ServerInfo server) { VoiceServerImpl svr = serverMap.get(server.getName()); if(svr != null) { svr.handlePlayerLoggedOut(player); } } - void handleVoiceSignalPacketTypeRequest(UUID player, ConnectedPlayer sender) { + public void handleVoiceSignalPacketTypeRequest(UUID player, EaglerPlayerData sender) { if(sender.getConnectedServer() != null) { VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); if(svr != null) { @@ -84,7 +90,7 @@ public class VoiceService { } } - void handleVoiceSignalPacketTypeConnect(ConnectedPlayer sender) { + public void handleVoiceSignalPacketTypeConnect(EaglerPlayerData sender) { if(sender.getConnectedServer() != null) { VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); if(svr != null) { @@ -93,7 +99,7 @@ public class VoiceService { } } - void handleVoiceSignalPacketTypeICE(UUID player, String str, ConnectedPlayer 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) { @@ -102,7 +108,7 @@ public class VoiceService { } } - void handleVoiceSignalPacketTypeDesc(UUID player, String str, ConnectedPlayer 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) { @@ -111,13 +117,31 @@ public class VoiceService { } } - void handleVoiceSignalPacketTypeDisconnect(UUID player, ConnectedPlayer sender) { + public void handleVoiceSignalPacketTypeDisconnect(EaglerPlayerData sender) { if(sender.getConnectedServer() != null) { VoiceServerImpl svr = serverMap.get(sender.getConnectedServer().getServerInfo().getName()); if(svr != null) { - svr.handleVoiceSignalPacketTypeDisconnect(player, sender); + 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; + } + } + } diff --git a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceSignalPackets.java b/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceSignalPackets.java deleted file mode 100644 index 44ce5c1e..00000000 --- a/gateway/EaglercraftXVelocity/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/voice/VoiceSignalPackets.java +++ /dev/null @@ -1,195 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.voice; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.UUID; - -import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.protocol.ProtocolUtils; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - -/** - * 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. - * - */ -public class VoiceSignalPackets { - - static final int VOICE_SIGNAL_ALLOWED = 0; - static final int VOICE_SIGNAL_REQUEST = 0; - static final int VOICE_SIGNAL_CONNECT = 1; - static final int VOICE_SIGNAL_DISCONNECT = 2; - static final int VOICE_SIGNAL_ICE = 3; - static final int VOICE_SIGNAL_DESC = 4; - static final int VOICE_SIGNAL_GLOBAL = 5; - - public static void processPacket(byte[] data, ConnectedPlayer sender, VoiceService voiceService) throws IOException { - int packetId = -1; - if(data.length == 0) { - throw new IOException("Zero-length packet recieved"); - } - try { - ByteBuf buffer = Unpooled.wrappedBuffer(data).writerIndex(data.length); - packetId = buffer.readUnsignedByte(); - switch(packetId) { - case VOICE_SIGNAL_REQUEST: { - voiceService.handleVoiceSignalPacketTypeRequest(ProtocolUtils.readUuid(buffer), sender); - break; - } - case VOICE_SIGNAL_CONNECT: { - voiceService.handleVoiceSignalPacketTypeConnect(sender); - break; - } - case VOICE_SIGNAL_ICE: { - voiceService.handleVoiceSignalPacketTypeICE(ProtocolUtils.readUuid(buffer), ProtocolUtils.readString(buffer, 32767), sender); - break; - } - case VOICE_SIGNAL_DESC: { - voiceService.handleVoiceSignalPacketTypeDesc(ProtocolUtils.readUuid(buffer), ProtocolUtils.readString(buffer, 32767), sender); - break; - } - case VOICE_SIGNAL_DISCONNECT: { - voiceService.handleVoiceSignalPacketTypeDisconnect(buffer.readableBytes() > 0 ? ProtocolUtils.readUuid(buffer) : null, sender); - break; - } - default: { - throw new IOException("Unknown packet type " + packetId); - } - } - if(buffer.readableBytes() > 0) { - throw new IOException("Voice packet is too long!"); - } - }catch(IOException ex) { - throw ex; - }catch(Throwable t) { - throw new IOException("Unhandled exception handling voice packet type " + packetId, t); - } - } - - static byte[] makeVoiceSignalPacketAllowed(boolean allowed, String[] iceServers) { - if (iceServers == null) { - byte[] ret = new byte[2]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED); - wrappedBuffer.writeBoolean(allowed); - return ret; - } - byte[][] iceServersBytes = new byte[iceServers.length][]; - int totalLen = 2 + getVarIntSize(iceServers.length); - for(int i = 0; i < iceServers.length; ++i) { - byte[] b = iceServersBytes[i] = iceServers[i].getBytes(StandardCharsets.UTF_8); - totalLen += getVarIntSize(b.length) + b.length; - } - byte[] ret = new byte[totalLen]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED); - wrappedBuffer.writeBoolean(allowed); - ProtocolUtils.writeVarInt(wrappedBuffer, iceServersBytes.length); - for(int i = 0; i < iceServersBytes.length; ++i) { - byte[] b = iceServersBytes[i]; - ProtocolUtils.writeVarInt(wrappedBuffer, b.length); - wrappedBuffer.writeBytes(b); - } - return ret; - } - - static byte[] makeVoiceSignalPacketGlobal(Collection users) { - int cnt = users.size(); - byte[][] displayNames = new byte[cnt][]; - int i = 0; - for(ConnectedPlayer user : users) { - String name = user.getUsername(); - if(name.length() > 16) name = name.substring(0, 16); - displayNames[i++] = name.getBytes(StandardCharsets.UTF_8); - } - int totalLength = 1 + getVarIntSize(cnt) + (cnt << 4); - for(i = 0; i < cnt; ++i) { - totalLength += getVarIntSize(displayNames[i].length) + displayNames[i].length; - } - byte[] ret = new byte[totalLength]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_GLOBAL); - ProtocolUtils.writeVarInt(wrappedBuffer, cnt); - for(ConnectedPlayer user : users) { - ProtocolUtils.writeUuid(wrappedBuffer, user.getUniqueId()); - } - for(i = 0; i < cnt; ++i) { - ProtocolUtils.writeVarInt(wrappedBuffer, displayNames[i].length); - wrappedBuffer.writeBytes(displayNames[i]); - } - return ret; - } - - static byte[] makeVoiceSignalPacketConnect(UUID player, boolean offer) { - byte[] ret = new byte[18]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT); - ProtocolUtils.writeUuid(wrappedBuffer, player); - wrappedBuffer.writeBoolean(offer); - return ret; - } - - static byte[] makeVoiceSignalPacketConnectAnnounce(UUID player) { - byte[] ret = new byte[17]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT); - ProtocolUtils.writeUuid(wrappedBuffer, player); - return ret; - } - - static byte[] makeVoiceSignalPacketDisconnect(UUID player) { - if(player == null) { - return new byte[] { (byte)VOICE_SIGNAL_DISCONNECT }; - } - byte[] ret = new byte[17]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT); - ProtocolUtils.writeUuid(wrappedBuffer, player); - return ret; - } - - static byte[] makeVoiceSignalPacketICE(UUID player, String str) { - byte[] strBytes = str.getBytes(StandardCharsets.UTF_8); - byte[] ret = new byte[17 + getVarIntSize(strBytes.length) + strBytes.length]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_ICE); - ProtocolUtils.writeUuid(wrappedBuffer, player); - ProtocolUtils.writeVarInt(wrappedBuffer, strBytes.length); - wrappedBuffer.writeBytes(strBytes); - return ret; - } - - static byte[] makeVoiceSignalPacketDesc(UUID player, String str) { - byte[] strBytes = str.getBytes(StandardCharsets.UTF_8); - byte[] ret = new byte[17 + getVarIntSize(strBytes.length) + strBytes.length]; - ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(ret).writerIndex(0); - wrappedBuffer.writeByte(VOICE_SIGNAL_DESC); - ProtocolUtils.writeUuid(wrappedBuffer, player); - ProtocolUtils.writeVarInt(wrappedBuffer, strBytes.length); - wrappedBuffer.writeBytes(strBytes); - return ret; - } - - public static int getVarIntSize(int input) { - for (int i = 1; i < 5; ++i) { - if ((input & -1 << i * 7) == 0) { - return i; - } - } - - return 5; - } -} 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 index 5e95a739..c771aa10 100644 --- 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 @@ -1,11 +1,11 @@ -voice_stun_servers: +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_turn_servers: +voice_servers_passwd: openrelay1: url: 'turn:openrelay.metered.ca:80' username: 'openrelayproject' 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 index d76580b8..e8e43d66 100644 --- 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 @@ -10,6 +10,10 @@ listener_01: - '&6An EaglercraftX server' allow_motd: true allow_query: true + allow_protocol_v3: true + allow_protocol_v4: true + protocol_v4_defrag_send_delay: 10 + allow_cookie_revoke_query: true request_motd_cache: cache_ttl: 7200 online_server_list_animation: false 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 new file mode 100644 index 00000000..ce854a05 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_example.html @@ -0,0 +1,68 @@ + + + + + +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 new file mode 100644 index 00000000..95e20d72 --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_message_api_v1.js @@ -0,0 +1,63 @@ +"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 new file mode 100644 index 00000000..9042249d --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu.yml @@ -0,0 +1,43 @@ +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 new file mode 100644 index 00000000..ee7077aa --- /dev/null +++ b/gateway/EaglercraftXVelocity/src/main/resources/net/lax1dude/eaglercraft/v1_8/plugin/gateway_velocity/config/default_pause_menu_server_info.html @@ -0,0 +1,30 @@ + + + + + +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 new file mode 100644 index 0000000000000000000000000000000000000000..9c9fc8980fc3d08e489084122e80d35a80fd2705 GIT binary patch literal 1258 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�Nota9PPSo?xHCFu!?X&4w2oR@7RNxMRM5 zMmIU*POn~zM`$_|JmWc_xJjV36ubkJ)BtL(E*;~Hk#0fPfYvSOR^z9-k$QSG@6JCL zhsOF}69Y;f@nb0~I7@~EE8(U$967L=w>&eB8|wA^U1Epa98i3J`y8Oc{u<)Kh~KI^ zz)hP&b3_;KN~DGqYJljCtnG?crRyZ-crf7vrq%6oWavg4uV8j%#SA!JVBk(;?4{U1 z%NacHs@ibsO|tEXJfX=MaXT=thb%XmJHT)UD6bMZeQ<95MZFQriD19g`C!<>D7{D8 zn&{kxIJf^7%=Bu)Igi2YG$;yld1GIHu}>s2?T$ z!c}!3zo+ztqT3ri{vy~FN6`2F>aK!6aQH#W_g8*DNDY_Iq