Compare commits

...

190 Commits

Author SHA1 Message Date
ME1312 d1cb53e0f5
Reoptimize the recycle cleaners 2023-12-24 19:07:54 -05:00
ME1312 903b8a98d3
Optimize the recycle cleaners #87 2023-12-24 18:46:25 -05:00
ME1312 f7f42c8ba9
VanillaCord 2.0 2023-12-22 19:23:48 -05:00
ME1312 ad24b0deb3
Trigger reconnect sequence for linking errors, too 2023-08-12 00:07:05 -04:00
ME1312 78f50e77b2
#83 Fixes some template inheritance issues 2023-05-25 22:22:09 -04:00
ME1312 c511ded3d4
Remove duplicate plugins folder
If you have encountered this issue, know that the correct plugins folder is named `Plugins`.
2023-05-21 22:43:43 -04:00
ME1312 b5cddeb892
Fixes deserialization of UUIDs 2023-05-06 06:00:30 -04:00
ME1312 7d9fabd2b9
Fixes your assembly xml 2023-04-09 09:01:06 -04:00
ME1312 b23aa18661
Ensure folia is not required to compile against us 2023-04-09 05:29:41 -04:00
ME1312 ba80e0a16a
Folia scheduling support
Plugins that depend on SubServers.Client can make use of our platform-`AgnosticScheduler` to achieve the same results
2023-04-09 04:25:30 -04:00
ME1312 ecf76a97de
Reduced and updated dependancies
Also includes potential fixes for external host state desyncing
2023-04-07 22:47:16 -04:00
ME1312 01456fd964
Updated SubData 2023-02-22 17:50:02 -05:00
ME1312 c90dbc8e3f
Updated GalaxiEngine 2023-02-22 17:28:52 -05:00
ME1312 e02093ab2f
Updated dependancies 2023-02-22 16:36:40 -05:00
ME1312 8a5a0cdc4b
Fixes to ping adjustment for global player count 2023-01-10 00:57:31 -05:00
ME1312 cf07e86a09
Mirror the listeners field 2022-12-18 14:30:32 -05:00
ME1312 d8463e25c5
Fix the state of CTRL+C shutdowns 2022-11-12 22:40:43 -05:00
ME1312 cb6d30c882
Fix javadoc linking 2022-10-26 15:12:22 -04:00
ME1312 c5377f7f13
Make the status button clickable 2022-10-26 15:02:06 -04:00
ME1312 36f2821524
#80 Bring creation event handling up to spec 2022-08-17 13:18:44 -04:00
ME1312 41dd2d69d0
Add `subservers:input` for 1.19+
This is a simple plugin message channel that simulates chat spoofing.
2022-06-15 11:54:36 -04:00
ME1312 307ac43df0
Fix PacketExControlPlayer 2022-05-28 05:59:33 -04:00
ME1312 1521acfc51
Fix brief shutdown hang in SubServers.Client 2022-04-12 07:59:33 -04:00
ME1312 ce262c62f0
Fix potential NPE 2022-04-09 21:03:29 -04:00
ME1312 e4300e76e2
Make our bukkit events async
Also, #76 store signs in instance
2022-04-05 19:26:50 -04:00
ME1312 7d9de9bf6e
I'm done now i swear 2022-03-19 14:48:16 -04:00
ME1312 249b0a4fab
Yet more minor tweaks to signs 2022-03-19 13:14:22 -04:00
ME1312 6fc8732003
Revert to instance checking for signs 2022-03-19 12:25:19 -04:00
ME1312 b7c89d26d5
Minor sign efficiency upgrades 2022-03-18 17:16:29 -04:00
ME1312 a4d9f46084
Fix possible NPE 2022-03-18 12:30:54 -04:00
ME1312 58ae08db1e
Improved efficiency when accessing maps
Also, #75 Support for hosts, groups, and external servers on signs
2022-03-18 11:57:38 -04:00
ME1312 f6ce5c92fb
Update lang.yml 2022-03-17 01:42:17 -04:00
ME1312 7433fc04a8
#75 Added Server Signs 2022-03-17 00:18:34 -04:00
ME1312 5454590874
Minor sequence correction 2022-02-15 11:43:25 -05:00
ME1312 3e78536d08
Fix rogue detection for remote subservers 2022-02-15 11:36:07 -05:00
ME1312 8a18b6f5d1
Some minor fixes 2022-02-14 12:53:55 -05:00
ME1312 c5573801c4
Minor reference changes 2021-12-31 17:55:56 -05:00
ME1312 80d2557631
Update dependencies 2021-12-18 13:59:56 -05:00
ME1312 9999cbe39e
Update purpur build location 2021-12-06 03:41:26 -05:00
ME1312 6d457200fe
Remove individual packet versioning 2021-12-01 22:25:54 -05:00
ME1312 0c5a89608b
Update SubData 2021-12-01 22:20:42 -05:00
ME1312 7d9f4f86d3
Fix potential nullpo 2021-12-01 06:00:41 -05:00
ME1312 508c2f7627
Use the previous log level for ambiguous lines 2021-12-01 05:42:55 -05:00
ME1312 7179911d4c
Allow commands to be sent to external servers 2021-12-01 04:50:25 -05:00
ME1312 aef7a164e6
Update default templates 2021-11-30 23:55:50 -05:00
ME1312 a0b8df47ac
Update PacketExSyncPlayer 2021-11-24 04:52:39 -05:00
ME1312 c137906fcd
Update SubData 2021-10-25 01:12:06 -04:00
ME1312 92151d75d0
Update GalaxiEngine (again)
This update removes string unescaping from ObjectMap.

This will surely fix a ton of yet unfound bugs that exist from us simply picking the wrong method.
2021-10-24 14:53:15 -04:00
ME1312 86471491bd
Update GalaxiEngine
Only slight changes this time :)
2021-10-24 03:40:47 -04:00
ME1312 3e074e365d
Update GalaxiEngine
The changes this time are to some of GalaxiEngine's core utilities... which means it took a lot of work this time.
2021-10-24 00:14:07 -04:00
ME1312 16c373b336
Assign a short-hand for getting player data
/sub info u ME1312
2021-10-21 21:31:59 -04:00
ME1312 5d3664cbc7
Rebuild local RemotePlayer cache before reconnecting 2021-10-06 14:11:26 -04:00
ME1312 a3896eccd4
Update purpur download location 2021-09-28 02:40:19 -04:00
ME1312 594ba30c64
Update app launchers 2021-09-14 22:05:56 -04:00
ME1312 9bf1bb0710
Wait for response before marking a server as `registered` 2021-08-02 18:33:10 -04:00
ME1312 6890b94b16
Implement Java 9 process termination
Decided to finally use this now that people are updating their JDK versions.

We can never have too many ways to track down and terminate processes around here, can we?
2021-08-01 01:20:12 -04:00
ME1312 52fd155b5f
Efficient stats for nerds 2021-07-30 21:42:05 -04:00
ME1312 16b170df1e
Updated stats for nerds
Our bstats pages have been reorganised so you can have an easier time finding what you're looking for.

There's also a new versioning stat available for proxies. That'll be neat once we get some data.
2021-07-28 02:28:16 -04:00
ME1312 5263f9d018
Prevent `Directory` from being inherited 2021-07-26 16:50:03 -04:00
ME1312 ef1c593607
SubServers.Sync.Velocity #64 (Preview)
And automatic external server definitions
2021-07-09 01:46:10 -04:00
ME1312 394c4b238b
Add the delete command to SubServers.Client 2021-06-28 23:45:49 -04:00
ME1312 ee82ec32a3
Revert to `.zip` 2021-06-28 21:59:27 -04:00
ME1312 1427ff04e1
Use `tar.xz` for downloading templates 2021-06-28 16:34:49 -04:00
ME1312 d3f3f194d0
Update SubData 2021-06-26 17:24:30 -04:00
ME1312 668fccccfe
Update Dependencies 2021-06-26 16:54:04 -04:00
ME1312 a86571a136
Update README.md 2021-06-26 15:49:43 -04:00
ME1312 9c54dfd2b4
Yet another Forge template update 2021-06-26 03:29:23 -04:00
ME1312 81d2d8b14e
Better log handling & Forge-related fixes 2021-06-25 18:26:49 -04:00
ME1312 1533987bf5
Feature creep commit
This commit has 3 new features in it:
-> Internal Templates
-> The new Purpur Template
-> Changes to External Logging
2021-06-24 23:06:53 -04:00
ME1312 ff709ba314
Allow build scripts to reference a template's source files 2021-06-16 00:38:00 -04:00
ME1312 dfabbcf4ad
Add missing static methods to platform-specific api 2021-06-15 05:15:18 -04:00
ME1312 0a6fdb337f
Fix constructor overrides 2021-06-15 04:23:26 -04:00
ME1312 1fff679005
Fix multi-line JSON message parsing 2021-06-15 01:47:06 -04:00
ME1312 7d6396ec1c
Allow targeting multiple RemotePlayers 2021-06-15 00:09:51 -04:00
ME1312 517074f2b3
Remove some unnecessary conversions 2021-06-14 00:42:06 -04:00
ME1312 2c7175e558
Fix one of the new packets 2021-06-13 22:43:05 -04:00
ME1312 f5a3575e54
Remove duplicate maven plugin 2021-06-13 22:29:28 -04:00
ME1312 89f2d646a5
Update build workflow 2021-06-13 22:22:23 -04:00
ME1312 2a9c74f601
Add action methods to RemotePlayer 2021-06-13 21:31:59 -04:00
ME1312 910b504af8
Update SubServers.Console 2021-06-12 23:20:41 -04:00
ME1312 de0e9a676d
Remove some unused internal classes 2021-06-12 17:14:31 -04:00
ME1312 b6a66cfb3b
Shorten client's data folder name 2021-06-12 15:27:51 -04:00
ME1312 51e83f4fb0
Allow ungrouped servers to be listed 2021-06-11 18:16:05 -04:00
ME1312 34c9effa6f
The release version commit (maybe?) 2021-06-11 16:32:14 -04:00
ME1312 bb592da15b
Pre-render the animations 2021-06-07 14:53:21 -04:00
ME1312 f5c8ade961
Optimizations for Client UI 2021-06-07 03:22:57 -04:00
ME1312 b707f2cc0c
Fixes for Client UI 2021-06-06 17:01:28 -04:00
ME1312 ba6af4d66d
Reset servers to unregistered after removal 2021-06-06 02:59:50 -04:00
ME1312 ee59429e1d
Disallow starting unregistered servers 2021-06-06 02:02:27 -04:00
ME1312 b2b80036d7
Update GalaxiEngine 2021-06-06 01:33:24 -04:00
ME1312 4d081f6e4f
Don't fire edit events for temporary modifications 2021-06-06 01:28:22 -04:00
ME1312 e1de6636f0
Optimizations for developers 2021-06-05 22:44:33 -04:00
ME1312 42a73c8372
Update GalaxiEngine 2021-06-05 14:16:24 -04:00
ME1312 c6a354fe84
Fix shutdown detection 2021-04-23 00:36:54 -04:00
ME1312 6258256081
Minor API corrections to template swapping 2021-04-15 00:45:04 -04:00
ME1312 ce38355c91
Less debugging. 2021-04-14 13:42:51 -04:00
ME1312 d0177ce055
More debugging! 2021-04-13 17:35:06 -04:00
ME1312 5898371780
Add some debug messages 2021-04-13 17:32:41 -04:00
ME1312 0ac4238dc8
Remove unnecessary launch flags
This allows users on non-linux but unix-based systems to install ports of the `setsid` command that might not be feature complete.
2021-04-09 17:12:36 -04:00
ME1312 18953046b8
Shorten the Linux terminator
No need to overcomplicate things. Also, no risk of killing the entire program with this.
2021-04-08 10:44:41 -04:00
ME1312 ff82fd5151
Minor API efficiency improvements 2021-04-08 09:15:35 -04:00
ME1312 eba5e6a7d1
A better terminator for Linux
SubServers' child processes now get their very own Session ID in Linux.
2021-04-07 22:06:13 -04:00
ME1312 746c51e8fa
Update lang.yml 2021-04-03 23:59:51 -04:00
ME1312 23a434054f
Simplify teleportation permissions 2021-03-14 14:03:48 -04:00
ME1312 b188f0d4af
Add `subservers.request` 2021-03-14 09:20:24 -04:00
ME1312 a9b0afb40a
Let plebs use `/sub teleport`
There's still explicit permissions for this command, but granting `subservers.command` is no longer necessary.
2021-03-13 12:09:54 -05:00
ME1312 a992ec7c52
Better legacy API emulation 2021-03-13 11:51:32 -05:00
ME1312 620db38e9b
Corrections to legacy formatting 2021-03-08 12:02:28 -05:00
ME1312 1c010ea9b2
Change placeholder format
This is to make it compatible with PAPI bracket format.
2021-03-08 06:08:54 -05:00
ME1312 98e487b44e
Add placeholders for groups 2021-03-08 04:47:49 -05:00
ME1312 15a4f109a4
Clean up Executable class 2021-02-24 20:07:20 -05:00
ME1312 2beec3ae7a
Put lock in a more strategic location 2021-02-24 17:13:26 -05:00
ME1312 f90a54e636
Set running to TRUE while running start event 2021-02-24 17:09:25 -05:00
ME1312 59d3404abf
Update GalaxiEngine 2021-02-21 04:40:43 -05:00
ME1312 91fe4e74ed
Update GalaxiEngine 2021-02-18 03:31:20 -05:00
ME1312 811d65b68a
Secure the compatibility plugin
This commit moves the loadable section of the compatibility plugin to an anonymous class to prevent misuse of that section of code.
2021-02-15 00:28:06 -05:00
ME1312 5732237477
Update GalaxiEngine 2021-02-13 13:43:09 -05:00
ME1312 d244e6a5b7
Update GalaxiEngine 2021-02-13 02:29:36 -05:00
ME1312 2cb783326a
Update GalaxiEngine 2021-02-13 00:04:20 -05:00
ME1312 76e11f0a0d
Keep the console reader alive during shutdown 2021-02-07 03:09:39 -05:00
ME1312 4e66461848
Move autorun queue to a more appropriate location
This restores plugins' ability to listen for server start events
2021-02-07 01:19:55 -05:00
ME1312 3dea3b67d0
Rework SubServers.Bungee's app lifecycle
SubServers.Bungee now puts code in 2 new places to better load/unload it's data.

When supported, this should give it better compatabilty with ordanary plugins. Also, it no longer has to 'shutdown' to handle /greload. Isn't that neat?
2021-02-06 23:53:03 -05:00
ME1312 25fff82af6
Update SubData 2021-01-30 01:53:30 -05:00
ME1312 e090815b37
Revert something
This change I made a few commits ago is now unnecessary given the previous commit.
2021-01-29 19:23:58 -05:00
ME1312 b0340b498e
SubData API updates & usage optimizations 2021-01-29 19:06:23 -05:00
ME1312 6d32f1b6a0
Update SubData
Can you believe it?
2021-01-29 17:57:47 -05:00
ME1312 bfff48a9ec
Update SubData 2021-01-28 05:16:14 -05:00
ME1312 4debf94fd6
Update SubData 2021-01-28 01:36:08 -05:00
ME1312 2c29182ca5
Update GalaxiEngine 2021-01-22 23:56:43 -05:00
ME1312 9af8dd02ce
Update SubData 2021-01-21 14:28:23 -05:00
ME1312 ea9eec9aa8
Don't store temporary servers in servers.yml 2021-01-16 18:10:51 -05:00
ME1312 08b56fc823
Don't rewrite files with no placeholders 2020-12-20 22:30:33 -05:00
ME1312 fe4f19e713
Rewrite SmartFallback's Fallback process 2020-12-04 23:30:36 -05:00
ME1312 c261be2215
Don't remote reload SubData
It doesn't make any sense to be doing this...
2020-11-27 22:00:54 -05:00
ME1312 2841bdf061
Update SubData 2020-11-23 00:52:36 -05:00
ME1312 bcd7f4f3c3
Update SubData 2020-11-23 00:25:00 -05:00
ME1312 80da5f7b27
Fix host.getRemotePlayers() 2020-11-20 12:14:43 -05:00
ME1312 4ea69298a3
Optimize imports 2020-11-16 15:34:59 -05:00
ME1312 4cfe1b4285
Standardize RemotePlayer
This is the RemotePlayer API, not the GlobalPlayer API.
2020-11-14 13:12:08 -05:00
ME1312 20ab75530a
Update pom.xml 2020-11-14 02:15:41 -05:00
ME1312 8d21771857
Update GalaxiEngine 2020-11-14 02:07:25 -05:00
ME1312 c0197759f4
ClientCommon API 2020-11-14 00:29:29 -05:00
ME1312 34b406e3ae
BungeeCommon API 2020-11-13 22:41:56 -05:00
ME1312 96a3cf797e
Update SubData 2020-11-11 16:07:22 -05:00
ME1312 c62363bdef
Make the compatibility plugin loadable
Some BungeeCord API calls require an actual plugin object. This is a problem.

Fortunately, the 2020 builds of BungeeCord provide a protected constructor that is actually usable by SubServers, so we implemented it.
2020-11-11 02:35:02 -05:00
ME1312 489b25f48d
Update SubData 2020-11-07 11:35:25 -05:00
ME1312 0136419960
Override fallback servers when using `Reconnect` 2020-08-29 06:57:38 -04:00
ME1312 29dbd107c0
More debug options 2020-08-24 12:11:16 -04:00
ME1312 fa82e0ab96
More debug messages 2020-08-24 12:04:21 -04:00
ME1312 d3e6d3e579
Fix some issues with restore points in SubCreator 2020-08-22 22:11:05 -04:00
ME1312 6e60138a79
Add an error checking thread for player sync 2020-08-22 20:01:58 -04:00
ME1312 e9c0075144
Misc fixes regarding the last few commits 2020-08-21 18:33:09 -04:00
ME1312 fa77eeeab0
Allow a subserver's template to be changed 2020-08-19 21:15:55 -04:00
ME1312 443e3c2d44
Favor new connections over the old ones
This is a change to the rules that govern what happens when the same UUID connects to the same network more than once. It is now more BungeeCord like in nature.
2020-08-19 15:24:05 -04:00
ME1312 d43aae8486
Allow command overrides to be disabled seperately
This also leaves room for disabling overrides in other features in the future.
2020-08-18 20:03:59 -04:00
ME1312 b68fa0fec1
Remove some implementation redundancies 2020-08-16 14:30:36 -04:00
ME1312 26490dc140
Use single-threaded I/O for StopAction 2020-08-13 18:26:22 -04:00
ME1312 b18f047d53
Disallow the same UUID to make multiple connections to a multi-proxy network 2020-08-12 20:18:55 -04:00
ME1312 83041a1f3f
Allow SubProtocol to be extended 2020-08-11 20:28:34 -04:00
ME1312 efc12e0649
Fix possible player data desyncs 2020-07-25 05:43:42 -04:00
ME1312 891913dbe3
Ditch RedisBungee. Long live the RemotePlayer API
RedisBungee has been abandoned by it's developers. So we're abanding it too.

SubServers.Sync will now finally pick up the slack and sync basic player information between proxies over their SubData connection.
2020-07-25 01:20:59 -04:00
ME1312 f2f196dc79
Update GalaxiEngine 2020-07-24 14:25:40 -04:00
ME1312 fcc87117dd
Allow arguments & responses to call other methods/placeholders 2020-07-15 21:08:47 -04:00
ME1312 2975ab05f4
Update GalaxiEngine 2020-07-06 17:19:02 -04:00
ME1312 0d052e0774
Make `color` the default behavior for placeholders 2020-07-05 03:33:58 -04:00
ME1312 dacb3aa541
Allow custom responses for some placeholders 2020-07-05 02:13:58 -04:00
ME1312 5ad6b49de7
Update a server's placeholders upon a state change 2020-07-05 00:11:51 -04:00
ME1312 69fad5221c
Allow selecting the master proxy in placeholders 2020-07-04 23:31:58 -04:00
ME1312 1564eaaaf9
Add PAPI placeholders with SubServers.Client 2020-07-04 22:39:59 -04:00
ME1312 db8aff55f6
Allow plugins to modify the result of ping_passthrough 2020-07-03 20:23:27 -04:00
ME1312 ec2d75d0f6
Modify pings for DNS-Forward servers 2020-07-03 19:05:02 -04:00
ME1312 d76d0347e5
Add more features to Smart Fallback 2020-07-03 17:14:59 -04:00
ME1312 928c40addc
Use proper grammar for single items
Not possible for SubServers.Client since it uses global lang, but the mistake was less egregious in that case anyway.
2020-06-26 02:52:34 -04:00
ME1312 312d010585
Some more compatibility changes 2020-06-25 19:47:30 -04:00
ME1312 d8ea0cee66
Rework the SmartFallback API
There were a couple things in Smart Fallback that seemed short-sighted when it came to use by external plugins. Now you can:
-> Make decisions using player data (when available)
-> Assign partial points to a confidence score
2020-06-21 17:42:10 -04:00
ME1312 89856a19b8
Don't update templates that are lacking a `Version` property 2020-06-20 23:46:16 -04:00
ME1312 0812ff3ade
Properly set a default value for the `Replacements` option 2020-06-20 03:45:45 -04:00
ME1312 0e8bae4187
Re-Add local templates to SubServers.Host
Local templates are now stored in `/Templates`

Template cache files are still stored in `/Cache/Templates`

Remote templates are now stored in `/Cache/Remote/Templates`
2020-06-19 21:00:50 -04:00
ME1312 3fc249cf07
Add RegEx to File Selection 2020-06-13 23:23:06 -04:00
ME1312 9d01f46c16
SubCreator File Replacements
SubCreator has several new build options for updating and making replacements in files
2020-06-13 17:53:18 -04:00
ME1312 bb0dd55c95
#50 #46 Selecting Multiple Servers
This commit includes the following major changes and additions:
-> New Command & Permission Formatting
-> RemotePlayer API
-> SubData with Blocks
2020-06-12 01:45:49 -04:00
ME1312 caf8ee793d
Update GalaxiEngine 2020-02-17 19:07:26 -05:00
ME1312 65a5b7d0c9
Send actual data packet on ExCreator reload 2020-02-16 22:25:15 -05:00
ME1312 d2c7512257
Update ExternalSubServer.java 2020-02-16 20:43:52 -05:00
ME1312 4ba0489d9d
Bypass new Oracle argument restrictions 2020-02-16 15:01:17 -05:00
ME1312 bb975413a5
Update SubData 2020-02-12 11:10:22 -05:00
ME1312 207393cfec
Don't get confused by Manifest line splitting 2020-01-25 16:06:05 -05:00
ME1312 11f92f2559
Correct getServerInfo() on Waterfall 2020-01-25 13:30:16 -05:00
ME1312 7a4d28b113
Update BungeeCord
The official BungeeCord fork hit us with a surprise incompatibility recently. Yikes.
2020-01-18 00:13:10 -05:00
ME1312 d39d875e2b
Correct default lang.yml formatting 2019-12-18 21:52:15 -05:00
500 changed files with 30203 additions and 26102 deletions

63
.gitattributes vendored
View File

@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

View File

@ -11,7 +11,7 @@ Paste in the version information from the SubServers app in question here. To ge
Here you can write about what happened that shouldn't have. If you have any errors in your console related to what happened, you should also paste those here.
### How It Happened
Tell us step-by-step how to recreate the problem. This step is vital for us to determine whether or not the problem happens to everyone else too.
Tell us step-by-step how to recreate the problem. This step is vital for us to determine whether the problem happens to everyone else too.
### Additional Information
Here you can provide any extra details you may think useful for solving the problem.

62
.gitignore vendored
View File

@ -1,49 +1,17 @@
# SubServers 2 Ignored Files
*.iml
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.userprefs
## Directory-based project format:
.idea/
## File-based project format:
*.ipr
*.iws
# IntelliJ
# Hide System and IDE Generated Files
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
# Hide Unfinished Project Files
/SubServers.Client/Windows/
/Artifacts/SubServers.Web.jar
/SubServers.Velocity/
/SubServers.Web/
# Hide Others
/Artifacts/-Maven/
/Artifacts/-History/
/Artifacts/-Icon/
/Artifacts/-Lite/
/Artifacts/*.jar
/Javadoc/
/SubServers.Test/
/build.ant
/build.log
.idea/
*.iml
.DS_STORE
# Hide Unfinished Projects
/SubServers.Test/
# Hide Compiled Artifacts
/Artifacts/*
/BungeeCord/
/Javadoc/
# Show Interpreted Artifacts
!/Artifacts/Download/
!/Artifacts/SubServers.Patcher.sh

View File

@ -52,7 +52,7 @@ if [ $__RETURN -eq 0 ]
rm -Rf LICENSE
fi
if [ -f "META-INF/MANIFEST.MF" ]; then
cat META-INF/MANIFEST.MF | sed -e "/^\s*$/d" -e "/^Main-Class:.*$/d" -e "/^Implementation-Title:.*$/d" -e "/^Specification-Title:.*$/d" -e "/^Build-Jdk:.*$/d" -e "/^Created-By:.*$/d" -e "/^Built-By:.*$/d" > ../MANIFEST.MF
cat META-INF/MANIFEST.MF | sed 's/\r$//' | sed ':a;N;$!ba;s/\n //g' | sed -e "/^\s*$/d" -e "/^Main-Class:.*$/d" -e "/^Implementation-Title:.*$/d" -e "/^Specification-Title:.*$/d" -e "/^Build-Jdk:.*$/d" -e "/^Created-By:.*$/d" -e "/^Built-By:.*$/d" > ../MANIFEST.MF
else
printf "Manifest-Version: 1.0\n" > ../MANIFEST.MF
fi
@ -67,8 +67,8 @@ if [ $__RETURN -eq 0 ]
then
echo ">> Writing Changes..."
if [ -f "META-INF/MANIFEST.MF" ]
then
cat META-INF/MANIFEST.MF | sed -e "/^\s*$/d" -e "/^Manifest-Version:.*$/d" -e "/^Class-Path:.*$/d" -e "/^Build-Jdk:.*$/d" -e "/^Created-By:.*$/d" -e "/^Built-By:.*$/d" >> ../MANIFEST.MF
then # (Read File) (Convert to LF) (Rejoin Split Lines) (Omit Empty, Duplicate, and Unnecessary Properties)
cat META-INF/MANIFEST.MF | sed 's/\r$//' | sed ':a;N;$!ba;s/\n //g' | sed -e "/^\s*$/d" -e "/^Manifest-Version:.*$/d" -e "/^Class-Path:.*$/d" -e "/^Build-Jdk:.*$/d" -e "/^Created-By:.*$/d" -e "/^Built-By:.*$/d" >> ../MANIFEST.MF
else
if [ ! -d "META-INF" ]; then
mkdir META-INF
@ -79,13 +79,13 @@ if [ $__RETURN -eq 0 ]
fi
yes | cp -rf . ../Patched.jar
cd ../
printf "Built-By: SubServers.Bungee.Patcher\n" >> MANIFEST.MF
printf "Built-By: SubServers.Patcher\n" >> MANIFEST.MF
cp -f MANIFEST.MF Patched.jar/META-INF
if [ -f "Patched.jar/bungee.yml" ]; then
rm -Rf Patched.jar/bungee.yml
fi
if [ ! -f "MODIFICATIONS" ]; then
printf "# SubServers.Bungee.Patcher generated difference list (may be empty if git is not installed)\n#\n" > MODIFICATIONS
printf "# SubServers.Patcher generated difference list (may be empty if git is not installed)\n#\n" > MODIFICATIONS
fi
printf "@ `date`\n> git --no-pager diff --no-index --name-status SubServers.Patcher/Original.jar SubServers.Patcher/Patched.jar\n" >> MODIFICATIONS
git --no-pager diff --no-index --name-status Original.jar Patched.jar | sed -e "s/\tOriginal.jar\//\t\//" -e "s/\tPatched.jar\//\t\//" >> MODIFICATIONS

View File

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2015-2019 ME1312
Copyright (C) 2015-2023 ME1312
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
# ![https://s3.postimg.cc/dikyxlz5v/Sub_Banner.png](https://s3.postimg.cc/dikyxlz5v/Sub_Banner.png)
[![Build Status](https://dev.me1312.net/jenkins/job/SubServers%20Platform/badge/icon)](https://dev.me1312.net/jenkins/job/SubServers%20Platform/)
[![Release Verison](https://img.shields.io/github/release/ME1312/SubServers-2/all.svg)](https://github.com/ME1312/SubServers-2/releases) [![Snapshot Verison](https://img.shields.io/badge/dynamic/xml.svg?label=snapshot&url=https%3A%2F%2Fdev.me1312.net%2Fmaven%2Fnet%2FME1312%2FSubServers%2FSubServers.Bungee%2Fmaven-metadata.xml&query=%2F%2Fversioning%2Frelease&colorB=blue)](https://dev.me1312.net/jenkins/job/SubServers%20Platform/) [![Discord](https://img.shields.io/discord/526520424880930867.svg)](https://discord.gg/VZ8YJqz)<br><br>
[![Release Verison](https://img.shields.io/github/release/ME1312/SubServers-2/all.svg)](https://github.com/ME1312/SubServers-2/releases) [![Snapshot Verison](https://img.shields.io/badge/dynamic/xml.svg?label=snapshot&url=https%3A%2F%2Fdev.me1312.net%2Fmaven%2Fnet%2FME1312%2FSubServers%2FSubServers.Bungee%2Fmaven-metadata.xml&query=%2F%2Fversioning%2Frelease&colorB=blue)](https://dev.me1312.net/jenkins/job/SubServers%20Platform/) [![Discord](https://img.shields.io/discord/526520424880930867.svg)](https://discord.gg/zWupnVn)<br><br>
SubServers 2 is a rewrite of SubServers, the Server Management Platform.<br>
> [https://www.spigotmc.org/resources/subservers-bungee.11264/](https://www.spigotmc.org/resources/subservers-bungee.11264/)<br>
> [https://www.spigotmc.org/resources/subservers-host.38833/](https://www.spigotmc.org/resources/subservers-host.38833/)<br>
@ -12,22 +12,26 @@ SubServers 2 is a rewrite of SubServers, the Server Management Platform.<br>
These are some quick links for common resources of SubServers 2.
### How to Install
> [https://github.com/ME1312/SubServers-2/wiki/Install](https://github.com/ME1312/SubServers-2/wiki/Install)
> [https://github.com/ME1312/SubServers-2/wiki/Install](https://github.com/ME1312/SubServers-2/wiki/Installation)
### Snapshot Downloads
> [https://dev.me1312.net/jenkins/job/SubServers Platform](https://dev.me1312.net/jenkins/job/SubServers%20Platform)
### Javadocs for Developers
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Bungee/](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Bungee/)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Host/](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Host/)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Sync/](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Sync/)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Client.Bukkit/](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Client.Bukkit/)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Client.Sponge/](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Client.Sponge/)
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Bungee](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Bungee)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Bungee.Common](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Bungee.Common)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Host](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Host)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Sync](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Sync)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Sync.Velocity](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Sync.Velocity)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Client.Bukkit](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Client.Bukkit)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Client.Common](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Client.Common)<br>
> [https://dev.me1312.net/jenkins/job/SubServers Platform/javadoc/SubServers.Client.Sponge](https://dev.me1312.net/jenkins/job/SubServers%20Platform/javadoc/SubServers.Client.Sponge)
### Stats for nerds
> [https://bstats.org/plugin/bungeecord/SubServers_Bungee](https://bstats.org/plugin/bungeecord/SubServers%202)<br>
> [https://bstats.org/plugin/other/SubServers_Host](https://bstats.org/plugin/other/SubServers%20Host)<br>
> [https://bstats.org/plugin/bungeecord/SubServers_Sync](https://bstats.org/plugin/bungeecord/SubServers%20Sync)<br>
> [https://bstats.org/plugin/velocity/SubServers_Sync](https://bstats.org/plugin/velocity/SubServers%20Sync)<br>
> [https://bstats.org/plugin/bungeecord/SubServers_Console](https://bstats.org/plugin/bungeecord/SubServers%20Console)<br>
> [https://bstats.org/plugin/bukkit/SubServers_Client](https://bstats.org/plugin/bukkit/SubServers%20Client)<br>
> [https://bstats.org/plugin/sponge/SubServers_Client](https://bstats.org/plugin/sponge/SubServers%20Client)

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.ME1312.SubServers</groupId>
<artifactId>SubServers.Bungee.Common</artifactId>
<version>-PLACEHOLDER</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>md_5-repo</id>
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
</repository>
<repository>
<id>me1312-repo</id>
<url>https://dev.me1312.net/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.md_5</groupId>
<artifactId>bungeecord-internal</artifactId>
<version>1.15-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiBase</artifactId>
<version>23w51a</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<directory>../../out/compile/target/SubServers.Bungee.Common</directory>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<mkdir dir="${project.build.directory}" />
<copy file="${basedir}/../../LICENSE" todir="${project.build.directory}/classes" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>SubServers.Bungee.Common</finalName>
<outputDirectory>../../Artifacts/Maven</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>javadoc</goal>
</goals>
<configuration>
<windowtitle>SubServers.Bungee.Common</windowtitle>
<doctitle>SubServers.Bungee.Common ${project.version}</doctitle>
<show>protected</show>
<destDir>./</destDir>
<outputDirectory>${basedir}/../../Javadoc/SubServers.Bungee.Common</outputDirectory>
<reportOutputDirectory>${basedir}/../../Javadoc/SubServers.Bungee.Common</reportOutputDirectory>
<additionalOptions>-Xdoclint:none</additionalOptions>
<links>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiBase/</link>
<link>https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/</link>
</links>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,137 @@
package net.ME1312.SubServers.Bungee;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
/**
* SubAPI BungeeCord Common Class
*/
public interface BungeeAPI {
/**
* Gets the SubAPI BungeeCord Common Methods
*
* @return SubAPI BungeeCord Common
*/
static BungeeAPI getInstance() {
return ((BungeeCommon) ProxyServer.getInstance()).api.get();
}
/**
* Gets the BungeeCommon Internals
*
* @deprecated Use BungeeAPI Methods when available
* @return BungeeCommon Internals
*/
@Deprecated
BungeeCommon getInternals();
/**
* Get the number of players on this network across all known proxies
*
* @return Remote Player Collection
*/
int getRemotePlayerCount();
/**
* Get players on this server across all known proxies
*
* @param server Server to search
* @return Remote Player Map
*/
Map<UUID, ? extends RemotePlayer> getRemotePlayers(ServerInfo server);
/**
* Get players on this network across all known proxies
*
* @return Remote Player Map
*/
Map<UUID, ? extends RemotePlayer> getRemotePlayers();
/**
* Get a player on this network by searching across all known proxies
*
* @param name Player name
* @return Remote Player
*/
RemotePlayer getRemotePlayer(String name);
/**
* Get a player on this network by searching across all known proxies
*
* @param id Player UUID
* @return Remote Player
*/
RemotePlayer getRemotePlayer(UUID id);
/**
* Gets the current SubServers Lang Channels
*
* @return SubServers Lang Channel list
*/
Collection<String> getLangChannels();
/**
* Gets values from the SubServers Lang
*
* @param channel Lang Channel
* @return Lang Value
*/
Map<String, String> getLang(String channel);
/**
* Gets a value from the SubServers Lang
*
* @param channel Lang Channel
* @param key Key
* @return Lang Values
*/
default String getLang(String channel, String key) {
Util.nullpo(channel, key);
return getLang(channel).get(key);
}
/**
* Gets the Runtime Directory
*
* @return Directory
*/
File getRuntimeDirectory();
/**
* Gets the SubServers Version
*
* @return SubServers Version
*/
Version getWrapperVersion();
/**
* Gets the SubServers Build Version
*
* @return SubServers Build Version (or null if unsigned)
*/
Version getWrapperBuild();
/**
* Gets the BungeeCord Version
*
* @return BungeeCord Version
*/
Version getProxyVersion();
/**
* Get an array of compatible Minecraft Versions
*
* @return Minecraft Versions
*/
Version[] getGameVersion();
}

View File

@ -0,0 +1,49 @@
package net.ME1312.SubServers.Bungee;
import net.ME1312.Galaxi.Library.Util;
import io.netty.channel.Channel;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;
/**
* BungeeCord Common Layout Class
*/
public abstract class BungeeCommon extends BungeeCord {
private static BungeeCommon instance;
final Supplier<BungeeAPI> api;
protected final Collection<Channel> listeners;
protected BungeeCommon(Supplier<BungeeAPI> api) throws Exception {
listeners= Util.reflect(BungeeCord.class.getDeclaredField("listeners"), this);
this.api = api;
instance = this;
}
/**
* Get the name from BungeeCord's original signature (for determining which fork is being used)
*
* @return BungeeCord Software Name
*/
public abstract String getBungeeName();
/**
* Waterfall's getServersCopy()
*
* @return Server Map Copy
*/
public abstract Map<String, ServerInfo> getServersCopy();
/**
* Gets the ProxyServer Common Object
*
* @return ProxyServer Common
*/
public static BungeeCommon getInstance() {
return instance;
}
}

View File

@ -0,0 +1,39 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.SubServers.Bungee.BungeeCommon;
import java.util.HashMap;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
/**
* Logger Compatibility Class
*/
public class Logger {
private static final HashMap<String, java.util.logging.Logger> existing = new HashMap<String, java.util.logging.Logger>();
/**
* Get a logger
*
* @param prefix Prefix
* @return Logger
*/
public static java.util.logging.Logger get(String prefix) {
if (!existing.containsKey(prefix)) {
java.util.logging.Logger log = java.util.logging.Logger.getAnonymousLogger();
log.setUseParentHandlers(false);
log.addHandler(new Handler() {
@Override
public void publish(LogRecord record) {
BungeeCommon.getInstance().getLogger().log(record.getLevel(), prefix + " > " + record.getMessage(), record.getParameters());
}
@Override
public void flush() {}
public void close() {}
});
existing.put(prefix, log);
}
return existing.get(prefix);
}
}

View File

@ -0,0 +1,52 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.md_5.bungee.api.chat.BaseComponent;
import java.util.UUID;
import java.util.function.IntConsumer;
/**
* RemotePlayer Static Implementation Layout Class
*/
public abstract class RPSI {
protected static RPSI instance;
protected RPSI() {
if (instance == null) instance = this;
}
/**
* Sends messages to this player
*
* @param players Players to send to
* @param messages Messages to send
* @param response Success Status
*/
protected abstract void sendMessage(UUID[] players, String[] messages, IntConsumer response);
/**
* Sends messages to this player
*
* @param players Players to send to
* @param messages Messages to send
* @param response Success Status
*/
protected abstract void sendMessage(UUID[] players, BaseComponent[][] messages, IntConsumer response);
/**
* Transfers this player to another server
*
* @param players Players to send to
* @param server Target server
* @param response Success Status
*/
protected abstract void transfer(UUID[] players, String server, IntConsumer response);
/**
* Disconnects this player from the network
*
* @param players Players to send to
* @param reason Disconnect Reason
* @param response Success status
*/
protected abstract void disconnect(UUID[] players, String reason, IntConsumer response);
}

View File

@ -0,0 +1,460 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.function.IntConsumer;
import static net.ME1312.SubServers.Bungee.Library.Compatibility.RPSI.instance;
/**
* RemotePlayer Layout Class
*/
public interface RemotePlayer {
/**
* Get Local Player
*
* @return Local Player (or null when not local)
*/
ProxiedPlayer get();
/**
* Get the UUID of this player.
*
* @return the UUID
*/
UUID getUniqueId();
/**
* Get the unique name of this player.
*
* @return the player's username
*/
String getName();
/**
* Gets the remote address of this connection.
*
* @return the remote address
*/
InetSocketAddress getAddress();
/**
* Gets the name of the proxy this player is connected to.
*
* @return the name of the proxy this player is connected to
*/
String getProxyName();
/**
* Gets the name of the server this player is connected to.
*
* @return the name of the server this player is connected to
*/
String getServerName();
/**
* Gets the server this player is connected to.
*
* @return the server this player is connected to
*/
ServerInfo getServer();
/**
* Sends messages to all players
*
* @param messages Messages to send
*/
static void broadcastMessage(String... messages) {
broadcastMessage(messages, i -> {});
}
/**
* Sends a message to all players
*
* @param message Message to send
* @param response Success Status
*/
static void broadcastMessage(String message, IntConsumer response) {
broadcastMessage(new String[]{ message }, response);
}
/**
* Sends messages to all players
*
* @param messages Messages to send
* @param response Success Status
*/
static void broadcastMessage(String[] messages, IntConsumer response) {
sendMessage(null, messages, response);
}
/**
* Sends messages to this player
*
* @param messages Messages to send
*/
default void sendMessage(String... messages) {
sendMessage(messages, i -> {});
}
/**
* Sends a message to this player
*
* @param message Message to send
* @param response Success Status
*/
default void sendMessage(String message, IntConsumer response) {
sendMessage(new String[]{ message }, response);
}
/**
* Sends messages to this player
*
* @param messages Messages to send
* @param response Success Status
*/
default void sendMessage(String[] messages, IntConsumer response) {
sendMessage(new UUID[]{ getUniqueId() }, messages, response);
}
/**
* Sends messages to these players
*
* @param players Players to select
* @param messages Messages to send
*/
static void sendMessage(UUID[] players, String... messages) {
sendMessage(players, messages, i -> {});
}
/**
* Sends a message to these players
*
* @param players Players to select
* @param message Message to send
* @param response Success Status
*/
static void sendMessage(UUID[] players, String message, IntConsumer response) {
sendMessage(players, new String[]{ message }, response);
}
/**
* Sends messages to these players
*
* @param players Players to select
* @param messages Messages to send
* @param response Success Status
*/
static void sendMessage(UUID[] players, String[] messages, IntConsumer response) {
instance.sendMessage(players, messages, response);
}
/**
* Sends a message to all players
*
* @param message Message to send
*/
static void broadcastMessage(BaseComponent... message) {
broadcastMessage(message, i -> {});
}
/**
* Sends a message to all players
*
* @param message Message to send
* @param response Success Status
*/
static void broadcastMessage(BaseComponent message, IntConsumer response) {
broadcastMessage(new BaseComponent[]{ message }, response);
}
/**
* Sends a messages to all players
*
* @param message Message to send
* @param response Success Status
*/
static void broadcastMessage(BaseComponent[] message, IntConsumer response) {
broadcastMessage(new BaseComponent[][]{ message }, response);
}
/**
* Sends messages to all players
*
* @param messages Messages to send
*/
static void broadcastMessage(BaseComponent[]... messages) {
broadcastMessage(messages, i -> {});
}
/**
* Sends messages to all players
*
* @param messages Messages to send
* @param response Success Status
*/
static void broadcastMessage(BaseComponent[][] messages, IntConsumer response) {
sendMessage(null, messages, response);
}
/**
* Sends a message to this player
*
* @param message Message to send
*/
default void sendMessage(BaseComponent... message) {
sendMessage(message, i -> {});
}
/**
* Sends a message to this player
*
* @param message Message to send
* @param response Success Status
*/
default void sendMessage(BaseComponent message, IntConsumer response) {
sendMessage(new BaseComponent[]{ message }, response);
}
/**
* Sends a message to this player
*
* @param message Message to send
* @param response Success Status
*/
default void sendMessage(BaseComponent[] message, IntConsumer response) {
sendMessage(new BaseComponent[][]{ message }, response);
}
/**
* Sends messages to this player
*
* @param messages Messages to send
*/
default void sendMessage(BaseComponent[]... messages) {
sendMessage(messages, i -> {});
}
/**
* Sends messages to this player
*
* @param messages Messages to send
* @param response Success Status
*/
default void sendMessage(BaseComponent[][] messages, IntConsumer response) {
sendMessage(new UUID[]{ getUniqueId() }, messages, response);
}
/**
* Sends a message to these players
*
* @param players Players to select
* @param message Message to send
*/
static void sendMessage(UUID[] players, BaseComponent... message) {
sendMessage(players, message, i -> {});
}
/**
* Sends a message to these players
*
* @param players Players to select
* @param message Message to send
* @param response Success Status
*/
static void sendMessage(UUID[] players, BaseComponent message, IntConsumer response) {
sendMessage(players, new BaseComponent[]{ message }, response);
}
/**
* Sends a message to these players
*
* @param players Players to select
* @param message Message to send
* @param response Success Status
*/
static void sendMessage(UUID[] players, BaseComponent[] message, IntConsumer response) {
sendMessage(players, new BaseComponent[][]{ message }, response);
}
/**
* Sends messages to these players
*
* @param players Players to select
* @param messages Messages to send
*/
static void sendMessage(UUID[] players, BaseComponent[]... messages) {
sendMessage(players, messages, i -> {});
}
/**
* Sends messages to these players
*
* @param players Players to select
* @param messages Message to send
* @param response Success Status
*/
static void sendMessage(UUID[] players, BaseComponent[][] messages, IntConsumer response) {
instance.sendMessage(players, messages, response);
}
/**
* Transfers this player to another server
*
* @param server Target server
*/
default void transfer(String server) {
transfer(server, i -> {});
}
/**
* Transfers this player to another server
*
* @param server Target server
* @param response Success status
*/
default void transfer(String server, IntConsumer response) {
transfer(new UUID[]{ getUniqueId() }, server, response);
}
/**
* Transfers these players to another server
*
* @param players Players to select
* @param server Target server
*/
static void transfer(UUID[] players, String server) {
transfer(players, server, i -> {});
}
/**
* Transfers these players to another server
*
* @param players Players to select
* @param server Target server
* @param response Success status
*/
static void transfer(UUID[] players, String server, IntConsumer response) {
instance.transfer(players, server, response);
}
/**
* Transfers this player to another server
*
* @param server Target server
*/
default void transfer(ServerInfo server) {
transfer(server, i -> {});
}
/**
* Transfers this player to another server
*
* @param server Target server
* @param response Success status
*/
default void transfer(ServerInfo server, IntConsumer response) {
transfer(new UUID[]{ getUniqueId() }, server, response);
}
/**
* Transfers these players to another server
*
* @param players Players to select
* @param server Target server
*/
static void transfer(UUID[] players, ServerInfo server) {
transfer(players, server, i -> {});
}
/**
* Transfers these players to another server
*
* @param players Players to select
* @param server Target server
* @param response Success status
*/
static void transfer(UUID[] players, ServerInfo server, IntConsumer response) {
instance.transfer(players, server.getName(), response);
}
/**
* Disconnects this player from the network
*/
default void disconnect() {
disconnect((String) null);
}
/**
* Disconnects this player from the network
*
* @param response Success status
*/
default void disconnect(IntConsumer response) {
disconnect((String) null, response);
}
/**
* Disconnects this player from the network
*
* @param reason Disconnect Reason
*/
default void disconnect(String reason) {
disconnect(reason, i -> {});
}
/**
* Disconnects this player from the network
*
* @param reason Disconnect Reason
* @param response Success status
*/
default void disconnect(String reason, IntConsumer response) {
disconnect(new UUID[]{ getUniqueId() }, reason, response);
}
/**
* Disconnects these players from the network
*
* @param players Players to select
*/
static void disconnect(UUID... players) {
disconnect(players, (String) null);
}
/**
* Disconnects these players from the network
*
* @param players Players to select
* @param response Success status
*/
static void disconnect(UUID[] players, IntConsumer response) {
disconnect(players, null, response);
}
/**
* Disconnects these players from the network
*
* @param players Players to select
* @param reason Disconnect Reason
*/
static void disconnect(UUID[] players, String reason) {
disconnect(players, reason, i -> {});
}
/**
* Disconnects these players from the network
*
* @param players Players to select
* @param reason Disconnect Reason
* @param response Success status
*/
static void disconnect(UUID[] players, String reason, IntConsumer response) {
instance.disconnect(players, reason, response);
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Bungee.Library.Fallback;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/**
* Fallback Server Inspector Layout Class
@ -8,10 +9,11 @@ import net.md_5.bungee.api.config.ServerInfo;
public interface FallbackInspector {
/**
* Inspect a fallback server and modify it's confidence score
* Inspect a fallback server and modify its confidence score
*
* @param player Player that requested (may be null)
* @param server Server to inspect
* @return A Positive Value to add points, a Negative Value to subtract points, a Null Value to invalidate the server, or a Zero Value to do nothing
*/
Integer inspect(ServerInfo server);
Double inspect(ProxiedPlayer player, ServerInfo server);
}

View File

@ -0,0 +1,72 @@
package net.ME1312.SubServers.Bungee.Library.Fallback;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.*;
/**
* Fallback Player State Class
*/
public class FallbackState {
public final UUID player;
public final LinkedList<String> names;
public final LinkedList<ServerInfo> servers;
public final BaseComponent[] reason;
private Map<String, ServerInfo> map;
private Timer finish;
/**
* Smart Fallback State Container
*
* @param player Player
* @param servers Fallback Servers
* @param reason Original Disconnect Reason
*/
public FallbackState(UUID player, Map<String, ServerInfo> servers, BaseComponent... reason) {
this.player = player;
this.map = servers;
this.names = new LinkedList<>(servers.keySet());
this.servers = new LinkedList<>(servers.values());
this.reason = reason;
}
/**
* <i>Use</i> a server
*
* @param name Server name to remove
*/
public void remove(String name) {
servers.remove(map.get(name));
names.remove(name);
map.remove(name);
}
/**
* <i>Use</i> a server
*
* @param server Server to remove
*/
public void remove(ServerInfo server) {
map.remove(server.getName());
names.remove(server.getName());
servers.remove(server);
}
/**
* Finish the process
*
* @param callback Finishing callback
* @param delay Delay for determining stability
*/
public void done(Runnable callback, long delay) {
if (finish != null) finish.cancel();
(finish = new Timer("SubServers.Bungee::Fallback_Limbo_Timer(" + player + ')')).schedule(new TimerTask() {
@Override
public void run() {
if (callback != null) callback.run();
finish.cancel();
}
}, delay);
}
}

View File

@ -0,0 +1,209 @@
package net.ME1312.SubServers.Bungee.Library.Fallback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.BungeeCommon;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ReconnectHandler;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Smart Fallback Handler Class
*/
public class SmartFallback implements ReconnectHandler {
private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>();
private static ReconnectHandler reconnect;
public static boolean dns_forward = false;
public SmartFallback(ObjectMap<String> settings) {
dns_forward = settings.getBoolean("DNS-Forward", false);
if (reconnect == null && settings.getBoolean("Reconnect", false))
reconnect = Try.all.get(() -> Util.reflect(ProxyServer.getInstance().getPluginManager().getPlugin("reconnect_yaml").getClass().getClassLoader().loadClass("net.md_5.bungee.module.reconnect.yaml.YamlReconnectHandler").getConstructor()));
}
@Override
public ServerInfo getServer(ProxiedPlayer player) {
return getServer(player, player instanceof UserConnection);
}
protected ServerInfo getServer(ProxiedPlayer player, boolean queue) {
ServerInfo override;
if ((override = getForcedHost(player.getPendingConnection())) != null
|| (override = getDNS(player.getPendingConnection())) != null) {
if (queue) ((UserConnection) player).setServerJoinQueue(new LinkedList<>());
return override;
} else {
Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener(), player);
if ((override = getReconnectServer(player)) != null || !fallbacks.isEmpty()) {
if (queue) ((UserConnection) player).setServerJoinQueue(new LinkedList<>(fallbacks.keySet()));
return (override != null)? override : new LinkedList<>(fallbacks.values()).getFirst();
} else {
return null;
}
}
}
/**
* Grabs the Forced Host Server for this connection
*
* @see AbstractReconnectHandler#getForcedHost(PendingConnection) Essentially the same method, but more ambigous
* @param connection Connection to check
* @return Forced Host Server (or null if there is none)
*/
public static ServerInfo getForcedHost(PendingConnection connection) {
if (connection.getVirtualHost() == null) {
return null;
} else {
String forced = connection.getListener().getForcedHosts().get(connection.getVirtualHost().getHostString());
//if (forced == null && con.getListener().isForceDefault()) { // This is the part of the method that made it ambiguous
// forced = con.getListener().getDefaultServer(); // Aside from that, everything else was fine
//} // :(
return ProxyServer.getInstance().getServerInfo(forced);
}
}
/**
* Grabs the Server that a connection's DNS matches
*
* @param connection Connection to check
* @return DNS Forward Server
*/
public static ServerInfo getDNS(PendingConnection connection) {
if (connection.getVirtualHost() == null || !dns_forward) {
return null;
} else {
Map.Entry<String, ServerInfo> server = null;
String dns = connection.getVirtualHost().getHostString().toLowerCase();
for (Map.Entry<String, ServerInfo> s : ((BungeeCommon) ProxyServer.getInstance()).getServersCopy().entrySet()) {
if (dns.startsWith(s.getKey().toLowerCase() + '.'))
if (server == null || server.getKey().length() < s.getKey().length())
server = s;
}
return (server == null)?null:server.getValue();
}
}
/**
* Grabs the Server that a player was last connected to
*
* @param player Player
* @return Reconnect Server
*/
public static ServerInfo getReconnectServer(ProxiedPlayer player) {
if (reconnect == null) {
return null;
} else try {
return Util.reflect(reconnect.getClass().getDeclaredMethod("getStoredServer", ProxiedPlayer.class), reconnect, player);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
return null;
}
}
/**
* Generates a <i>smart</i> sorted map of fallback servers using a generated confidence score
*
* @param listener Listener to grab fallback servers from
* @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) {
return getFallbackServers(listener, null);
}
/**
* Generates a <i>smart</i> sorted map of fallback servers using a generated confidence score
*
* @param listener Listener to grab fallback servers from
* @param player Player that is requesting fallback servers
* @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener, ProxiedPlayer player) {
TreeMap<Double, List<ServerInfo>> score = new TreeMap<Double, List<ServerInfo>>(Collections.reverseOrder());
for (String name : listener.getServerPriority()) {
ServerInfo server = ProxyServer.getInstance().getServerInfo(name);
if (server != null) {
boolean valid = true;
double confidence = 0;
List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>();
inspectors.addAll(SmartFallback.inspectors);
for (FallbackInspector inspector : inspectors) try {
Double response = inspector.inspect(player, server);
if (response == null) {
valid = false;
} else {
confidence += response;
}
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running inspecting fallback server: " + server.getName()).printStackTrace();
}
if (valid) {
List<ServerInfo> servers = (score.containsKey(confidence))?score.get(confidence):new LinkedList<ServerInfo>();
servers.add(server);
score.put(confidence, servers);
}
}
}
Random random = new Random();
LinkedHashMap<String, ServerInfo> map = new LinkedHashMap<String, ServerInfo>();
for (List<ServerInfo> servers : score.values()) {
while (!servers.isEmpty()) {
ServerInfo next = servers.get(random.nextInt(servers.size()));
map.put(next.getName(), next);
servers.remove(next);
}
}
return map;
}
/**
* Add a Fallback Server Inspector
*
* @param inspector Inspector
*/
public static void addInspector(FallbackInspector inspector) {
Util.nullpo(inspector);
inspectors.add(inspector);
}
/**
* Remove a Fallback Server Inspector
*
* @param inspector Inspector
*/
public static void removeInspector(FallbackInspector inspector) {
Util.nullpo(inspector);
Try.all.run(() -> inspectors.remove(inspector));
}
@Override
public void setServer(ProxiedPlayer player) {
if (reconnect != null) reconnect.setServer(player);
}
@Override
public void save() {
if (reconnect != null) reconnect.save();
}
@Override
public void close() {
if (reconnect != null) reconnect.close();
}
}

View File

@ -0,0 +1,909 @@
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.SubServers.Bungee.BungeeAPI;
import net.ME1312.SubServers.Bungee.BungeeCommon;
import gnu.trove.map.hash.TIntObjectHashMap;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import net.md_5.bungee.protocol.ProtocolConstants;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
/**
* SubServers BStats Metrics Implementation
*/
public class Metrics {
private final Plugin plugin;
private final MetricsBase metricsBase;
private boolean enabled;
private String serverUUID;
private boolean logErrors = false;
private boolean logSentData;
private boolean logResponseStatusText;
/**
* Creates a new Metrics instance.
*
* @param plugin Your plugin instance.
* @param serviceId The id of the service. It can be found at <a
* href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public Metrics(Plugin plugin, int serviceId) {
this.plugin = plugin;
try {
loadConfig();
} catch (IOException e) {
// Failed to load configuration
plugin.getLogger().log(Level.WARNING, "Failed to load bStats config!", e);
metricsBase = null;
return;
}
metricsBase =
new MetricsBase(
"bungeecord",
serverUUID,
serviceId,
enabled,
this::appendPlatformData,
this::appendServiceData,
null,
() -> true,
(message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
(message) -> this.plugin.getLogger().log(Level.INFO, message),
logErrors,
logSentData,
logResponseStatusText);
}
/** Loads the bStats configuration. */
private void loadConfig() throws IOException {
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
bStatsFolder.mkdirs();
File configFile = new File(bStatsFolder, "config.yml");
if (!configFile.exists()) {
writeFile(
configFile,
"# bStats (https://bStats.org) collects some basic information for plugin authors, like how",
"# many people use their plugin and their total player count. It's recommended to keep bStats",
"# enabled, but if you're not comfortable with this, you can turn this setting off. There is no",
"# performance penalty associated with having metrics enabled, and data sent to bStats is fully",
"# anonymous.",
"enabled: true",
"serverUuid: \"" + UUID.randomUUID() + "\"",
"logFailedRequests: false",
"logSentData: false",
"logResponseStatusText: false");
}
Configuration configuration =
ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
// Load configuration
enabled = configuration.getBoolean("enabled", true);
serverUUID = configuration.getString("serverUuid");
logErrors = configuration.getBoolean("logFailedRequests", false);
logSentData = configuration.getBoolean("logSentData", false);
logResponseStatusText = configuration.getBoolean("logResponseStatusText", false);
}
private void writeFile(File file, String... lines) throws IOException {
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
for (String line : lines) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
}
}
private static final AdvancedPie PLAYER_VERSIONS;
static {
final int[] PROTOCOL_VERSIONS;
final String[] PROTOCOL_NAMES;
{
TIntObjectHashMap<String> protocols = new TIntObjectHashMap<String>();
try {
for (Field f : ProtocolConstants.class.getDeclaredFields()) {
int fm = f.getModifiers();
if (Modifier.isPublic(fm) && Modifier.isStatic(fm) && Modifier.isFinal(fm) && f.getType() == int.class && f.getName().startsWith("MINECRAFT_")) {
protocols.put(f.getInt(null), f.getName().substring(10).replace('_', '.'));
}
}
} catch (Throwable e) {
e.printStackTrace();
}
PROTOCOL_VERSIONS = protocols.keys();
PROTOCOL_NAMES = new String[PROTOCOL_VERSIONS.length];
Arrays.sort(PROTOCOL_VERSIONS);
for (int i = 0; i < PROTOCOL_VERSIONS.length; ++i) {
PROTOCOL_NAMES[i] = protocols.get(PROTOCOL_VERSIONS[i]);
}
}
PLAYER_VERSIONS = new AdvancedPie("player_versions", () -> {
int[] players = new int[PROTOCOL_VERSIONS.length];
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
int i = Arrays.binarySearch(PROTOCOL_VERSIONS, player.getPendingConnection().getVersion());
if (i != -1) {
++players[i];
}
}
HashMap<String, Integer> map = new HashMap<String, Integer>();
for (int i = 0; i < PROTOCOL_NAMES.length; ++i) if (players[i] != 0) {
map.put(PROTOCOL_NAMES[i], players[i]);
}
return map;
});
}
/**
* Add subservers platform information as custom charts
*/
public Metrics addPlatformCharts() {
return addCustomChart(new SimplePie("subservers_version", () -> BungeeAPI.getInstance().getWrapperVersion().toString())).addCustomChart(PLAYER_VERSIONS);
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public Metrics addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
return this;
}
private void appendPlatformData(JsonObjectBuilder builder) {
builder.appendField("playerAmount", plugin.getProxy().getOnlineCount());
builder.appendField("managedServers", ((BungeeCommon) plugin.getProxy()).getServersCopy().size());
builder.appendField("onlineMode", plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0);
builder.appendField("bungeecordVersion", plugin.getProxy().getVersion());
builder.appendField("javaVersion", System.getProperty("java.version"));
builder.appendField("osName", System.getProperty("os.name"));
builder.appendField("osArch", System.getProperty("os.arch"));
builder.appendField("osVersion", System.getProperty("os.version"));
builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
}
private void appendServiceData(JsonObjectBuilder builder) {
builder.appendField("pluginVersion", plugin.getDescription().getVersion());
}
public static class MetricsBase {
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "3.0.0";
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private final String platform;
private final String serverUuid;
private final int serviceId;
private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
private final Consumer<Runnable> submitTaskConsumer;
private final Supplier<Boolean> checkServiceEnabledSupplier;
private final BiConsumer<String, Throwable> errorLogger;
private final Consumer<String> infoLogger;
private final boolean logErrors;
private final boolean logSentData;
private final boolean logResponseStatusText;
private final Set<CustomChart> customCharts = new HashSet<>();
private final boolean enabled;
/**
* Creates a new MetricsBase class instance.
*
* @param platform The platform of the service.
* @param serviceId The id of the service.
* @param serverUuid The server uuid.
* @param enabled Whether or not data sending is enabled.
* @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all platform-specific data.
* @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all service-specific data.
* @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
* used to delegate the data collection to a another thread to prevent errors caused by
* concurrency. Can be {@code null}.
* @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
* @param errorLogger A consumer that accepts log message and an error.
* @param infoLogger A consumer that accepts info log messages.
* @param logErrors Whether or not errors should be logged.
* @param logSentData Whether or not the sent data should be logged.
* @param logResponseStatusText Whether or not the response status text should be logged.
*/
public MetricsBase(
String platform,
String serverUuid,
int serviceId,
boolean enabled,
Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
Consumer<JsonObjectBuilder> appendServiceDataConsumer,
Consumer<Runnable> submitTaskConsumer,
Supplier<Boolean> checkServiceEnabledSupplier,
BiConsumer<String, Throwable> errorLogger,
Consumer<String> infoLogger,
boolean logErrors,
boolean logSentData,
boolean logResponseStatusText) {
this.platform = platform;
this.serverUuid = serverUuid;
this.serviceId = serviceId;
this.enabled = enabled;
this.appendPlatformDataConsumer = appendPlatformDataConsumer;
this.appendServiceDataConsumer = appendServiceDataConsumer;
this.submitTaskConsumer = submitTaskConsumer;
this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
this.errorLogger = errorLogger;
this.infoLogger = infoLogger;
this.logErrors = logErrors;
this.logSentData = logSentData;
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
// WARNING: Removing the option to opt-out will get your plugin banned from bStats
startSubmitting();
}
}
public void addCustomChart(CustomChart chart) {
this.customCharts.add(chart);
}
private void startSubmitting() {
final Runnable submitTask =
() -> {
if (!enabled || !checkServiceEnabledSupplier.get()) {
// Submitting data or service is disabled
scheduler.shutdown();
return;
}
if (submitTaskConsumer != null) {
submitTaskConsumer.accept(this::submitData);
} else {
this.submitData();
}
};
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution
// of requests on the
// bStats backend. To circumvent this problem, we introduce some randomness into the initial
// and second delay.
// WARNING: You must not modify and part of this Metrics class, including the submit delay or
// frequency!
// WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it!
long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(
submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
}
private void submitData() {
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
appendPlatformDataConsumer.accept(baseJsonBuilder);
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
appendServiceDataConsumer.accept(serviceJsonBuilder);
JsonObjectBuilder.JsonObject[] chartData =
customCharts.stream()
.map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
.filter(Objects::nonNull)
.toArray(JsonObjectBuilder.JsonObject[]::new);
serviceJsonBuilder.appendField("id", serviceId);
serviceJsonBuilder.appendField("customCharts", chartData);
baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
baseJsonBuilder.appendField("serverUUID", serverUuid);
baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
scheduler.execute(
() -> {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logErrors) {
errorLogger.accept("Could not submit bStats metrics data", e);
}
}
});
}
private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
if (logSentData) {
infoLogger.accept("Sent bStats metrics data: " + data.toString());
}
String url = String.format(REPORT_URL, platform);
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "Metrics-Service/1");
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try (BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
if (logResponseStatusText) {
infoLogger.accept("Sent data to bStats and received response: " + builder);
}
}
/** Checks that the class was properly relocated. */
private void checkRelocation() {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little
// "trick" ... :D
final String defaultPackage =
new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
final String examplePackage =
new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure no one just copy & pastes the example and uses the wrong package
// names
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
/**
* Gzips the given string.
*
* @param str The string to gzip.
* @return The gzipped string.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
}
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
protected CustomChart(String chartId) {
if (chartId == null) {
throw new IllegalArgumentException("chartId must not be null");
}
this.chartId = chartId;
}
public JsonObjectBuilder.JsonObject getRequestJsonObject(
BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
JsonObjectBuilder builder = new JsonObjectBuilder();
builder.appendField("chartId", chartId);
try {
JsonObjectBuilder.JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
builder.appendField("data", data);
} catch (Throwable t) {
if (logErrors) {
errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return builder.build();
}
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
/**
* An extremely simple JSON builder.
*
* <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
* for its use-case.
*/
public static class JsonObjectBuilder {
private StringBuilder builder = new StringBuilder();
private boolean hasAtLeastOneField = false;
public JsonObjectBuilder() {
builder.append("{");
}
/**
* Appends a null field to the JSON.
*
* @param key The key of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendNull(String key) {
appendFieldUnescaped(key, "null");
return this;
}
/**
* Appends a string field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String value) {
if (value == null) {
throw new IllegalArgumentException("JSON value must not be null");
}
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
return this;
}
/**
* Appends an integer field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int value) {
appendFieldUnescaped(key, String.valueOf(value));
return this;
}
/**
* Appends an object to the JSON.
*
* @param key The key of the field.
* @param object The object.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject object) {
if (object == null) {
throw new IllegalArgumentException("JSON object must not be null");
}
appendFieldUnescaped(key, object.toString());
return this;
}
/**
* Appends a string array to the JSON.
*
* @param key The key of the field.
* @param values The string array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values)
.map(value -> "\"" + escape(value) + "\"")
.collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an integer array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an object array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends a field to the object.
*
* @param key The key of the field.
* @param escapedValue The escaped value of the field.
*/
private void appendFieldUnescaped(String key, String escapedValue) {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
if (key == null) {
throw new IllegalArgumentException("JSON key must not be null");
}
if (hasAtLeastOneField) {
builder.append(",");
}
builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
hasAtLeastOneField = true;
}
/**
* Builds the JSON string and invalidates this builder.
*
* @return The built JSON string.
*/
public JsonObject build() {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
JsonObject object = new JsonObject(builder.append("}").toString());
builder = null;
return object;
}
/**
* Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
*
* <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
* Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
*
* @param value The value to escape.
* @return The escaped value.
*/
private static String escape(String value) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '"') {
builder.append("\\\"");
} else if (c == '\\') {
builder.append("\\\\");
} else if (c <= '\u000F') {
builder.append("\\u000").append(Integer.toHexString(c));
} else if (c <= '\u001F') {
builder.append("\\u00").append(Integer.toHexString(c));
} else {
builder.append(c);
}
}
return builder.toString();
}
/**
* A super simple representation of a JSON object.
*
* <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
* allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
* JsonObject)}.
*/
public static class JsonObject {
private final String value;
private JsonObject(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
}
}

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.ME1312.SubServers</groupId>
@ -24,41 +22,26 @@
<dependency>
<groupId>net.md_5</groupId>
<artifactId>bungeecord-internal</artifactId>
<version>1.9-SNAPSHOT</version>
<version>1.15-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiUtil</artifactId>
<version>19w50b</version>
<groupId>net.ME1312.SubServers</groupId>
<artifactId>SubServers.Bungee.Common</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiEngine</artifactId>
<version>19w50b</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.ME1312.SubData</groupId>
<artifactId>Server</artifactId>
<version>19w50a</version>
<version>23w08b</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.dosse.upnp</groupId>
<artifactId>WaifUPnP</artifactId>
<version>1.1</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.imaginarycode.minecraft</groupId>
<artifactId>RedisBungee</artifactId>
<version>0.3.8-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@ -97,14 +80,14 @@
<tasks>
<mkdir dir="${project.build.directory}" />
<copy file="${basedir}/../LICENSE" todir="${project.build.directory}/classes" />
<mkdir dir="${basedir}/../Artifacts/-Lite" />
<copy file="${basedir}/../Artifacts/SubServers.Client.jar" tofile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/client.jar" />
<mkdir dir="${basedir}/../Artifacts/Modulized" />
<copy file="${basedir}/../Artifacts/SubServers.Client.Universal.jar" tofile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/client.jar" />
<mkdir dir="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates" />
<zip basedir="${basedir}/../SubServers.Creator/src" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/forge.zip" includes="Forge/**" />
<zip basedir="${basedir}/../SubServers.Creator/src" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/paper.zip" includes="Paper/**" />
<zip basedir="${basedir}/../SubServers.Creator/src" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/spigot.zip" includes="Spigot/**" />
<zip basedir="${basedir}/../SubServers.Creator/src" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/sponge.zip" includes="Sponge/**" />
<zip basedir="${basedir}/../SubServers.Creator/src" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/vanilla.zip" includes="Vanilla/**" />
<zip basedir="${basedir}/../SubServers.Creator" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/forge.zip" includes="Forge/**" />
<zip basedir="${basedir}/../SubServers.Creator" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/purpur.zip" includes="Purpur/**" />
<zip basedir="${basedir}/../SubServers.Creator" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/spigot.zip" includes="Spigot/**" />
<zip basedir="${basedir}/../SubServers.Creator" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/sponge.zip" includes="Sponge/**" />
<zip basedir="${basedir}/../SubServers.Creator" destfile="${project.build.directory}/classes/net/ME1312/SubServers/Bungee/Library/Files/Templates/vanilla.zip" includes="Vanilla/**" />
</tasks>
</configuration>
</execution>
@ -116,7 +99,7 @@
</goals>
<configuration>
<tasks> <!-- Dependency Stripped Jar for Testing -->
<jar destfile="${basedir}/../Artifacts/-Lite/SubServers.Bungee.jar" manifest="src/META-INF/MANIFEST.MF">
<jar destfile="${basedir}/../Artifacts/Modulized/SubServers.Bungee.jar" manifest="src/META-INF/MANIFEST.MOD.MF">
<zipfileset src="${basedir}/../Artifacts/SubServers.Bungee.jar" excludes="net/ME1312/Galaxi/** net/ME1312/SubData/**" />
</jar>
</tasks>
@ -124,6 +107,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<finalName>SubServers.Bungee</finalName>
<outputDirectory>../Artifacts/Maven</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
@ -134,9 +126,9 @@
<archive>
<manifestFile>src/META-INF/MANIFEST.MF</manifestFile>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<descriptors>
<descriptor>../SubServers.Client/Common/jar-with-some-dependencies.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
@ -160,18 +152,22 @@
<goal>javadoc</goal>
</goals>
<configuration>
<windowtitle>SubServers.Bungee Javadoc</windowtitle>
<doctitle>SubServers.Bungee Javadoc</doctitle>
<show>public</show>
<windowtitle>SubServers.Bungee</windowtitle>
<doctitle>SubServers.Bungee ${project.version}</doctitle>
<show>protected</show>
<destDir>./</destDir>
<outputDirectory>${basedir}/../Javadoc/SubServers.Bungee</outputDirectory>
<reportOutputDirectory>${basedir}/../Javadoc/SubServers.Bungee</reportOutputDirectory>
<additionalOptions>-Xdoclint:none</additionalOptions>
<links>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiUtil/</link>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiBase/</link>
<link>https://dev.me1312.net/jenkins/job/SubData/javadoc/Server/</link>
<link>https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/</link>
</links>
<includeDependencySources>true</includeDependencySources>
<dependencySourceIncludes>
<dependencySourceInclude>net.ME1312.SubServers:SubServers.Bungee.Common:*</dependencySourceInclude>
</dependencySourceIncludes>
</configuration>
</execution>
</executions>

View File

@ -1,4 +1,4 @@
Manifest-Version: 1.0
Class-Path: GalaxiEngine.jar SubDataServer.jar BungeeCord.jar Waterfall.jar
Class-Path: BungeeCord.jar Waterfall.jar
Main-Class: net.ME1312.SubServers.Bungee.Launch
Implementation-Title: SubServers.Bungee

View File

@ -0,0 +1,4 @@
Manifest-Version: 1.0
Class-Path: libraries/GalaxiBase.jar libraries/SubDataServer.jar libraries/BungeeCord.jar
Main-Class: net.ME1312.SubServers.Bungee.Launch
Implementation-Title: SubServers.Bungee

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -23,7 +24,7 @@ public class SubAddHostEvent extends Event implements SubEvent, Cancellable {
* @param host Host Being Added
*/
public SubAddHostEvent(UUID player, Host host) {
if (Util.isNull(host)) throw new NullPointerException();
Util.nullpo(host);
this.player = player;
this.host = host;
}

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Proxy;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Event;
/**
@ -17,7 +18,7 @@ public class SubAddProxyEvent extends Event implements SubEvent {
* @param proxy Host Being Added
*/
public SubAddProxyEvent(Proxy proxy) {
if (Util.isNull(proxy)) throw new NullPointerException();
Util.nullpo(proxy);
this.proxy = proxy;
}

View File

@ -1,9 +1,10 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -26,7 +27,7 @@ public class SubAddServerEvent extends Event implements SubEvent, Cancellable {
* @param server Server Starting
*/
public SubAddServerEvent(UUID player, Host host, Server server) {
if (Util.isNull(server)) throw new NullPointerException();
Util.nullpo(server);
this.player = player;
this.host = host;
this.server = server;

View File

@ -1,11 +1,12 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -35,7 +36,7 @@ public class SubCreateEvent extends Event implements SubEvent, Cancellable {
* @param port Server Port Number
*/
public SubCreateEvent(UUID player, Host host, String name, SubCreator.ServerTemplate template, Version version, int port) {
if (Util.isNull(host, name, template, port)) throw new NullPointerException();
Util.nullpo(host, name, template);
this.player = player;
this.host = host;
this.name = name;
@ -49,15 +50,16 @@ public class SubCreateEvent extends Event implements SubEvent, Cancellable {
*
* @param player Player Updating
* @param server Server to be Updated
* @param template Server Template
* @param version Server Version
*/
public SubCreateEvent(UUID player, SubServer server, Version version) {
if (Util.isNull(server)) throw new NullPointerException();
public SubCreateEvent(UUID player, SubServer server, SubCreator.ServerTemplate template, Version version) {
Util.nullpo(server);
this.player = player;
this.update = server;
this.name = server.getName();
this.host = server.getHost();
this.template = server.getTemplate();
this.template = template;
this.version = version;
this.port = server.getAddress().getPort();
}

View File

@ -6,6 +6,7 @@ import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.md_5.bungee.api.plugin.Event;
import java.util.UUID;
@ -38,7 +39,7 @@ public class SubCreatedEvent extends Event implements SubEvent {
* @param success Success Status
*/
public SubCreatedEvent(UUID player, Host host, String name, SubCreator.ServerTemplate template, Version version, int port, SubServer server, boolean update, boolean success) {
if (Util.isNull(host, name, template, port)) throw new NullPointerException();
Util.nullpo(host, name, template);
this.player = player;
this.host = host;
this.name = name;

View File

@ -1,11 +1,13 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -18,8 +20,7 @@ public class SubEditServerEvent extends Event implements SubEvent, Cancellable {
private boolean cancelled = false;
private UUID player;
private Server server;
private NamedContainer<String, ObjectMapValue> edit;
private boolean perm;
private Pair<String, ObjectMapValue> edit;
/**
* Server Edit Event
@ -27,16 +28,14 @@ public class SubEditServerEvent extends Event implements SubEvent, Cancellable {
* @param player Player Adding Server
* @param server Server to be Edited
* @param edit Edit to make
* @param permanent If the change is permanent
*/
public SubEditServerEvent(UUID player, Server server, NamedContainer<String, ?> edit, boolean permanent) {
if (Util.isNull(server, edit)) throw new NullPointerException();
public SubEditServerEvent(UUID player, Server server, Pair<String, ?> edit) {
Util.nullpo(server, edit);
ObjectMap<String> section = new ObjectMap<String>();
section.set(".", edit.get());
section.set(".", edit.value());
this.player = player;
this.server = server;
this.edit = new NamedContainer<String, ObjectMapValue>(edit.name(), section.get("."));
this.perm = permanent;
this.edit = new ContainedPair<String, ObjectMapValue>(edit.key(), section.get("."));
}
/**
@ -58,19 +57,10 @@ public class SubEditServerEvent extends Event implements SubEvent, Cancellable {
*
* @return Edit to be made
*/
public NamedContainer<String, ObjectMapValue> getEdit() {
public Pair<String, ObjectMapValue> getEdit() {
return edit;
}
/**
* Gets if the edit is permanent
*
* @return Permanent Status
*/
public boolean isPermanent() {
return perm;
}
/**
* Gets the Cancelled Status
*

View File

@ -1,16 +1,13 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.DataServer;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataServer;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
import java.net.InetAddress;
/**
* SubData Network Connect Event
*/
@ -23,7 +20,7 @@ public class SubNetworkConnectEvent extends Event implements SubEvent, Cancellab
* SubData Network Connect Event
*/
public SubNetworkConnectEvent(DataServer network, DataClient client) {
if (Util.isNull(network, client)) throw new NullPointerException();
Util.nullpo(network, client);
this.network = network;
this.client = client;
}

View File

@ -1,12 +1,11 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.DataServer;
import net.ME1312.SubData.Server.Library.DisconnectReason;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataServer;
import net.md_5.bungee.api.plugin.Event;
/**
@ -21,7 +20,7 @@ public class SubNetworkDisconnectEvent extends Event implements SubEvent {
* SubData Network Disconnect Event
*/
public SubNetworkDisconnectEvent(DataServer network, DataClient client, DisconnectReason reason) {
if (Util.isNull(network, client, reason)) throw new NullPointerException();
Util.nullpo(network, client, reason);
this.network = network;
this.client = client;
this.reason = reason;

View File

@ -4,7 +4,7 @@ import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.DataServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
/**
@ -18,7 +18,7 @@ public class SubNetworkLoginEvent extends Event implements SubEvent {
* SubData Network Login Event
*/
public SubNetworkLoginEvent(DataServer network, DataClient client) {
if (Util.isNull(network, client)) throw new NullPointerException();
Util.nullpo(network, client);
this.network = network;
this.client = client;
}

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -23,7 +24,7 @@ public class SubRemoveHostEvent extends Event implements SubEvent, Cancellable {
* @param host Host to be added
*/
public SubRemoveHostEvent(UUID player, Host host) {
if (Util.isNull(host)) throw new NullPointerException();
Util.nullpo(host);
this.player = player;
this.host = host;
}

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Proxy;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Event;
/**
@ -17,7 +18,7 @@ public class SubRemoveProxyEvent extends Event implements SubEvent {
* @param proxy Host Being Added
*/
public SubRemoveProxyEvent(Proxy proxy) {
if (Util.isNull(proxy)) throw new NullPointerException();
Util.nullpo(proxy);
this.proxy = proxy;
}

View File

@ -1,9 +1,10 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -26,7 +27,7 @@ public class SubRemoveServerEvent extends Event implements SubEvent, Cancellable
* @param server Server Starting
*/
public SubRemoveServerEvent(UUID player, Host host, Server server) {
if (Util.isNull(server)) throw new NullPointerException();
Util.nullpo(server);
this.player = player;
this.host = host;
this.server = server;

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -14,20 +15,24 @@ import java.util.UUID;
public class SubSendCommandEvent extends Event implements SubEvent, Cancellable {
private boolean cancelled = false;
private UUID player;
private SubServer server;
private Server server;
private String command;
private UUID target;
/**
* Server Command Event
*
* @param player Player Commanding Server
* @param server Server being Commanded
* @param player Player Commanding
* @param server Target Server
* @param command Command to Send
* @param target Player that will send
*/
public SubSendCommandEvent(UUID player, SubServer server, String command) {
if (Util.isNull(server, command)) throw new NullPointerException();
public SubSendCommandEvent(UUID player, Server server, String command, UUID target) {
Util.nullpo(server, command);
this.player = player;
this.server = server;
this.command = command;
this.target = target;
}
/**
@ -35,7 +40,7 @@ public class SubSendCommandEvent extends Event implements SubEvent, Cancellable
*
* @return The Server Effected
*/
public SubServer getServer() { return server; }
public Server getServer() { return server; }
/**
* Gets the player that triggered the Event
@ -62,6 +67,15 @@ public class SubSendCommandEvent extends Event implements SubEvent, Cancellable
command = value;
}
/**
* Gets the Player that will be forced to send the Command
*
* @return Target Player or null if Console
*/
public UUID getTarget() {
return target;
}
/**
* Gets the Cancelled Status
*

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -23,7 +24,7 @@ public class SubStartEvent extends Event implements SubEvent, Cancellable {
* @param server Server Starting
*/
public SubStartEvent(UUID player, SubServer server) {
if (Util.isNull(server)) throw new NullPointerException();
Util.nullpo(server);
this.player = player;
this.server = server;
}

View File

@ -3,10 +3,8 @@ package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
import java.util.UUID;
import net.md_5.bungee.api.plugin.Event;
/**
* Server Started Event
@ -21,7 +19,7 @@ public class SubStartedEvent extends Event implements SubEvent {
* @param server Server Starting
*/
public SubStartedEvent(SubServer server) {
if (Util.isNull(server)) throw new NullPointerException();
Util.nullpo(server);
this.server = server;
}

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@ -25,7 +26,7 @@ public class SubStopEvent extends Event implements SubEvent, Cancellable {
* @param force If it was a Forced Shutdown
*/
public SubStopEvent(UUID player, SubServer server, boolean force) {
if (Util.isNull(server, force)) throw new NullPointerException();
Util.nullpo(server, force);
this.player = player;
this.server = server;
this.force = force;

View File

@ -1,8 +1,9 @@
package net.ME1312.SubServers.Bungee.Event;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Library.SubEvent;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Event;
/**
@ -17,7 +18,7 @@ public class SubStoppedEvent extends Event implements SubEvent {
* @param server Server that Stopped
*/
public SubStoppedEvent(SubServer server) {
if (Util.isNull(server)) throw new NullPointerException();
Util.nullpo(server);
this.server = server;
}

View File

@ -1,70 +1,87 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.SubServers.Bungee.Library.Compatibility.JNA;
import net.ME1312.Galaxi.Library.Platform;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Library.Compatibility.JNA;
import java.io.File;
import java.util.stream.Stream;
/**
* Executable Handler Class
*/
public class Executable {
private Executable() {}
private static final boolean USE_SESSION_TRACKING;
/**
* Format a command to be executed
*
* @param gitbash Git Bash location (optional)
* @param exec Executable String
* @return
* @return Formatted Executable
*/
public static String[] parse(String gitbash, String exec) {
if (exec.startsWith("java ")) {
if (exec.startsWith("java "))
exec = '\"' + System.getProperty("java.home") + File.separator + "bin" + File.separator + "java" + '\"' + exec.substring(4);
}
String[] cmd;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
if (Platform.getSystem() == Platform.WINDOWS) {
if (gitbash != null && (exec.toLowerCase().startsWith("bash ") || exec.toLowerCase().startsWith("sh ")))
exec = '"' + gitbash + ((gitbash.endsWith(File.separator))?"":File.separator) + "bin" + File.separatorChar + "sh.exe\" -lc \"" +
exec.replace("\\", "/\\").replace("\"", "\\\"").replace("^", "^^").replace("%", "^%").replace("&", "^&").replace("<", "^<").replace(">", "^>").replace("|", "^|") + '"';
cmd = new String[]{"cmd.exe", "/q", "/c", '"'+exec+'"'};
} else if (USE_SESSION_TRACKING) {
cmd = new String[]{"setsid", "sh", "-lc", exec};
} else {
cmd = new String[]{"sh", "-lc", exec};
}
return cmd;
}
static {
USE_SESSION_TRACKING = Platform.getSystem() != Platform.WINDOWS && Try.all.get(() -> {
Process test = Runtime.getRuntime().exec(new String[]{"setsid", "bash", "-c", "exit 0"});
test.waitFor(); // The purpose of this block is to test for the 'setsid' command
return test.exitValue() == 0;
}, false);
}
/**
* Get the PID of a currently running process
*
* @param process Process
* @return Process ID (null if unknown)
*/
@SuppressWarnings("JavaReflectionMemberAccess")
public static Long pid(Process process) {
if (process.isAlive()) {
try {
return (long) Process.class.getDeclaredMethod("pid").invoke(process);
} catch (Throwable ex) {
try {
if (process.getClass().getName().equals("java.lang.Win32Process") || process.getClass().getName().equals("java.lang.ProcessImpl")) {
try { // Java 9 Standard
return (long) Process.class.getMethod("pid").invoke(process);
} catch (Throwable e) {
try { // Java 8 Not-so-standard
Object response = Util.reflect(process.getClass().getDeclaredField("pid"), process);
if (response instanceof Number) {
return ((Number) response).longValue();
} else throw e;
} catch (Throwable e2) {
if (Platform.getSystem() == Platform.WINDOWS) try {
long handle = Util.reflect(process.getClass().getDeclaredField("handle"), process);
ClassLoader jna = JNA.get();
Class<?> pc = jna.loadClass("com.sun.jna.Pointer"),
ntc = jna.loadClass("com.sun.jna.platform.win32.WinNT$HANDLE"),
k32c = jna.loadClass("com.sun.jna.platform.win32.Kernel32");
k32c = jna.loadClass("com.sun.jna.platform.win32.Kernel32");
Object k32 = k32c.getField("INSTANCE").get(null),
nt = ntc.getConstructor().newInstance();
ntc.getMethod("setPointer", pc).invoke(nt, pc.getMethod("createConstant", long.class).invoke(null, handle));
return ((Number) k32c.getMethod("GetProcessId", ntc).invoke(k32, nt)).longValue();
} else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
Object response = Util.reflect(process.getClass().getDeclaredField("pid"), process);
if (response instanceof Number)
return ((Number) response).longValue();
} catch (Throwable e3) {
// No way to find pid, I suppose.
}
} catch (Throwable e) {}
}
}
}
return null;
@ -77,14 +94,28 @@ public class Executable {
*/
public static void terminate(Process process) {
if (process.isAlive()) {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
Long pid = pid(process);
if (pid != null) try {
Process terminator = Runtime.getRuntime().exec(new String[]{"taskkill.exe", "/T", "/F", "/PID", pid.toString()});
terminator.waitFor();
} catch (Throwable e) {}
Long pid;
if (Platform.getSystem() == Platform.WINDOWS) {
if ((pid = pid(process)) != null) Try.all.run(() -> Runtime.getRuntime().exec(new String[]{"taskkill.exe", "/T", "/F", "/PID", pid.toString()}).waitFor());
} else if (USE_SESSION_TRACKING) {
if ((pid = pid(process)) != null) Try.all.run(() -> Runtime.getRuntime().exec(new String[]{"bash", "-c", "kill -9 $(ps -s " + pid + " -o pid=)"}).waitFor());
}
if (process.isAlive()) process.destroyForcibly();
if (process.isAlive() && terminate9(process)) {
process.destroyForcibly();
}
}
}
private static boolean terminate9(Object handle) {
try { // Attempt iteration over Java 9 ProcessHandle objects
Class<?> clazz = handle.getClass();
Stream<?> children = (Stream<?>) clazz.getMethod("children").invoke(handle);
clazz.getMethod("destroyForcibly").invoke(handle);
children.forEach(Executable::terminate9);
return false;
} catch (Throwable e) {
return true;
}
}
}

View File

@ -1,25 +1,26 @@
package net.ME1312.SubServers.Bungee.Host.External;
import com.google.common.collect.Range;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.ClientHandler;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.Protocol.PacketOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.SubAddServerEvent;
import net.ME1312.SubServers.Bungee.Event.SubRemoveServerEvent;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExAddServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExDeleteServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExRemoveServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExReset;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.BungeeCord;
import com.google.common.collect.Range;
import java.net.InetAddress;
import java.util.*;
@ -31,14 +32,14 @@ public class ExternalHost extends Host implements ClientHandler {
private HashMap<Integer, SubDataClient> subdata = new HashMap<Integer, SubDataClient>();
private HashMap<String, SubServer> servers = new HashMap<String, SubServer>();
private String name;
protected boolean available;
boolean available;
private boolean enabled;
private InetAddress address;
private SubCreator creator;
private String directory;
private LinkedList<PacketObjectOut> queue;
private LinkedList<PacketOut> queue;
private boolean clean;
protected SubProxy plugin;
SubProxy plugin;
/**
* Creates an External Host
@ -61,7 +62,7 @@ public class ExternalHost extends Host implements ClientHandler {
this.address = address;
this.creator = new ExternalSubCreator(this, ports, log, gitBash);
this.directory = directory;
this.queue = new LinkedList<PacketObjectOut>();
this.queue = new LinkedList<PacketOut>();
this.clean = false;
subdata.put(0, null);
@ -69,17 +70,18 @@ public class ExternalHost extends Host implements ClientHandler {
@Override
public DataClient[] getSubData() {
LinkedList<Integer> keys = new LinkedList<Integer>(subdata.keySet());
LinkedList<SubDataClient> channels = new LinkedList<SubDataClient>();
Collections.sort(keys);
for (Integer channel : keys) channels.add(subdata.get(channel));
return channels.toArray(new DataClient[0]);
Integer[] keys = subdata.keySet().toArray(new Integer[0]);
DataClient[] channels = new DataClient[keys.length];
Arrays.sort(keys);
for (int i = 0; i < keys.length; ++i) channels[i] = subdata.get(keys[i]);
return channels;
}
public void setSubData(DataClient client, int channel) {
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client == null && channel == 0) available = false;
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);
}
@ -93,8 +95,8 @@ public class ExternalHost extends Host implements ClientHandler {
for (Integer channel : Util.getBackwards(subdata, (SubDataClient) client)) setSubData(null, channel);
}
protected void queue(PacketObjectOut... packet) {
for (PacketObjectOut p : packet) if (getSubData()[0] == null || !available) {
void queue(PacketOut... packet) {
for (PacketOut p : packet) if (getSubData()[0] == null || !available) {
queue.add(p);
} else {
((SubDataClient) getSubData()[0]).sendPacket(p);
@ -106,16 +108,27 @@ public class ExternalHost extends Host implements ClientHandler {
client.sendPacket(new PacketOutExReset("Prevent Desync"));
clean = true;
}
HashSet<String> served = new HashSet<String>();
LinkedList<PacketOut> queue = this.queue; this.queue = new LinkedList<PacketOut>();
PacketOut[] payload = new PacketOut[queue.size()];
for (int i = 0; i < payload.length; ++i) {
PacketOut packet = queue.get(i);
if (packet instanceof PacketExAddServer) served.add(((PacketExAddServer) packet).peek());
payload[i] = packet;
}
for (SubServer server : servers.values()) {
client.sendPacket(new PacketExAddServer(server.getName(), server.isEnabled(), server.getAddress().getPort(), server.isLogging(), server.getPath(), ((ExternalSubServer) server).exec, server.getStopCommand(), (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
}));
}
while (queue.size() != 0) {
client.sendPacket(queue.get(0));
queue.remove(0);
if (!served.contains(server.getName())) {
client.sendPacket(new PacketExAddServer((ExternalSubServer) server, (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
else if (server.isRunning()) ((ExternalSubServer) server).stopped(false);
}));
}
}
client.sendPacket(payload);
available = true;
while (this.queue.size() != 0) {
client.sendPacket(this.queue.remove(0));
}
}
@Override
@ -160,42 +173,52 @@ public class ExternalHost extends Host implements ClientHandler {
@Override
public SubServer getSubServer(String name) {
if (Util.isNull(name)) throw new NullPointerException();
return getSubServers().get(name.toLowerCase());
if (Util.isNull(name)) return null;
return servers.get(name.toLowerCase());
}
@Override
public SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
if (plugin.api.getServers().keySet().contains(name.toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
ExternalSubServer server = new ExternalSubServer(this, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
public SubServer constructSubServer(String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
return ExternalSubServer.construct(this, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
@Override
public boolean addSubServer(UUID player, SubServer server) throws InvalidServerException {
if (server.getHost() != this) throw new IllegalArgumentException("That Server does not belong to this Host!");
if (plugin.api.getServers().containsKey(server.getName().toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
SubAddServerEvent event = new SubAddServerEvent(player, this, server);
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
queue(new PacketExAddServer(name, enabled, port, log, directory, executable, stopcmd, (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) server.started(data.getUUID(0x0002));
queue(new PacketExAddServer(((ExternalSubServer) server), (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
((ExternalSubServer) server).registered(true);
}));
servers.put(name.toLowerCase(), server);
return server;
servers.put(server.getName().toLowerCase(), server);
return true;
} else {
return null;
return false;
}
}
@Override
public boolean removeSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
protected boolean removeSubServer(UUID player, String name, boolean forced) throws InterruptedException {
Util.nullpo(name);
ExternalSubServer server = (ExternalSubServer) servers.get(name.toLowerCase());
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, server);
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
if (forced || !event.isCancelled()) {
server.registered(false);
if (server.isRunning()) {
server.stop();
server.waitFor();
}
queue(new PacketExRemoveServer(server, data -> {
if (data.getInt(0x0001) == 0 || data.getInt(0x0001) == 1) {
servers.remove(server.toLowerCase());
servers.remove(name.toLowerCase());
queue(new PacketExRemoveServer(name.toLowerCase(), data -> {
if (data.getInt(0x0001) != 0 && data.getInt(0x0001) != 1) {
server.registered(true);
servers.put(name.toLowerCase(), server);
}
}));
return true;
@ -203,35 +226,18 @@ public class ExternalHost extends Host implements ClientHandler {
}
@Override
public boolean forceRemoveSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
protected boolean recycleSubServer(UUID player, String name, boolean forced) throws InterruptedException {
Util.nullpo(name);
ExternalSubServer s = (ExternalSubServer) servers.get(name.toLowerCase());
String server = s.getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, s);
plugin.getPluginManager().callEvent(event);
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
}
queue(new PacketExRemoveServer(server, data -> {
if (data.getInt(0x0001) == 0 || data.getInt(0x0001) == 1) {
servers.remove(server.toLowerCase());
}
}));
return true;
}
@Override
public boolean recycleSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
if (forced || !event.isCancelled()) {
s.registered(false);
if (s.isRunning()) {
s.stop();
s.waitFor();
}
Logger.get("SubServers").info("Saving...");
@ -253,6 +259,7 @@ public class ExternalHost extends Host implements ClientHandler {
servers.remove(server.toLowerCase());
Logger.get("SubServers").info("Deleted SubServer: " + server);
} else {
s.registered(true);
Logger.get("SubServers").info("Couldn't remove " + server + " from memory. See " + getName() + " console for more details");
}
}));
@ -261,53 +268,18 @@ public class ExternalHost extends Host implements ClientHandler {
}
@Override
public boolean forceRecycleSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
protected boolean deleteSubServer(UUID player, String name, boolean forced) throws InterruptedException {
Util.nullpo(name);
ExternalSubServer s = (ExternalSubServer) servers.get(name.toLowerCase());
String server = s.getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
plugin.getPluginManager().callEvent(event);
if (getSubServer(server).isRunning()) {
getSubServer(server).terminate();
}
Logger.get("SubServers").info("Saving...");
ObjectMap<String> info = (plugin.servers.get().getMap("Servers").getKeys().contains(server))?plugin.servers.get().getMap("Servers").getMap(server).clone():new ObjectMap<String>();
info.set("Name", server);
info.set("Timestamp", Calendar.getInstance().getTime().getTime());
try {
if (plugin.servers.get().getMap("Servers").getKeys().contains(server)) {
plugin.servers.get().getMap("Servers").remove(server);
plugin.servers.save();
}
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Moving Files...");
queue(new PacketExDeleteServer(server, info, true, data -> {
if (data.getInt(0x0001) == 0 || data.getInt(0x0001) == 1) {
for (String group : getSubServer(server).getGroups()) getSubServer(server).removeGroup(group);
servers.remove(server.toLowerCase());
Logger.get("SubServers").info("Deleted SubServer: " + server);
} else {
Logger.get("SubServers").info("Couldn't remove " + server + " from memory. See " + getName() + " console for more details");
}
}));
return true;
}
@Override
public boolean deleteSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
if (forced || !event.isCancelled()) {
s.registered(false);
if (s.isRunning()) {
s.stop();
s.waitFor();
}
Logger.get("SubServers").info("Saving...");
@ -329,6 +301,7 @@ public class ExternalHost extends Host implements ClientHandler {
servers.remove(server.toLowerCase());
Logger.get("SubServers").info("Deleted SubServer: " + server);
} else {
s.registered(true);
Logger.get("SubServers").info("Couldn't remove " + server + " from memory. See " + getName() + " console for more details");
}
}));
@ -336,46 +309,9 @@ public class ExternalHost extends Host implements ClientHandler {
} else return false;
}
@Override
public boolean forceDeleteSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
plugin.getPluginManager().callEvent(event);
if (getSubServer(server).isRunning()) {
getSubServer(server).terminate();
}
Logger.get("SubServers").info("Saving...");
ObjectMap<String> info = (plugin.servers.get().getMap("Servers").getKeys().contains(server))?plugin.servers.get().getMap("Servers").getMap(server).clone():new ObjectMap<String>();
info.set("Name", server);
info.set("Timestamp", Calendar.getInstance().getTime().getTime());
try {
if (plugin.servers.get().getMap("Servers").getKeys().contains(server)) {
plugin.servers.get().getMap("Servers").remove(server);
plugin.servers.save();
}
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Removing Files...");
queue(new PacketExDeleteServer(server, info, false, data -> {
if (data.getInt(0x0001) == 0 || data.getInt(0x0001) == 1) {
for (String group : getSubServer(server).getGroups()) getSubServer(server).removeGroup(group);
servers.remove(server.toLowerCase());
Logger.get("SubServers").info("Deleted SubServer: " + server);
} else {
Logger.get("SubServers").info("Couldn't remove " + server + " from memory. See " + getName() + " console for more details");
}
}));
return true;
}
@Override
public boolean destroy() {
if (Util.getDespiteException(() -> Util.reflect(BungeeCord.class.getDeclaredField("isRunning"), plugin), true)) {
if (Try.all.get(() -> Util.reflect(SubProxy.class.getDeclaredField("running"), plugin), true)) {
return super.destroy();
}
return true;

View File

@ -1,26 +1,38 @@
package net.ME1312.SubServers.Bungee.Host.External;
import com.google.common.collect.Range;
import net.ME1312.Galaxi.Library.*;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Callback.ReturnCallback;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.SubCreateEvent;
import net.ME1312.SubServers.Bungee.Event.SubCreatedEvent;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubLogger;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.Host.SubServer.StopAction;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExConfigureHost;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExCreateServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExDownloadTemplates;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExUploadTemplates;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import com.google.common.collect.Range;
import net.md_5.bungee.api.ChatColor;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.function.Consumer;
/**
* External SubCreator Class
@ -28,11 +40,13 @@ import java.util.*;
@SuppressWarnings("unchecked")
public class ExternalSubCreator extends SubCreator {
private HashMap<String, ServerTemplate> templates = new HashMap<String, ServerTemplate>();
private HashMap<String, ServerTemplate> templatesR = new HashMap<String, ServerTemplate>();
private Boolean enableRT = false;
private ExternalHost host;
private Range<Integer> ports;
private Container<Boolean> log;
private Value<Boolean> log;
private String gitBash;
private TreeMap<String, NamedContainer<Integer, ExternalSubLogger>> thread;
private TreeMap<String, Pair<Integer, ExternalSubLogger>> thread;
/**
* Creates an External SubCreator
@ -44,121 +58,66 @@ public class ExternalSubCreator extends SubCreator {
*/
public ExternalSubCreator(ExternalHost host, Range<Integer> ports, boolean log, String gitBash) {
if (!ports.hasLowerBound() || !ports.hasUpperBound()) throw new IllegalArgumentException("Port range is not bound");
if (Util.isNull(host, ports, log, gitBash)) throw new NullPointerException();
Util.nullpo(host, ports, log, gitBash);
this.host = host;
this.ports = ports;
this.log = new Container<Boolean>(log);
this.gitBash = gitBash;
this.thread = new TreeMap<String, NamedContainer<Integer, ExternalSubLogger>>();
this.thread = new TreeMap<String, Pair<Integer, ExternalSubLogger>>();
reload();
}
@Override
public void reload() {
templates.clear();
if (new UniversalFile(host.plugin.dir, "SubServers:Templates").exists()) for (File file : new UniversalFile(host.plugin.dir, "SubServers:Templates").listFiles()) {
templatesR.clear();
if (new File(host.plugin.dir, "SubServers/Templates").exists()) for (File file : new File(host.plugin.dir, "SubServers/Templates").listFiles()) {
try {
if (file.isDirectory() && !file.getName().endsWith(".x")) {
ObjectMap<String> config = (new UniversalFile(file, "template.yml").exists())?new YAMLConfig(new UniversalFile(file, "template.yml")).get().getMap("Template", new ObjectMap<String>()):new ObjectMap<String>();
ServerTemplate template = new ServerTemplate(file.getName(), config.getBoolean("Enabled", true), config.getRawString("Icon", "::NULL::"), file, config.getMap("Build", new ObjectMap<String>()), config.getMap("Settings", new ObjectMap<String>()));
templates.put(file.getName().toLowerCase(), template);
if (config.getKeys().contains("Display")) template.setDisplayName(config.getString("Display"));
ObjectMap<String> config = (new File(file, "template.yml").exists())? new YAMLConfig(new File(file, "template.yml")).get().getMap("Template", new ObjectMap<String>()) : new ObjectMap<String>();
ServerTemplate template = loadTemplate(file.getName(), config.getBoolean("Enabled", true), config.getBoolean("Internal", false), config.getString("Icon", "::NULL::"), file, config.getMap("Build", new ObjectMap<String>()), config.getMap("Settings", new ObjectMap<String>()));
templatesR.put(file.getName().toLowerCase(), template);
if (config.getKeys().contains("Display")) template.setDisplayName(Util.unescapeJavaString(config.getString("Display")));
}
} catch (Exception e) {
System.out.println(host.getName() + "/Creator > Couldn't load template: " + file.getName());
Logger.get(host.getName()).severe("Couldn't load template: " + file.getName());
e.printStackTrace();
}
}
if (host.available) host.queue(new PacketExConfigureHost(host.plugin, host));
if (host.available && !Try.all.get(() -> Util.reflect(SubProxy.class.getDeclaredField("reloading"), host.plugin), false)) {
host.queue(new PacketExConfigureHost(host.plugin, host), new PacketExUploadTemplates(host.plugin, () -> {
if (enableRT == null || enableRT) host.queue(new PacketExDownloadTemplates(host.plugin, host));
}));
}
}
@Override
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Callback<SubServer> callback) {
if (Util.isNull(name, template)) throw new NullPointerException();
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().keySet().contains(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Exception().getStackTrace();
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback) {
Util.nullpo(name, template);
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().containsKey(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
if (port == null) {
Container<Integer> i = new Container<Integer>(ports.lowerEndpoint() - 1);
port = Util.getNew(getAllReservedAddresses(), () -> {
do {
i.set(i.get() + 1);
if (i.get() > ports.upperEndpoint()) throw new IllegalStateException("There are no more ports available in range: " + ports.toString());
} while (!ports.contains(i.get()));
return new InetSocketAddress(host.getAddress(), i.get());
++i.value;
if (i.value > ports.upperEndpoint()) throw new IllegalStateException("There are no more ports available in range: " + ports.toString());
} while (!ports.contains(i.value));
return new InetSocketAddress(host.getAddress(), i.value);
}).getPort();
}
String prefix = name + File.separator + "Creator";
ExternalSubLogger logger = new ExternalSubLogger(this, prefix, log, null);
thread.put(name.toLowerCase(), new NamedContainer<>(port, logger));
thread.put(name.toLowerCase(), new ContainedPair<>(port, logger));
final int fport = port;
final SubCreateEvent event = new SubCreateEvent(player, host, name, template, version, port);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
Container<String> address = new Container<>("$address$");
ReturnCallback<Object, Object> conversion = obj -> convert(obj, new NamedContainer<>("$player$", (player == null)?"":player.toString()), new NamedContainer<>("$name$", name),
new NamedContainer<>("$template$", template.getName()), new NamedContainer<>("$type$", template.getType().toString()), new NamedContainer<>("$version$", (version != null)?version.toString().replace(" ", "@"):""),
new NamedContainer<>("$address$", address.get()), new NamedContainer<>("$port$", Integer.toString(fport)));
logger.start();
host.queue(new PacketExCreateServer(name, template, version, port, (template.getConfigOptions().contains("Directory"))?conversion.run(template.getConfigOptions().getRawString("Directory")).toString():name, logger.getExternalAddress(), data -> {
try {
if (data.getInt(0x0001) == 0) {
Logger.get(prefix).info("Saving...");
address.set(data.getRawString(0x0003));
if (host.plugin.exServers.keySet().contains(name.toLowerCase()))
host.plugin.exServers.remove(name.toLowerCase());
ObjectMap<String> server = new ObjectMap<String>();
ObjectMap<String> config = new ObjectMap<String>((Map<String, ?>) conversion.run(data.getMap(0x0002).get()));
config.remove("\033address");
server.set("Enabled", true);
server.set("Display", "");
server.set("Host", host.getName());
server.set("Template", template.getName());
server.set("Group", new ArrayList<String>());
server.set("Port", fport);
server.set("Motd", "Some SubServer");
server.set("Log", true);
server.set("Directory", "./" + name);
server.set("Executable", "java -Xmx1024M -jar " + template.getType().toString() + ".jar");
server.set("Stop-Command", "stop");
server.set("Stop-Action", "NONE");
server.set("Run-On-Launch", false);
server.set("Restricted", false);
server.set("Incompatible", new ArrayList<String>());
server.set("Hidden", false);
server.setAll(config);
SubServer subserver = host.addSubServer(player, name, server.getBoolean("Enabled"), fport, ChatColor.translateAlternateColorCodes('&', server.getString("Motd")), server.getBoolean("Log"), server.getRawString("Directory"),
server.getRawString("Executable"), server.getRawString("Stop-Command"), server.getBoolean("Hidden"), server.getBoolean("Restricted"));
if (server.getString("Display").length() > 0) subserver.setDisplayName(server.getString("Display"));
subserver.setTemplate(getTemplate(server.getRawString("Template")));
for (String group : server.getStringList("Group")) subserver.addGroup(group);
SubServer.StopAction action = Util.getDespiteException(() -> SubServer.StopAction.valueOf(server.getRawString("Stop-Action").toUpperCase().replace('-', '_').replace(' ', '_')), null);
if (action != null) subserver.setStopAction(action);
if (server.contains("Extra")) for (String extra : server.getMap("Extra").getKeys())
subserver.addExtra(extra, server.getMap("Extra").getObject(extra));
host.plugin.servers.get().getMap("Servers").set(name, server);
host.plugin.servers.save();
if (template.getBuildOptions().getBoolean("Run-On-Finish", true))
subserver.start();
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, fport, subserver, false, true));
callback(origin, callback, subserver);
} else {
Logger.get(prefix).info(data.getString(0x0004));
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, fport, null, false, false));
callback(origin, callback, null);
}
} catch (Exception e) {
e.printStackTrace();
callback(origin, callback, null);
}
logger.stop();
host.queue(new PacketExCreateServer(player, name, template, version, port, logger.getExternalAddress(), data -> {
finish(player, null, name, template, version, fport, prefix, origin, data, callback);
this.thread.remove(name.toLowerCase());
}));
return true;
@ -167,31 +126,9 @@ public class ExternalSubCreator extends SubCreator {
return false;
}
} else return false;
} private Object convert(Object value, NamedContainer<String, String>... replacements) {
if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key), replacements));
return value;
} else if (value instanceof Collection) {
List<Object> list = new ArrayList<Object>();
for (Object val : (Collection<Object>) value) list.add(convert(val, replacements));
return list;
} else if (value.getClass().isArray()) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < ((Object[]) value).length; i++) list.add(convert(((Object[]) value)[i], replacements));
return list;
} else if (value instanceof String) {
return replace((String) value, replacements);
} else {
return value;
}
} private String replace(String string, NamedContainer<String, String>... replacements) {
for (NamedContainer<String, String> replacement : replacements) string = string.replace(replacement.name(), replacement.get());
return string;
} private <T> void callback(StackTraceElement[] origin, Callback<T> callback, T value) {
} private <T> void callback(StackTraceElement[] origin, Consumer<T> callback, T value) {
if (callback != null) try {
callback.run(value);
callback.accept(value);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
@ -200,38 +137,27 @@ public class ExternalSubCreator extends SubCreator {
}
@Override
public boolean update(UUID player, SubServer server, Version version, Callback<Boolean> callback) {
if (Util.isNull(server)) throw new NullPointerException();
if (host.isAvailable() && host.isEnabled() && host == server.getHost() && server.isAvailable() && !server.isRunning() && server.getTemplate() != null && server.getTemplate().isEnabled() && server.getTemplate().canUpdate() && (version != null || !server.getTemplate().requiresVersion())) {
StackTraceElement[] origin = new Exception().getStackTrace();
public boolean update(UUID player, SubServer server, ServerTemplate template, Version version, Consumer<Boolean> callback) {
Util.nullpo(server);
final ServerTemplate ft = (template == null)?server.getTemplate():template;
if (host.isAvailable() && host.isEnabled() && host == server.getHost() && server.isAvailable() && !server.isRunning() && ft != null && ft.isEnabled() && ft.canUpdate() && (version != null || !ft.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
String name = server.getName();
String prefix = name + File.separator + "Updater";
Util.isException(() -> Util.reflect(SubServerContainer.class.getDeclaredField("updating"), server, true));
((ExternalSubServer) server).updating(true);
ExternalSubLogger logger = new ExternalSubLogger(this, prefix, log, null);
thread.put(name.toLowerCase(), new NamedContainer<>(server.getAddress().getPort(), logger));
thread.put(name.toLowerCase(), new ContainedPair<>(server.getAddress().getPort(), logger));
final SubCreateEvent event = new SubCreateEvent(player, server, version);
final SubCreateEvent event = new SubCreateEvent(player, server, ft, version);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
logger.start();
host.queue(new PacketExCreateServer(server, version, logger.getExternalAddress(), data -> {
Util.isException(() -> Util.reflect(SubServerContainer.class.getDeclaredField("updating"), server, false));
if (data.getInt(0x0001) == 0) {
Logger.get(prefix).info("Saving...");
} else {
Logger.get(prefix).info(data.getString(0x0004));
}
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, server.getTemplate(), version, server.getAddress().getPort(), server, true, data.getInt(0x0001) == 0));
if (callback != null) try {
callback.run(data.getInt(0x0001) == 0);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
ew.printStackTrace();
}
logger.stop();
host.queue(new PacketExCreateServer(player, server, ft, version, logger.getExternalAddress(), data -> {
finish(player, server, server.getName(), ft, version, server.getAddress().getPort(), prefix, origin, data, s -> {
((ExternalSubServer) server).updating(false);
if (callback != null) callback.accept(s != null);
});
this.thread.remove(name.toLowerCase());
}));
return true;
@ -242,9 +168,87 @@ public class ExternalSubCreator extends SubCreator {
} else return false;
}
private void finish(UUID player, SubServer update, String name, ServerTemplate template, Version version, int port, String prefix, StackTraceElement[] origin, ObjectMap<Integer> data, Consumer<SubServer> callback) {
try {
if (data.getInt(0x0001) == 0) {
Logger.get(prefix).info("Saving...");
SubServer subserver = update;
if (update == null || update.getTemplate() != template || template.getBuildOptions().getBoolean("Update-Settings", false)) {
if (host.plugin.exServers.containsKey(name.toLowerCase()))
host.plugin.exServers.remove(name.toLowerCase());
ObjectMap<String> server = new ObjectMap<String>();
ObjectMap<String> config = new ObjectMap<String>((Map<String, ?>) data.getObject(0x0002));
if (config.contains("Directory") && (update != null || !template.getConfigOptions().contains("Directory"))) config.remove("Directory");
if (update == null) {
server.set("Enabled", true);
server.set("Display", "");
server.set("Host", host.getName());
server.set("Template", template.getName());
server.set("Group", new ArrayList<String>());
server.set("Port", port);
server.set("Motd", "Some SubServer");
server.set("Log", true);
server.set("Directory", "./" + name);
server.set("Executable", "java -Xmx1024M -jar " + template.getType().toString() + ".jar");
server.set("Stop-Command", "stop");
server.set("Stop-Action", "NONE");
server.set("Run-On-Launch", false);
server.set("Restricted", false);
server.set("Incompatible", new ArrayList<String>());
server.set("Hidden", false);
} else {
server.setAll(host.plugin.servers.get().getMap("Servers").getMap(name, new HashMap<>()));
server.set("Template", template.getName());
}
server.setAll(config);
if (update != null) Try.all.run(() -> update.getHost().forceRemoveSubServer(name));
subserver = host.constructSubServer(name, server.getBoolean("Enabled"), port, ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(server.getString("Motd"))), server.getBoolean("Log"),
server.getString("Directory"), server.getString("Executable"), server.getString("Stop-Command"), server.getBoolean("Hidden"), server.getBoolean("Restricted"));
if (server.getString("Display").length() > 0) subserver.setDisplayName(Util.unescapeJavaString(server.getString("Display")));
subserver.setTemplate(server.getString("Template"));
for (String group : server.getStringList("Group")) subserver.addGroup(group);
SubServer.StopAction action = Try.all.get(() -> SubServer.StopAction.valueOf(server.getString("Stop-Action").toUpperCase().replace('-', '_').replace(' ', '_')));
if (action != null) subserver.setStopAction(action);
if (server.contains("Extra")) for (String extra : server.getMap("Extra").getKeys())
subserver.addExtra(extra, server.getMap("Extra").getObject(extra));
if ((update != null && host.plugin.servers.get().getMap("Servers").contains(name)) ||
!(subserver.getStopAction() == StopAction.REMOVE_SERVER || subserver.getStopAction() == StopAction.RECYCLE_SERVER || subserver.getStopAction() == StopAction.DELETE_SERVER)) {
host.plugin.servers.get().getMap("Servers").set(name, server);
host.plugin.servers.save();
}
host.addSubServer(subserver);
if (update == null && template.getBuildOptions().getBoolean("Run-On-Finish", true)) {
while (!subserver.isAvailable() && host.isAvailable()) {
Thread.sleep(250);
}
if (subserver.isAvailable()) {
subserver.start();
}
}
}
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, port, subserver, update != null, true));
callback(origin, callback, subserver);
} else {
Logger.get(prefix).info(data.getString(0x0003));
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, port, update, update != null, false));
callback(origin, callback, null);
}
} catch (Exception e) {
e.printStackTrace();
callback(origin, callback, null);
}
}
@Override
public void terminate() {
HashMap<String, NamedContainer<Integer, ExternalSubLogger>> thread = new HashMap<String, NamedContainer<Integer, ExternalSubLogger>>();
HashMap<String, Pair<Integer, ExternalSubLogger>> thread = new HashMap<String, Pair<Integer, ExternalSubLogger>>();
thread.putAll(this.thread);
for (String i : thread.keySet()) {
terminate(i);
@ -253,7 +257,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
if (this.thread.containsKey(name.toLowerCase())) {
((SubDataClient) host.getSubData()[0]).sendPacket(new PacketExCreateServer(name.toLowerCase()));
thread.remove(name.toLowerCase());
}
@ -261,7 +265,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public void waitFor() throws InterruptedException {
HashMap<String, NamedContainer<Integer, ExternalSubLogger>> thread = new HashMap<String, NamedContainer<Integer, ExternalSubLogger>>();
HashMap<String, Pair<Integer, ExternalSubLogger>> thread = new HashMap<String, Pair<Integer, ExternalSubLogger>>();
thread.putAll(this.thread);
for (String i : thread.keySet()) {
waitFor(i);
@ -270,7 +274,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public void waitFor(String name) throws InterruptedException {
while (this.thread.keySet().contains(name.toLowerCase()) && host.getSubData()[0] != null) {
while (this.thread.containsKey(name.toLowerCase()) && host.getSubData()[0] != null) {
Thread.sleep(250);
}
}
@ -299,7 +303,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public List<SubLogger> getLoggers() {
List<SubLogger> loggers = new ArrayList<SubLogger>();
HashMap<String, NamedContainer<Integer, ExternalSubLogger>> temp = new HashMap<String, NamedContainer<Integer, ExternalSubLogger>>();
HashMap<String, Pair<Integer, ExternalSubLogger>> temp = new HashMap<String, Pair<Integer, ExternalSubLogger>>();
temp.putAll(thread);
for (String i : temp.keySet()) {
loggers.add(getLogger(i));
@ -309,18 +313,18 @@ public class ExternalSubCreator extends SubCreator {
@Override
public SubLogger getLogger(String name) {
return this.thread.get(name.toLowerCase()).get();
return this.thread.get(name.toLowerCase()).value();
}
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
@Override
public void setLogging(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
log.set(value);
Util.nullpo(value);
log.value(value);
}
@Override
@ -331,18 +335,33 @@ public class ExternalSubCreator extends SubCreator {
@Override
public List<Integer> getReservedPorts() {
List<Integer> ports = new ArrayList<Integer>();
for (NamedContainer<Integer, ExternalSubLogger> task : thread.values()) ports.add(task.name());
for (Pair<Integer, ExternalSubLogger> task : thread.values()) ports.add(task.key());
return ports;
}
@Override
public Map<String, ServerTemplate> getTemplates() {
return new TreeMap<String, ServerTemplate>(templates);
TreeMap<String, ServerTemplate> map = new TreeMap<String, ServerTemplate>();
if (enableRT != null && enableRT) for (Map.Entry<String, ServerTemplate> template : templatesR.entrySet()) {
if (!template.getValue().isInternal()) map.put(template.getKey(), template.getValue());
}
for (Map.Entry<String, ServerTemplate> template : templates.entrySet()) {
if (!template.getValue().isInternal()) map.put(template.getKey(), template.getValue());
}
return map;
}
@Override
public ServerTemplate getTemplate(String name) {
if (Util.isNull(name)) throw new NullPointerException();
return getTemplates().get(name.toLowerCase());
Util.nullpo(name);
name = name.toLowerCase();
ServerTemplate template = templates.getOrDefault(name, null);
if (template == null && enableRT != null && enableRT) template = templatesR.getOrDefault(name, null);
if (template == null || template.isInternal()) {
return null;
} else {
return template;
}
}
}

View File

@ -1,37 +1,37 @@
package net.ME1312.SubServers.Bungee.Host.External;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubLogFilter;
import net.ME1312.SubServers.Bungee.Host.SubLogger;
import net.ME1312.Galaxi.Library.Container;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketInExLogMessage;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.ProxyServer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* External Process Logger Class
*/
public class ExternalSubLogger extends SubLogger {
private Object handle;
protected UUID id = null;
protected String name;
protected Container<Boolean> log;
UUID id = null;
String name;
Value<Boolean> log;
private List<SubLogFilter> filters = new CopyOnWriteArrayList<>();
protected File file;
File file;
private PrintWriter writer = null;
private boolean started = false;
@ -43,7 +43,7 @@ public class ExternalSubLogger extends SubLogger {
* @param log Console Logging Status
* @param file File to log to (or null for disabled)
*/
protected ExternalSubLogger(Object user, String name, Container<Boolean> log, File file) {
ExternalSubLogger(Object user, String name, Value<Boolean> log, File file) {
this.handle = user;
this.name = name;
this.log = log;
@ -73,29 +73,20 @@ public class ExternalSubLogger extends SubLogger {
}
@SuppressWarnings("deprecation")
private void log(String line) {
private void log(int type, String msg) {
if (started) {
String msg = line;
Level level;
// REGEX Formatting
String type = "";
Matcher matcher = Pattern.compile("^((?:\\s*\\[?([0-9]{2}:[0-9]{2}:[0-9]{2})]?)?[\\s\\/\\\\\\|]*(?:\\[|\\[.*\\/)?(MESSAGE|INFO|WARNING|WARN|ERROR|ERR|SEVERE)\\]?:?(?:\\s*>)?\\s*)").matcher(msg.replaceAll("\u001B\\[[;\\d]*m", ""));
while (matcher.find()) {
type = matcher.group(3).toUpperCase();
}
msg = msg.substring(msg.length() - msg.replaceAll("^((?:\\s*\\[?([0-9]{2}:[0-9]{2}:[0-9]{2})]?)?[\\s\\/\\\\\\|]*(?:\\[|\\[.*\\/)?(MESSAGE|INFO|WARNING|WARN|ERROR|ERR|SEVERE)\\]?:?(?:\\s*>)?\\s*)", "").length());
// Determine LOG LEVEL
switch (type) {
case "WARNING":
case "WARN":
case 80:
level = Level.FINE;
break;
case 40:
level = Level.WARNING;
break;
case "SEVERE":
case "ERROR":
case "ERR":
case 30:
case 20:
level = Level.SEVERE;
break;
default:
@ -103,7 +94,7 @@ public class ExternalSubLogger extends SubLogger {
}
// Filter Message
boolean allow = (SubAPI.getInstance().getInternals().sudo == getHandler() && SubAPI.getInstance().getInternals().canSudo) || (log.get() && (SubAPI.getInstance().getInternals().sudo == null || !SubAPI.getInstance().getInternals().canSudo));
boolean allow = (SubAPI.getInstance().getInternals().sudo == getHandler() && SubAPI.getInstance().getInternals().canSudo) || (log.value() && (SubAPI.getInstance().getInternals().sudo == null || !SubAPI.getInstance().getInternals().canSudo));
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters)
@ -118,7 +109,7 @@ public class ExternalSubLogger extends SubLogger {
// Log to FILE
if (writer != null) {
writer.println(line);
writer.println('[' + new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()) + "] [" + level + "] > " + msg);
writer.flush();
}
}
@ -135,20 +126,19 @@ public class ExternalSubLogger extends SubLogger {
@Override
public void registerFilter(SubLogFilter filter) {
if (Util.isNull(filter)) throw new NullPointerException();
Util.nullpo(filter);
filters.add(filter);
}
@Override
public void unregisterFilter(SubLogFilter filter) {
if (Util.isNull(filter)) throw new NullPointerException();
Util.isException(() -> filters.remove(filter));
Util.nullpo(filter);
Try.all.run(() -> filters.remove(filter));
}
@Override
public void stop() {
if (started) {
PacketInExLogMessage.unregister(id);
id = null;
started = false;
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
@ -161,7 +151,7 @@ public class ExternalSubLogger extends SubLogger {
if (writer != null) {
PrintWriter writer = this.writer;
this.writer = null;
int l = (int) Math.floor((("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2);
int l = (("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2;
String s = "";
while (s.length() < l) s += '-';
writer.println(s + " LOG END " + s);
@ -182,6 +172,6 @@ public class ExternalSubLogger extends SubLogger {
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
}

View File

@ -1,35 +1,41 @@
package net.ME1312.SubServers.Bungee.Host.External;
import net.ME1312.Galaxi.Library.Callback.ReturnRunnable;
import net.ME1312.SubServers.Bungee.Event.*;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Container;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.*;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExEditServer;
import net.md_5.bungee.BungeeServerInfo;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExControlServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExControlServer.Action;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer.Edit;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.ChatColor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;
/**
* External SubServer Class
*/
public class ExternalSubServer extends SubServerContainer {
public class ExternalSubServer extends SubServerImpl {
private ExternalHost host;
private boolean enabled;
private Container<Boolean> log;
private Value<Boolean> log;
private String dir;
protected String exec;
String exec;
private String stopcmd;
private StopAction stopaction;
private LinkedList<LoggedCommand> history;
@ -53,9 +59,34 @@ public class ExternalSubServer extends SubServerContainer {
* @param restricted Restricted Status
* @throws InvalidServerException
*/
public ExternalSubServer(ExternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
public static ExternalSubServer construct(ExternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
try {
return new ExternalSubServer(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
} catch (NoSuchMethodError e) {
return new ExternalSubServer(host, name, enabled, (Integer) port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
}
/**
* Super Method 2 (newest)
* @see #construct(ExternalHost, String, boolean, int, String, boolean, String, String, String, boolean, boolean) for method details
*/
protected ExternalSubServer(ExternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
if (Util.isNull(host, name, enabled, port, motd, log, stopcmd, hidden, restricted)) throw new NullPointerException();
init(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
/**
* Super Method 1 (oldest)
* @see #construct(ExternalHost, String, boolean, int, String, boolean, String, String, String, boolean, boolean) for method details
*/
protected ExternalSubServer(ExternalHost host, String name, boolean enabled, Integer port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
init(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
private void init(ExternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
Util.nullpo(host, name, enabled, port, motd, log, stopcmd, hidden, restricted);
this.host = host;
this.enabled = enabled;
this.log = new Container<Boolean>(log);
@ -70,26 +101,43 @@ public class ExternalSubServer extends SubServerContainer {
this.lock = false;
}
void registered(boolean value) {
registered = value;
}
void updating(boolean value) {
updating = value;
}
@Override
public boolean start(UUID player) {
if (!lock && isAvailable() && isEnabled() && !running && getCurrentIncompatibilities().size() == 0) {
lock = true;
SubStartEvent event = new SubStartEvent(player, this);
host.plugin.getPluginManager().callEvent(event);
lock = false;
if (!event.isCancelled()) {
Logger.get("SubServers").info("Now starting " + getName());
started(null);
host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.START, logger.getExternalAddress().toString()));
host.queue(new PacketExControlServer(this, Action.START, logger.getExternalAddress().toString()));
return true;
} else return false;
} else {
lock = false;
return false;
}
} else return false;
}
void started(UUID address) {
started = false;
running = true;
logger.start();
if (address != null && address != logger.getExternalAddress()) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_LOGGING_ADDRESS, logger.getExternalAddress().toString()));
if (!running) {
stopping = false;
started = false;
running = true;
lock = false;
logger.start();
if (address != null) {
if (address != logger.getExternalAddress()) host.queue(new PacketExControlServer(this, Action.SET_LOGGING_ADDRESS, logger.getExternalAddress().toString()));
host.plugin.getPluginManager().callEvent(new SubStartEvent(null, this));
}
}
}
private void falsestart() {
Logger.get("SubServers").info("Couldn't start " + getName() + " - See the " + host.getName() + " console for more details");
@ -104,15 +152,18 @@ public class ExternalSubServer extends SubServerContainer {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
history.add(new LoggedCommand(player, stopcmd));
host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.STOP));
host.queue(new PacketExControlServer(this, Action.STOP));
stopping = true;
return true;
} else return false;
} else return false;
}
private void stopped(Boolean allowrestart) {
void stopped(Boolean allowrestart) {
logger.stop();
history.clear();
started = false;
running = false;
stopping = false;
SubStoppedEvent event = new SubStoppedEvent(this);
host.plugin.getPluginManager().callEvent(event);
Logger.get("SubServers").info(getName() + " has stopped");
@ -157,7 +208,8 @@ public class ExternalSubServer extends SubServerContainer {
SubStopEvent event = new SubStopEvent(player, this, true);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.TERMINATE));
host.queue(new PacketExControlServer(this, Action.TERMINATE));
stopping = true;
return true;
} else return false;
} else return false;
@ -165,32 +217,26 @@ public class ExternalSubServer extends SubServerContainer {
@Override
public boolean command(UUID player, String command) {
if (Util.isNull(command)) throw new NullPointerException();
Util.nullpo(command);
if (running) {
SubSendCommandEvent event = new SubSendCommandEvent(player, this, command);
SubSendCommandEvent event = new SubSendCommandEvent(player, this, command, null);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (!event.isCancelled() && (player == null || !DISALLOWED_COMMANDS.matcher(command).find())) {
history.add(new LoggedCommand(player, event.getCommand()));
if (event.getCommand().equalsIgnoreCase(stopcmd)) {
host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.STOP));
host.queue(new PacketExControlServer(this, Action.STOP));
stopping = true;
} else {
host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.COMMAND, event.getCommand()));
host.queue(new PacketExControlServer(this, Action.COMMAND, event.getCommand()));
}
return true;
} else return false;
} else return false;
}
public int edit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, false);
}
public int permaEdit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, true);
}
@SuppressWarnings({"deprecation", "unchecked"})
private int edit(UUID player, ObjectMap<String> edit, boolean perma) {
@Override
protected int edit(UUID player, ObjectMap<String> edit, boolean perma) {
if (isAvailable()) {
int c = 0;
boolean state = isRunning();
@ -199,14 +245,18 @@ public class ExternalSubServer extends SubServerContainer {
for (String key : edit.getKeys()) {
pending.remove(key);
ObjectMapValue value = edit.get(key);
SubEditServerEvent event = new SubEditServerEvent(player, this, new NamedContainer<String, ObjectMapValue>(key, value), perma);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
boolean allowed = true;
if (perma) {
SubEditServerEvent event = new SubEditServerEvent(player, this, new ContainedPair<String, ObjectMapValue>(key, value));
host.plugin.getPluginManager().callEvent(event);
allowed = !event.isCancelled();
}
if (allowed) {
try {
switch (key.toLowerCase()) {
case "name":
if (value.isString() && host.removeSubServer(player, getName())) {
SubServer server = host.addSubServer(player, value.asRawString(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(value.asString(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
ObjectMap<String> config = this.host.plugin.servers.get().getMap("Servers").getMap(getName());
@ -221,14 +271,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "display":
if (value.isString()) {
Field f = ServerContainer.class.getDeclaredField("nick");
f.setAccessible(true);
if (value.isNull() || value.asString().length() == 0 || getName().equals(value.asString())) {
f.set(this, null);
} else {
f.set(this, value.asString());
}
f.setAccessible(false);
setDisplayName(value.asString());
logger.name = getDisplayName();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
if (getName().equals(getDisplayName())) {
@ -243,7 +286,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "enabled":
if (value.isBoolean()) {
if (enabled != value.asBoolean()) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_ENABLED, (Boolean) value.asBoolean()));
if (enabled != value.asBoolean()) host.queue(new PacketExControlServer(this, Action.SET_ENABLED, (Boolean) value.asBoolean()));
enabled = value.asBoolean();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Enabled", isEnabled());
@ -254,7 +297,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "group":
if (value.isList()) {
Util.reflect(ServerContainer.class.getDeclaredField("groups"), this, value.asStringList());
Util.reflect(ServerImpl.class.getDeclaredField("groups"), this, value.asStringList());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Group", value.asStringList());
this.host.plugin.servers.save();
@ -265,7 +308,7 @@ public class ExternalSubServer extends SubServerContainer {
case "host":
if (value.isString() && host.removeSubServer(player, getName())) {
waitFor(() -> host.getSubServer(getName()), null);
SubServer server = this.host.plugin.api.getHost(value.asRawString()).addSubServer(player, getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = this.host.plugin.api.getHost(value.asString()).constructSubServer(getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Host", server.getHost().getName());
@ -278,7 +321,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "template":
if (value.isString()) {
Util.reflect(SubServerContainer.class.getDeclaredField("template"), this, value.asString());
setTemplate(value.asString());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Template", value.asString());
this.host.plugin.servers.save();
@ -289,7 +332,7 @@ public class ExternalSubServer extends SubServerContainer {
case "port":
if (value.isNumber() && host.removeSubServer(player, getName())) {
waitFor(() -> host.getSubServer(getName()), null);
SubServer server = host.addSubServer(player, getName(), isEnabled(), value.asInt(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(getName(), isEnabled(), value.asInt(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Port", server.getAddress().getPort());
@ -302,7 +345,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "motd":
if (value.isString()) {
Util.reflect(BungeeServerInfo.class.getDeclaredField("motd"), this, ChatColor.translateAlternateColorCodes('&', value.asString()));
setMotd(ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(value.asString())));
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Motd", value.asString());
this.host.plugin.servers.save();
@ -312,8 +355,8 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "log":
if (value.isBoolean()) {
if (log.get() != value.asBoolean()) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_LOGGING, (Boolean) value.asBoolean()));
log.set(value.asBoolean());
if (log.value() != value.asBoolean()) host.queue(new PacketExControlServer(this, Action.SET_LOGGING, (Boolean) value.asBoolean()));
log.value(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Log", isLogging());
this.host.plugin.servers.save();
@ -325,7 +368,7 @@ public class ExternalSubServer extends SubServerContainer {
case "directory":
if (value.isString() && host.removeSubServer(player, getName())) {
waitFor(() -> host.getSubServer(getName()), null);
SubServer server = host.addSubServer(player, getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), value.asRawString(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), value.asString(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Directory", server.getPath());
@ -340,10 +383,10 @@ public class ExternalSubServer extends SubServerContainer {
case "executable":
if (value.isString() && host.removeSubServer(player, getName())) {
waitFor(() -> host.getSubServer(getName()), null);
SubServer server = host.addSubServer(player, getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), value.asRawString(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), value.asString(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Executable", value.asRawString());
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Executable", value.asString());
this.host.plugin.servers.save();
}
forward = server;
@ -359,8 +402,8 @@ public class ExternalSubServer extends SubServerContainer {
case "stop-cmd":
case "stop-command":
if (value.isString()) {
if (!stopcmd.equals(value)) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_STOP_COMMAND, value.asRawString()));
stopcmd = value.asRawString();
if (!stopcmd.equals(value.asString())) host.queue(new PacketExControlServer(this, Action.SET_STOP_COMMAND, value.asString()));
stopcmd = value.asString();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Stop-Command", getStopCommand());
this.host.plugin.servers.save();
@ -370,7 +413,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "stop-action":
if (value.isString()) {
StopAction action = Util.getDespiteException(() -> StopAction.valueOf(value.asRawString().toUpperCase().replace('-', '_').replace(' ', '_')), null);
StopAction action = Try.all.get(() -> StopAction.valueOf(value.asString().toUpperCase().replace('-', '_').replace(' ', '_')));
if (action != null) {
stopaction = action;
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
@ -407,7 +450,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "restricted":
if (value.isBoolean()) {
Util.reflect(BungeeServerInfo.class.getDeclaredField("restricted"), this, value.asBoolean());
setRestricted(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Restricted", isRestricted());
this.host.plugin.servers.save();
@ -417,7 +460,7 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "hidden":
if (value.isBoolean()) {
Util.reflect(ServerContainer.class.getDeclaredField("hidden"), this, value.asBoolean());
setHidden(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Hidden", isHidden());
this.host.plugin.servers.save();
@ -427,7 +470,10 @@ public class ExternalSubServer extends SubServerContainer {
break;
case "whitelist":
if (value.isList()) {
Util.reflect(ServerContainer.class.getDeclaredField("whitelist"), this, value.asUUIDList());
Util.reflect(ServerImpl.class.getDeclaredField("whitelist"), this, value.asUUIDList());
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.WHITELIST_SET, value.asUUIDList()));
}
c++;
}
break;
@ -436,7 +482,7 @@ public class ExternalSubServer extends SubServerContainer {
forward.setStopAction(getStopAction());
if (!getName().equals(getDisplayName())) forward.setDisplayName(getDisplayName());
List<String> groups = new ArrayList<String>();
Util.reflect(SubServerContainer.class.getDeclaredField("template"), forward, Util.reflect(SubServerContainer.class.getDeclaredField("template"), this));
forward.setTemplate(getTemplate());
groups.addAll(getGroups());
for (String group : groups) {
removeGroup(group);
@ -460,8 +506,8 @@ public class ExternalSubServer extends SubServerContainer {
if (!isRunning() && forward == null && state) start(player);
return c;
} else return -1;
} private <V> void waitFor(ReturnRunnable<V> method, V value) throws InterruptedException {
while (method.run() != value) {
} private <V> void waitFor(Supplier<V> method, V value) throws InterruptedException {
while (method.get() != value) {
Thread.sleep(250);
}
}
@ -475,14 +521,13 @@ public class ExternalSubServer extends SubServerContainer {
@Override
public boolean isRunning() {
return running;
return running || lock;
}
@Override
public void setDisplayName(String value) {
super.setDisplayName(value);
logger.name = getDisplayName();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("display", value), false));
}
@Override
@ -497,23 +542,21 @@ public class ExternalSubServer extends SubServerContainer {
@Override
public void setEnabled(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("enabled", value), false));
if (enabled != value) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_ENABLED, (Boolean) value));
Util.nullpo(value);
if (enabled != value) host.queue(new PacketExControlServer(this, Action.SET_ENABLED, (Boolean) value));
enabled = value;
}
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
@Override
public void setLogging(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("log", value), false));
if (log.get() != value) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_LOGGING, (Boolean) value));
log.set(value);
Util.nullpo(value);
if (log.value() != value) host.queue(new PacketExControlServer(this, Action.SET_LOGGING, (Boolean) value));
log.value(value);
}
@Override
@ -543,9 +586,8 @@ public class ExternalSubServer extends SubServerContainer {
@Override
public void setStopCommand(String value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("stop-cmd", value), false));
if (!stopcmd.equals(value)) host.queue(new PacketExEditServer(this, PacketExEditServer.UpdateType.SET_STOP_COMMAND, value));
Util.nullpo(value);
if (!stopcmd.equals(value)) host.queue(new PacketExControlServer(this, Action.SET_STOP_COMMAND, value));
stopcmd = value;
}
@ -556,8 +598,7 @@ public class ExternalSubServer extends SubServerContainer {
@Override
public void setStopAction(StopAction action) {
if (Util.isNull(action)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("stop-action", action), false));
Util.nullpo(action);
stopaction = action;
}
}

View File

@ -1,23 +1,29 @@
package net.ME1312.SubServers.Bungee.Host;
import com.google.common.collect.Range;
import net.ME1312.Galaxi.Library.ExtraDataHandler;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidHostException;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.ExtraDataHandler;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import com.google.common.collect.Range;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.net.InetAddress;
import java.util.*;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.UUID;
/**
* Host Layout Class
*/
public abstract class Host implements ExtraDataHandler {
private ObjectMap<String> extra = new ObjectMap<String>();
public abstract class Host implements ExtraDataHandler<String> {
private final ObjectMap<String> extra = new ObjectMap<String>();
private final String signature;
private String nick = null;
@ -37,7 +43,7 @@ public abstract class Host implements ExtraDataHandler {
public Host(SubProxy plugin, String name, boolean enabled, Range<Integer> ports, boolean log, InetAddress address, String directory, String gitBash) {
if (name.contains(" ")) throw new InvalidHostException("Host names cannot have spaces: " + name);
if (!ports.hasLowerBound() || !ports.hasUpperBound()) throw new InvalidHostException("Port range is not bound");
if (Util.isNull(plugin, name, enabled, ports, log, address, directory, gitBash)) throw new NullPointerException();
Util.nullpo(plugin, name, enabled, ports, log, address, directory, gitBash);
signature = plugin.api.signAnonymousObject();
SubAPI.getInstance().getInternals().subprotocol.whitelist(address.getHostAddress());
}
@ -108,6 +114,32 @@ public abstract class Host implements ExtraDataHandler {
}
}
/**
* Get players on servers provided by this host
*
* @return Local Player Collection
*/
public Collection<ProxiedPlayer> getPlayers() {
LinkedList<ProxiedPlayer> players = new LinkedList<ProxiedPlayer>();
for (SubServer server : getSubServers().values()) {
players.addAll(server.getPlayers());
}
return players;
}
/**
* Get players on servers provided by this host across all known proxies
*
* @return Remote Player Collection
*/
public Collection<RemotePlayer> getRemotePlayers() {
LinkedList<RemotePlayer> players = new LinkedList<RemotePlayer>();
for (SubServer server : getSubServers().values()) {
players.addAll(server.getRemotePlayers());
}
return players;
}
/**
* Starts the Servers Specified
*
@ -233,9 +265,8 @@ public abstract class Host implements ExtraDataHandler {
public abstract SubServer getSubServer(String name);
/**
* Adds a SubServer
* Constructs a SubServer (but doesn't add it to the server manager)
*
* @param player Player who Added
* @param name Name of Server
* @param enabled Enabled Status
* @param port Port Number
@ -249,7 +280,7 @@ public abstract class Host implements ExtraDataHandler {
* @return The SubServer
* @throws InvalidServerException
*/
public abstract SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException;
public abstract SubServer constructSubServer(String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException;
/**
* Adds a SubServer
@ -271,6 +302,47 @@ public abstract class Host implements ExtraDataHandler {
return addSubServer(null, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
/**
* Adds a SubServer
*
* @param player Player who Added
* @param name Name of Server
* @param enabled Enabled Status
* @param port Port Number
* @param motd Motd of the Server
* @param log Logging Status
* @param directory Directory
* @param executable Executable String
* @param stopcmd Command to Stop the Server
* @param hidden if the server should be hidden from players
* @param restricted Players will need a permission to join if true
* @return The SubServer
* @throws InvalidServerException
*/
public SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
SubServer server = constructSubServer(name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
return (addSubServer(player, server))?server:null;
}
/**
* Adds a SubServer
*
* @param server SubServer to add
* @return Success status
*/
public boolean addSubServer(SubServer server) throws InvalidServerException {
return addSubServer(null, server);
}
/**
* Adds a SubServer
*
* @param player Player who added
* @param server SubServer to add
* @return Success status
*/
public abstract boolean addSubServer(UUID player, SubServer server) throws InvalidServerException;
/**
* Removes a SubServer
*
@ -290,7 +362,20 @@ public abstract class Host implements ExtraDataHandler {
* @throws InterruptedException
* @return Success Status
*/
public abstract boolean removeSubServer(UUID player, String name) throws InterruptedException;
public boolean removeSubServer(UUID player, String name) throws InterruptedException {
return removeSubServer(player, name, false);
}
/**
* Removes a SubServer
*
* @param player Player Removing
* @param name SubServer Name
* @param forced Forces the Removal
* @throws InterruptedException
* @return Success Status
*/
protected abstract boolean removeSubServer(UUID player, String name, boolean forced) throws InterruptedException;
/**
* Forces the Removal of a SubServer
@ -303,16 +388,18 @@ public abstract class Host implements ExtraDataHandler {
}
/**
* Forces the Removal of a SubServer (will move to 'Recently Deleted')
* Forces the Removal of a SubServer
*
* @param player Player Removing
* @param name SubServer Name
* @return Success Status
*/
public abstract boolean forceRemoveSubServer(UUID player, String name) throws InterruptedException;
public boolean forceRemoveSubServer(UUID player, String name) throws InterruptedException {
return removeSubServer(player, name, true);
}
/**
* Delete a SubServer (will move to 'Recently Deleted')
* Deletes a SubServer (will move to 'Recently Deleted')
*
* @param name SubServer Name
* @return Success Status
@ -322,16 +409,28 @@ public abstract class Host implements ExtraDataHandler {
}
/**
* Delete a SubServer
* Deletes a SubServer (will move to 'Recently Deleted')
*
* @param player Player Deleting
* @param name SubServer Name
* @return Success Status
*/
public abstract boolean recycleSubServer(UUID player, String name) throws InterruptedException;
public boolean recycleSubServer(UUID player, String name) throws InterruptedException {
return recycleSubServer(player, name, false);
}
/**
* Forced the Deletion of a SubServer (will move to 'Recently Deleted')
* Deletes a SubServer (will move to 'Recently Deleted')
*
* @param player Player Deleting
* @param name SubServer Name
* @param forced Forces the Deletion
* @return Success Status
*/
protected abstract boolean recycleSubServer(UUID player, String name, boolean forced) throws InterruptedException;
/**
* Forces the Deletion of a SubServer (will move to 'Recently Deleted')
*
* @param name SubServer Name
* @return Success Status
@ -347,10 +446,12 @@ public abstract class Host implements ExtraDataHandler {
* @param name SubServer Name
* @return Success Status
*/
public abstract boolean forceRecycleSubServer(UUID player, String name) throws InterruptedException;
public boolean forceRecycleSubServer(UUID player, String name) throws InterruptedException {
return recycleSubServer(player, name, true);
}
/**
* Delete a SubServer
* Deletes a SubServer
*
* @param name SubServer Name
* @return Success Status
@ -360,16 +461,28 @@ public abstract class Host implements ExtraDataHandler {
}
/**
* Delete a SubServer
* Deletes a SubServer
*
* @param player Player Deleting
* @param name SubServer Name
* @return Success Status
*/
public abstract boolean deleteSubServer(UUID player, String name) throws InterruptedException;
public boolean deleteSubServer(UUID player, String name) throws InterruptedException {
return deleteSubServer(player, name, false);
}
/**
* Forced the Deletion of a SubServer
* Deletes a SubServer
*
* @param player Player Deleting
* @param name SubServer Name
* @param forced Forces the Deletion
* @return Success Status
*/
protected abstract boolean deleteSubServer(UUID player, String name, boolean forced) throws InterruptedException;
/**
* Forces the Deletion of a SubServer
*
* @param name SubServer Name
* @return Success Status
@ -385,22 +498,24 @@ public abstract class Host implements ExtraDataHandler {
* @param name SubServer Name
* @return Success Status
*/
public abstract boolean forceDeleteSubServer(UUID player, String name) throws InterruptedException;
public boolean forceDeleteSubServer(UUID player, String name) throws InterruptedException {
return deleteSubServer(player, name, true);
}
/**
* Resets this Host object
*
* @return Success Status
*/
@SuppressWarnings("unchecked")
public boolean destroy() {
try {
List<String> subservers = new ArrayList<String>();
subservers.addAll(getSubServers().keySet());
Map.Entry<String, SubServer>[] subservers = getSubServers().entrySet().toArray(new Map.Entry[0]);
for (String server : subservers) {
forceRemoveSubServer(server);
for (Map.Entry<String, SubServer> entry : subservers) {
if (entry.getValue().isRunning()) Logger.get("SubServers").info("Stopping " + entry.getValue().getName());
forceRemoveSubServer(entry.getKey());
}
subservers.clear();
getCreator().terminate();
getCreator().waitFor();
return true;
@ -419,21 +534,26 @@ public abstract class Host implements ExtraDataHandler {
return signature;
}
@Override
public boolean equals(Object obj) {
return obj instanceof Host && signature.equals(((Host) obj).signature);
}
@Override
public void addExtra(String handle, Object value) {
if (Util.isNull(handle, value)) throw new NullPointerException();
Util.nullpo(handle, value);
extra.set(handle, value);
}
@Override
public boolean hasExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
return extra.getKeys().contains(handle);
}
@Override
public ObjectMapValue getExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
return extra.get(handle);
}
@ -444,7 +564,7 @@ public abstract class Host implements ExtraDataHandler {
@Override
public void removeExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
extra.remove(handle);
}

View File

@ -1,20 +1,22 @@
package net.ME1312.SubServers.Bungee.Host.Internal;
import com.dosse.upnp.UPnP;
import com.google.common.collect.Range;
import net.ME1312.Galaxi.Library.Config.YAMLSection;
import net.ME1312.Galaxi.Library.Directories;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Event.SubAddServerEvent;
import net.ME1312.SubServers.Bungee.Event.SubRemoveServerEvent;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.Galaxi.Library.UniversalFile;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Bungee.SubProxy;
import com.dosse.upnp.UPnP;
import com.google.common.collect.Range;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileWriter;
import java.net.InetAddress;
@ -31,7 +33,7 @@ public class InternalHost extends Host {
private InetAddress address;
private SubCreator creator;
private String directory;
protected SubProxy plugin;
SubProxy plugin;
/**
* Creates an Internal Host
@ -93,122 +95,81 @@ public class InternalHost extends Host {
@Override
public SubServer getSubServer(String name) {
if (Util.isNull(name)) throw new NullPointerException();
return getSubServers().get(name.toLowerCase());
if (Util.isNull(name)) return null;
return servers.get(name.toLowerCase());
}
@Override
public SubServer addSubServer(UUID player, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
if (plugin.api.getServers().keySet().contains(name.toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
SubServer server = new InternalSubServer(this, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
public SubServer constructSubServer(String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
return InternalSubServer.construct(this, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
@Override
public boolean addSubServer(UUID player, SubServer server) throws InvalidServerException {
if (server.getHost() != this) throw new IllegalArgumentException("That Server does not belong to this Host!");
if (plugin.api.getServers().containsKey(server.getName().toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
SubAddServerEvent event = new SubAddServerEvent(player, this, server);
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
servers.put(name.toLowerCase(), server);
if (UPnP.isUPnPAvailable() && plugin.config.get().getMap("Settings").getMap("UPnP", new ObjectMap<String>()).getBoolean("Forward-Servers", false)) UPnP.openPortTCP(port);
return server;
((InternalSubServer) server).registered(true);
servers.put(server.getName().toLowerCase(), server);
if (UPnP.isUPnPAvailable() && plugin.config.get().getMap("Settings").getMap("UPnP", new ObjectMap<String>()).getBoolean("Forward-Servers", false)) UPnP.openPortTCP(server.getAddress().getPort());
return true;
} else {
return null;
return false;
}
}
@Override
public boolean removeSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
protected boolean removeSubServer(UUID player, String name, boolean forced) throws InterruptedException {
Util.nullpo(name);
InternalSubServer server = (InternalSubServer) servers.get(name.toLowerCase());
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, server);
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
if (forced || !event.isCancelled()) {
server.registered(false);
if (server.isRunning()) {
server.stop();
server.waitFor();
}
if (UPnP.isUPnPAvailable() && UPnP.isMappedTCP(getSubServer(server).getAddress().getPort()))
UPnP.closePortTCP(getSubServer(server).getAddress().getPort());
servers.remove(server.toLowerCase());
servers.remove(name.toLowerCase());
if (UPnP.isUPnPAvailable() && UPnP.isMappedTCP(server.getAddress().getPort()))
UPnP.closePortTCP(server.getAddress().getPort());
return true;
} else return false;
}
@Override
public boolean forceRemoveSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
SubRemoveServerEvent event = new SubRemoveServerEvent(player, this, getSubServer(server));
plugin.getPluginManager().callEvent(event);
if (getSubServer(server).isRunning()) {
getSubServer(server).stop();
getSubServer(server).waitFor();
}
if (UPnP.isUPnPAvailable() && UPnP.isMappedTCP(getSubServer(server).getAddress().getPort()))
UPnP.closePortTCP(getSubServer(server).getAddress().getPort());
servers.remove(server.toLowerCase());
return true;
protected boolean recycleSubServer(UUID player, String name, boolean forced) throws InterruptedException {
return recycleSubServer(player, name, forced, true);
}
@Override
public boolean recycleSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
/**
* Deletes a SubServer (will move to 'Recently Deleted')
*
* @param player Player Deleting
* @param name SubServer Name
* @param forced Forces the Deletion
* @param multithreading Uses Multithreading for I/O
* @return Success Status
*/
protected boolean recycleSubServer(UUID player, String name, boolean forced, boolean multithreading) throws InterruptedException {
Util.nullpo(name);
String server = servers.get(name.toLowerCase()).getName();
File from = new File(getPath(), servers.get(server.toLowerCase()).getPath());
if (removeSubServer(player, server)) {
new Thread(() -> {
UniversalFile to = new UniversalFile(plugin.dir, "SubServers:Recently Deleted:" + server.toLowerCase());
if (removeSubServer(player, server, forced)) {
Runnable method = () -> {
File to = new File(plugin.dir, "SubServers/Recently Deleted/" + server.toLowerCase());
try {
if (from.exists()) {
Logger.get("SubServers").info("Moving Files...");
if (to.exists()) {
if (to.isDirectory()) Util.deleteDirectory(to);
if (to.isDirectory()) Directories.delete(to);
else to.delete();
}
to.mkdirs();
Util.copyDirectory(from, to);
Util.deleteDirectory(from);
}
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Saving...");
YAMLSection info = (plugin.servers.get().getMap("Servers").getKeys().contains(server))?new YAMLSection(plugin.servers.get().getMap("Servers").getMap(server).get()):new YAMLSection();
info.set("Name", server);
info.set("Timestamp", Calendar.getInstance().getTime().getTime());
try {
if (plugin.servers.get().getMap("Servers").getKeys().contains(server)) {
plugin.servers.get().getMap("Servers").remove(server);
plugin.servers.save();
}
if (!to.exists()) to.mkdirs();
FileWriter writer = new FileWriter(new File(to, "info.json"));
writer.write(info.toJSON().toString());
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Deleted SubServer: " + server);
}, "SubServers.Bungee::Internal_Server_Recycler(" + name + ')').start();
return true;
} else return false;
}
@Override
public boolean forceRecycleSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
File from = new File(getPath(), servers.get(server.toLowerCase()).getPath());
if (forceRemoveSubServer(player, server)) {
new Thread(() -> {
UniversalFile to = new UniversalFile(plugin.dir, "SubServers:Recently Deleted:" + server.toLowerCase());
try {
if (from.exists()) {
Logger.get("SubServers").info("Moving Files...");
if (to.exists()) {
if (to.isDirectory()) Util.deleteDirectory(to);
else to.delete();
}
to.mkdirs();
Util.copyDirectory(from, to);
Util.deleteDirectory(from);
Directories.copy(from, to);
Directories.delete(from);
}
} catch (Exception e) {
e.printStackTrace();
@ -225,28 +186,45 @@ public class InternalHost extends Host {
}
if (!to.exists()) to.mkdirs();
FileWriter writer = new FileWriter(new File(to, "info.json"), false);
writer.write(info.toJSON().toString());
writer.write(new Gson().toJson(info.get()));
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Deleted SubServer: " + server);
}, "SubServers.Bungee::Internal_Server_Recycler(" + name + ')').start();
};
if (multithreading) {
new Thread(method, "SubServers.Bungee::Internal_Server_Recycler(" + name + ')').start();
} else method.run();
return true;
} else return false;
}
@Override
public boolean deleteSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
protected boolean deleteSubServer(UUID player, String name, boolean forced) throws InterruptedException {
return deleteSubServer(player, name, forced, true);
}
/**
* Deletes a SubServer
*
* @param player Player Deleting
* @param name SubServer Name
* @param forced Forces the Deletion
* @param multithreading Uses Multithreading for I/O
* @return Success Status
*/
protected boolean deleteSubServer(UUID player, String name, boolean forced, boolean multithreading) throws InterruptedException {
Util.nullpo(name);
String server = servers.get(name.toLowerCase()).getName();
File from = new File(getPath(), servers.get(server.toLowerCase()).getPath());
if (removeSubServer(player, server)) {
new Thread(() -> {
if (removeSubServer(player, server, forced)) {
Runnable method = () -> {
try {
if (from.exists()) {
Logger.get("SubServers").info("Removing Files...");
Util.deleteDirectory(from);
Directories.delete(from);
}
} catch (Exception e) {
e.printStackTrace();
@ -262,38 +240,11 @@ public class InternalHost extends Host {
e.printStackTrace();
}
Logger.get("SubServers").info("Deleted SubServer: " + server);
}, "SubServers.Bungee::Internal_Server_Deletion(" + name + ')').start();
return true;
} else return false;
}
};
@Override
public boolean forceDeleteSubServer(UUID player, String name) throws InterruptedException {
if (Util.isNull(name)) throw new NullPointerException();
String server = servers.get(name.toLowerCase()).getName();
File from = new File(getPath(), servers.get(server.toLowerCase()).getPath());
if (forceRemoveSubServer(player, server)) {
new Thread(() -> {
try {
if (from.exists()) {
Logger.get("SubServers").info("Removing Files...");
Util.deleteDirectory(from);
}
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Saving...");
try {
if (plugin.servers.get().getMap("Servers").getKeys().contains(server)) {
plugin.servers.get().getMap("Servers").remove(server);
plugin.servers.save();
}
} catch (Exception e) {
e.printStackTrace();
}
Logger.get("SubServers").info("Deleted SubServer: " + server);
}, "SubServers.Bungee::Internal_Server_Deletion(" + name + ')').start();
if (multithreading) {
new Thread(method, "SubServers.Bungee::Internal_Server_Deletion(" + name + ')').start();
} else method.run();
return true;
} else return false;
}

View File

@ -1,22 +1,30 @@
package net.ME1312.SubServers.Bungee.Host.Internal;
import com.google.common.collect.Range;
import com.google.gson.Gson;
import net.ME1312.Galaxi.Library.*;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Callback.ReturnCallback;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Config.YAMLSection;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Directories;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Event.SubCreateEvent;
import net.ME1312.SubServers.Bungee.Event.SubCreatedEvent;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Host.SubServer.StopAction;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Bungee.Library.Exception.SubCreatorException;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.ReplacementScanner;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import com.google.common.collect.Range;
import com.google.gson.Gson;
import net.md_5.bungee.api.ChatColor;
import java.io.*;
@ -25,9 +33,16 @@ import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
/**
* Internal SubCreator Class
*/
@ -36,7 +51,7 @@ public class InternalSubCreator extends SubCreator {
private HashMap<String, ServerTemplate> templates = new HashMap<String, ServerTemplate>();
private InternalHost host;
private Range<Integer> ports;
private Container<Boolean> log;
private Value<Boolean> log;
private String gitBash;
private TreeMap<String, CreatorTask> thread;
@ -49,10 +64,13 @@ public class InternalSubCreator extends SubCreator {
private final int port;
private final String prefix;
private final InternalSubLogger log;
private final Callback<SubServer> callback;
private final LinkedList<String> replace;
private final HashMap<String, String> replacements;
private final Consumer<SubServer> callback;
private boolean install;
private Process process;
private CreatorTask(UUID player, String name, ServerTemplate template, Version version, int port, Callback<SubServer> callback) {
private CreatorTask(UUID player, String name, ServerTemplate template, Version version, int port, Consumer<SubServer> callback) {
super("SubServers.Bungee::Internal_SubCreator_Process_Handler(" + name + ')');
this.player = player;
this.update = null;
@ -61,87 +79,106 @@ public class InternalSubCreator extends SubCreator {
this.version = version;
this.port = port;
this.log = new InternalSubLogger(null, this, prefix = name + File.separator + "Creator", InternalSubCreator.this.log, null);
(this.replace = new LinkedList<String>()).add("/server.properties");
this.replacements = new HashMap<String, String>();
this.callback = callback;
this.install = true;
}
private CreatorTask(UUID player, SubServer server, Version version, Callback<SubServer> callback) {
private CreatorTask(UUID player, SubServer server, ServerTemplate template, Version version, Consumer<SubServer> callback) {
super("SubServers.Bungee::Internal_SubCreator_Process_Handler(" + server.getName() + ')');
this.player = player;
this.update = server;
this.name = server.getName();
this.template = server.getTemplate();
this.template = template;
this.version = version;
this.port = server.getAddress().getPort();
this.log = new InternalSubLogger(null, this, prefix = name + File.separator + "Updater", InternalSubCreator.this.log, null);
(this.replace = new LinkedList<String>()).add("/server.properties");
this.replacements = new HashMap<String, String>();
this.callback = callback;
this.install = true;
}
private ObjectMap<String> build(File dir, ServerTemplate template, List<ServerTemplate> history) throws SubCreatorException {
private ObjectMap<String> build(File dir, ServerTemplate template, List<ServerTemplate> history, List<ServerTemplate> stack) throws SubCreatorException {
ObjectMap<String> server = new ObjectMap<String>();
Version version = this.version;
HashMap<String, String> var = new HashMap<String, String>();
boolean error = false;
if (history.contains(template)) throw new IllegalStateException("Template Import loop detected");
history.add(template);
if (stack.contains(template)) throw new IllegalStateException("Infinite template import loop detected");
stack.add(template);
for (String other : template.getBuildOptions().getStringList("Import", new ArrayList<String>())) {
if (templates.keySet().contains(other.toLowerCase())) {
if (templates.get(other.toLowerCase()).isEnabled()) {
if (version != null || !templates.get(other.toLowerCase()).requiresVersion()) {
if (update == null || templates.get(other.toLowerCase()).canUpdate()) {
ObjectMap<String> config = build(dir, templates.get(other.toLowerCase()), history);
if (config == null) {
throw new SubCreatorException();
if (templates.containsKey(other.toLowerCase())) {
final ServerTemplate ot = templates.get(other.toLowerCase());
if (ot.isEnabled()) {
if (version != null || !ot.requiresVersion()) {
if (update == null || ot.canUpdate()) {
if (!history.contains(ot)) {
server.setAll(this.build(dir, ot, history, stack));
} else {
server.setAll(config);
log.log(WARNING, "Skipping template that is already loaded: " + other);
}
} else {
Logger.get(prefix).info("Skipping template that cannot be run in update mode: " + other);
log.log(WARNING, "Skipping template that cannot be run in update mode: " + other);
}
} else {
Logger.get(prefix).info("Skipping template that requires extra versioning: " + other);
log.log(WARNING, "Skipping template that requires extra versioning information: " + other);
}
} else {
Logger.get(prefix).info("Skipping disabled template: " + other);
log.log(WARNING, "Skipping disabled template: " + other);
}
} else {
Logger.get(prefix).info("Skipping missing template: " + other);
log.log(WARNING, "Skipping missing template: " + other);
}
}
history.add(template);
stack.remove(template);
server.setAll(template.getConfigOptions());
try {
Logger.get(prefix).info("Loading Template: " + template.getDisplayName());
Util.copyDirectory(template.getDirectory(), dir);
log.log(INFO, "Loading" + ((template.isDynamic())?" Dynamic":"") + " Template: " + template.getDisplayName());
updateDirectory(template.getDirectory(), dir, template.getBuildOptions().getBoolean("Update-Files", false));
install = template.getBuildOptions().getBoolean("Install-Client", install);
replace.addAll(template.getBuildOptions().getStringList("Replace", Collections.emptyList()));
for (ObjectMapValue<String> replacement : template.getBuildOptions().getMap("Replacements", new ObjectMap<>()).getValues()) if (!replacement.isNull()) {
replacements.put(replacement.getHandle().toLowerCase().replace('-', '_').replace(' ', '_'), replacement.asString());
}
var.putAll(replacements);
var.put("java", System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
var.put("mode", (update == null)?"CREATE":"UPDATE");
var.put("mode", (update == null)? "CREATE" : ((CreatorTask.this.template.equals(update.getTemplate()))?"UPDATE":"SWITCH"));
if (player != null) var.put("player", player.toString().toUpperCase());
else var.remove("player");
var.put("name", name);
var.put("host", host.getName());
var.put("template", template.getName());
var.put("type", template.getType().toString().toUpperCase());
if (version != null) var.put("version", version.toString());
else var.remove("version");
var.put("address", host.getAddress().getHostAddress());
var.put("port", Integer.toString(port));
switch (template.getType()) {
case SPONGE:
case FORGE:
if (version != null) {
Logger.get(prefix).info("Searching Versions...");
log.log(INFO, "Searching Versions...");
ObjectMap<String> spversionmanifest = new ObjectMap<String>(new Gson().fromJson("{\"versions\":" + Util.readAll(new BufferedReader(new InputStreamReader(new URL("https://dl-api.spongepowered.org/v1/org.spongepowered/sponge" + ((template.getType() == ServerType.FORGE)?"forge":"vanilla") + "/downloads?type=stable&minecraft=" + version).openStream(), Charset.forName("UTF-8")))) + '}', Map.class));
ObjectMap<String> spprofile = null;
Version spversion = null;
for (ObjectMap<String> profile : spversionmanifest.getMapList("versions")) {
if (profile.getMap("dependencies").getRawString("minecraft").equalsIgnoreCase(version.toString()) && (spversion == null || new Version(profile.getRawString("version")).compareTo(spversion) >= 0)) {
if (profile.getMap("dependencies").getString("minecraft").equalsIgnoreCase(version.toString()) && (spversion == null || new Version(profile.getString("version")).compareTo(spversion) >= 0)) {
spprofile = profile;
spversion = new Version(profile.getRawString("version"));
spversion = new Version(profile.getString("version"));
}
}
if (spversion == null)
throw new InvalidServerException("Cannot find Sponge version for Minecraft " + version.toString());
Logger.get(prefix).info("Found \"sponge" + ((template.getType() == ServerType.FORGE)?"forge":"vanilla") + "-" + spversion.toString() + '"');
log.log(INFO, "Found \"sponge" + ((template.getType() == ServerType.FORGE)?"forge":"vanilla") + "-" + spversion.toString() + '"');
if (template.getType() == ServerType.FORGE) {
Version mcfversion = new Version(((spprofile.getMap("dependencies").getRawString("forge").contains("-"))?"":spprofile.getMap("dependencies").getRawString("minecraft") + '-') + spprofile.getMap("dependencies").getRawString("forge"));
Logger.get(prefix).info("Found \"forge-" + mcfversion.toString() + '"');
Version mcfversion = new Version(((spprofile.getMap("dependencies").getString("forge").contains("-"))?"":spprofile.getMap("dependencies").getString("minecraft") + '-') + spprofile.getMap("dependencies").getString("forge"));
log.log(INFO, "Found \"forge-" + mcfversion.toString() + '"');
var.put("mcf_version", mcfversion.toString());
}
@ -154,29 +191,25 @@ public class InternalSubCreator extends SubCreator {
}
if (template.getBuildOptions().contains("Executable")) {
File cache;
File cache = null;
if (template.getBuildOptions().getBoolean("Use-Cache", true)) {
cache = new UniversalFile(host.plugin.dir, "SubServers:Cache:Templates:" + template.getName());
cache = new File(host.plugin.dir, "SubServers/Cache/Templates/" + template.getName());
cache.mkdirs();
String c = cache.toString();
if (System.getProperty("os.name").toLowerCase().startsWith("windows") &&
(template.getBuildOptions().getRawString("Executable").toLowerCase().startsWith("bash ") || template.getBuildOptions().getRawString("Executable").toLowerCase().startsWith("sh "))) c = c.replace(File.separatorChar, '/');
var.put("cache", c);
} else {
cache = null;
var.put("cache", cache.getAbsolutePath());
}
var.put("source", dir.getAbsolutePath());
try {
Logger.get(prefix).info("Launching Build Script...");
ProcessBuilder pb = new ProcessBuilder().command(Executable.parse(gitBash, template.getBuildOptions().getRawString("Executable"))).directory(dir);
log.log(INFO, "Launching Build Script...");
ProcessBuilder pb = new ProcessBuilder().command(Executable.parse(gitBash, template.getBuildOptions().getString("Executable"))).directory(dir);
pb.environment().putAll(var);
process = pb.start();
log.file = new File(dir, "SubCreator-" + template.getName() + ((version != null)?"-"+version.toString():"") + ".log");
process = pb.start();
log.process = process;
log.start();
process.waitFor();
Thread.sleep(500);
Thread.sleep(250);
if (process.exitValue() != 0) error = true;
} catch (InterruptedException e) {
@ -188,119 +221,132 @@ public class InternalSubCreator extends SubCreator {
if (cache != null) {
if (cache.isDirectory() && cache.listFiles().length == 0) cache.delete();
cache = new UniversalFile(host.plugin.dir, "SubServers:Cache:Templates");
cache = new File(host.plugin.dir, "SubServers/Cache/Templates");
if (cache.isDirectory() && cache.listFiles().length == 0) cache.delete();
cache = new UniversalFile(host.plugin.dir, "SubServers:Cache");
cache = new File(host.plugin.dir, "SubServers/Cache");
if (cache.isDirectory() && cache.listFiles().length == 0) cache.delete();
}
}
new UniversalFile(dir, "template.yml").delete();
new File(dir, "template.yml").delete();
if (error) throw new SubCreatorException();
return server;
}
public void run() {
ReturnCallback<Object, Object> conversion = obj -> convert(obj, new NamedContainer<>("$player$", (player == null)?"":player.toString()), new NamedContainer<>("$name$", name),
new NamedContainer<>("$template$", template.getName()), new NamedContainer<>("$type$", template.getType().toString()), new NamedContainer<>("$version$", (version != null)?version.toString().replace(" ", "@"):""),
new NamedContainer<>("$address$", host.getAddress().getHostAddress()), new NamedContainer<>("$port$", Integer.toString(port)));
Runnable declaration = () -> {
replacements.put("player", (player == null)?"":player.toString());
replacements.put("name", name);
replacements.put("host", host.getName());
replacements.put("template", template.getName());
replacements.put("type", template.getType().toString());
replacements.put("version", (version != null)?version.toString():"");
replacements.put("address", host.getAddress().getHostAddress());
replacements.put("port", Integer.toString(port));
};
declaration.run();
File dir = (update != null)?new File(update.getFullPath()):new File(host.getPath(),
(template.getConfigOptions().contains("Directory"))?conversion.run(template.getConfigOptions().getRawString("Directory")).toString():name);
dir.mkdirs();
(template.getConfigOptions().contains("Directory"))?new ReplacementScanner(replacements).replace(template.getConfigOptions().getString("Directory")).toString():name);
ObjectMap<String> server = new ObjectMap<String>();
ObjectMap<String> config;
try {
config = build(dir, template, new LinkedList<>());
generateProperties(dir, port);
generateClient(dir, template.getType(), name);
log.init();
config = build(dir, template, new LinkedList<>(), new LinkedList<>());
} catch (SubCreatorException e) {
config = null;
} catch (Exception e) {
config = null;
e.printStackTrace();
} finally {
log.destroy();
}
declaration.run();
ReplacementScanner replacements = new ReplacementScanner(this.replacements);
if (config != null) {
try {
if (install) generateClient(dir, template.getType(), name);
replacements.replace(dir, replace.toArray(new String[0]));
} catch (Exception e) {
config = null;
e.printStackTrace();
}
}
if (config != null) {
try {
Logger.get(prefix).info("Saving...");
SubServer subserver = update;
if (update == null) {
if (host.plugin.exServers.keySet().contains(name.toLowerCase()))
if (update == null || update.getTemplate() != template || template.getBuildOptions().getBoolean("Update-Settings", false)) {
if (host.plugin.exServers.containsKey(name.toLowerCase()))
host.plugin.exServers.remove(name.toLowerCase());
config = new ObjectMap<String>((Map<String, ?>) conversion.run(config.get()));
config = new ObjectMap<String>((Map<String, ?>) replacements.replace(config.get()));
if (config.contains("Directory") && (update != null || !template.getConfigOptions().contains("Directory"))) config.remove("Directory");
server.set("Enabled", true);
server.set("Display", "");
server.set("Host", host.getName());
server.set("Template", template.getName());
server.set("Group", new ArrayList<String>());
server.set("Port", port);
server.set("Motd", "Some SubServer");
server.set("Log", true);
server.set("Directory", "./" + name);
server.set("Executable", "java -Xmx1024M -jar " + template.getType().toString() + ".jar");
server.set("Stop-Command", "stop");
server.set("Stop-Action", "NONE");
server.set("Run-On-Launch", false);
server.set("Restricted", false);
server.set("Incompatible", new ArrayList<String>());
server.set("Hidden", false);
if (update == null) {
server.set("Enabled", true);
server.set("Display", "");
server.set("Host", host.getName());
server.set("Template", template.getName());
server.set("Group", new ArrayList<String>());
server.set("Port", port);
server.set("Motd", "Some SubServer");
server.set("Log", true);
server.set("Directory", "./" + name);
server.set("Executable", "java -Xmx1024M -jar " + template.getType().toString() + ".jar");
server.set("Stop-Command", "stop");
server.set("Stop-Action", "NONE");
server.set("Run-On-Launch", false);
server.set("Restricted", false);
server.set("Incompatible", new ArrayList<String>());
server.set("Hidden", false);
} else {
server.setAll(host.plugin.servers.get().getMap("Servers").getMap(name, new HashMap<>()));
server.set("Template", template.getName());
}
server.setAll(config);
subserver = host.addSubServer(player, name, server.getBoolean("Enabled"), port, ChatColor.translateAlternateColorCodes('&', server.getString("Motd")), server.getBoolean("Log"), server.getRawString("Directory"),
server.getRawString("Executable"), server.getRawString("Stop-Command"), server.getBoolean("Hidden"), server.getBoolean("Restricted"));
if (server.getString("Display").length() > 0) subserver.setDisplayName(server.getString("Display"));
subserver.setTemplate(getTemplate(server.getRawString("Template")));
if (update != null) Try.all.run(() -> update.getHost().forceRemoveSubServer(name));
subserver = host.constructSubServer(name, server.getBoolean("Enabled"), port, ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(server.getString("Motd"))), server.getBoolean("Log"),
server.getString("Directory"), server.getString("Executable"), server.getString("Stop-Command"), server.getBoolean("Hidden"), server.getBoolean("Restricted"));
if (server.getString("Display").length() > 0) subserver.setDisplayName(Util.unescapeJavaString(server.getString("Display")));
subserver.setTemplate(server.getString("Template"));
for (String group : server.getStringList("Group")) subserver.addGroup(group);
SubServer.StopAction action = Util.getDespiteException(() -> SubServer.StopAction.valueOf(server.getRawString("Stop-Action").toUpperCase().replace('-', '_').replace(' ', '_')), null);
SubServer.StopAction action = Try.all.get(() -> SubServer.StopAction.valueOf(server.getString("Stop-Action").toUpperCase().replace('-', '_').replace(' ', '_')));
if (action != null) subserver.setStopAction(action);
if (server.contains("Extra")) for (String extra : server.getMap("Extra").getKeys())
subserver.addExtra(extra, server.getMap("Extra").getObject(extra));
host.plugin.servers.get().getMap("Servers").set(name, server);
host.plugin.servers.save();
if (template.getBuildOptions().getBoolean("Run-On-Finish", true))
if ((update != null && host.plugin.servers.get().getMap("Servers").contains(name)) ||
!(subserver.getStopAction() == StopAction.REMOVE_SERVER || subserver.getStopAction() == StopAction.RECYCLE_SERVER || subserver.getStopAction() == StopAction.DELETE_SERVER)) {
host.plugin.servers.get().getMap("Servers").set(name, server);
host.plugin.servers.save();
}
host.addSubServer(subserver);
if (update == null && template.getBuildOptions().getBoolean("Run-On-Finish", true))
subserver.start();
}
InternalSubCreator.this.thread.remove(name.toLowerCase());
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, port, subserver, update != null, true));
callback.run(subserver);
callback.accept(subserver);
} catch (Exception e) {
e.printStackTrace();
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, port, update, update != null, false));
callback.run(null);
callback.accept(null);
}
} else {
Logger.get(prefix).info("Couldn't build the server jar. Check the SubCreator logs for more detail.");
host.plugin.getPluginManager().callEvent(new SubCreatedEvent(player, host, name, template, version, port, update, update != null, false));
callback.run(null);
callback.accept(null);
}
InternalSubCreator.this.thread.remove(name.toLowerCase());
} private Object convert(Object value, NamedContainer<String, String>... replacements) {
if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key), replacements));
return value;
} else if (value instanceof Collection) {
List<Object> list = new ArrayList<Object>();
for (Object val : (Collection<Object>) value) list.add(convert(val, replacements));
return list;
} else if (value.getClass().isArray()) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < ((Object[]) value).length; i++) list.add(convert(((Object[]) value)[i], replacements));
return list;
} else if (value instanceof String) {
return replace((String) value, replacements);
} else {
return value;
}
} private String replace(String string, NamedContainer<String, String>... replacements) {
for (NamedContainer<String, String> replacement : replacements) string = string.replace(replacement.name(), replacement.get());
return string;
}
}
@ -314,7 +360,7 @@ public class InternalSubCreator extends SubCreator {
*/
public InternalSubCreator(InternalHost host, Range<Integer> ports, boolean log, String gitBash) {
if (!ports.hasLowerBound() || !ports.hasUpperBound()) throw new IllegalArgumentException("Port range is not bound");
if (Util.isNull(host, ports, log, gitBash)) throw new NullPointerException();
Util.nullpo(host, ports, log, gitBash);
this.host = host;
this.ports = ports;
this.log = new Container<Boolean>(log);
@ -327,17 +373,17 @@ public class InternalSubCreator extends SubCreator {
@Override
public void reload() {
templates.clear();
if (new UniversalFile(host.plugin.dir, "SubServers:Templates").exists())
for (File file : new UniversalFile(host.plugin.dir, "SubServers:Templates").listFiles()) {
if (new File(host.plugin.dir, "SubServers/Templates").exists())
for (File file : new File(host.plugin.dir, "SubServers/Templates").listFiles()) {
try {
if (file.isDirectory() && !file.getName().endsWith(".x")) {
ObjectMap<String> config = (new UniversalFile(file, "template.yml").exists()) ? new YAMLConfig(new UniversalFile(file, "template.yml")).get().getMap("Template", new ObjectMap<String>()) : new ObjectMap<String>();
ServerTemplate template = new ServerTemplate(file.getName(), config.getBoolean("Enabled", true), config.getRawString("Icon", "::NULL::"), file, config.getMap("Build", new ObjectMap<String>()), config.getMap("Settings", new ObjectMap<String>()));
ObjectMap<String> config = (new File(file, "template.yml").exists())? new YAMLConfig(new File(file, "template.yml")).get().getMap("Template", new ObjectMap<String>()) : new ObjectMap<String>();
ServerTemplate template = loadTemplate(file.getName(), config.getBoolean("Enabled", true), config.getBoolean("Internal", false), config.getString("Icon", "::NULL::"), file, config.getMap("Build", new ObjectMap<String>()), config.getMap("Settings", new ObjectMap<String>()));
templates.put(file.getName().toLowerCase(), template);
if (config.getKeys().contains("Display")) template.setDisplayName(config.getString("Display"));
if (config.getKeys().contains("Display")) template.setDisplayName(Util.unescapeJavaString(config.getString("Display")));
}
} catch (Exception e) {
Logger.get(host.getName() + File.separator + "Creator").info("Couldn't load template: " + file.getName());
Logger.get(host.getName()).severe("Couldn't load template: " + file.getName());
e.printStackTrace();
}
}
@ -345,25 +391,25 @@ public class InternalSubCreator extends SubCreator {
@SuppressWarnings("deprecation")
@Override
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Callback<SubServer> callback) {
if (Util.isNull(name, template)) throw new NullPointerException();
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().keySet().contains(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Exception().getStackTrace();
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback) {
Util.nullpo(name, template);
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().containsKey(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
if (port == null) {
Container<Integer> i = new Container<Integer>(ports.lowerEndpoint() - 1);
Value<Integer> i = new Container<Integer>(ports.lowerEndpoint() - 1);
port = Util.getNew(getAllReservedAddresses(), () -> {
do {
i.set(i.get() + 1);
if (i.get() > ports.upperEndpoint()) throw new IllegalStateException("There are no more ports available in range: " + ports.toString());
} while (!ports.contains(i.get()));
return new InetSocketAddress(host.getAddress(), i.get());
i.value(i.value() + 1);
if (i.value() > ports.upperEndpoint()) throw new IllegalStateException("There are no more ports available in range: " + ports.toString());
} while (!ports.contains(i.value()));
return new InetSocketAddress(host.getAddress(), i.value());
}).getPort();
}
CreatorTask task = new CreatorTask(player, name, template, version, port, server -> {
if (callback != null) try {
callback.run(server);
callback.accept(server);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
@ -386,17 +432,17 @@ public class InternalSubCreator extends SubCreator {
@SuppressWarnings("deprecation")
@Override
public boolean update(UUID player, SubServer server, Version version, Callback<Boolean> callback) {
if (Util.isNull(server)) throw new NullPointerException();
if (host.isAvailable() && host.isEnabled() && host == server.getHost() && server.isAvailable() && !server.isRunning() && server.getTemplate() != null && server.getTemplate().isEnabled() && server.getTemplate().canUpdate() && (version != null || !server.getTemplate().requiresVersion())) {
StackTraceElement[] origin = new Exception().getStackTrace();
public boolean update(UUID player, SubServer server, ServerTemplate template, Version version, Consumer<Boolean> callback) {
Util.nullpo(server);
final ServerTemplate ft = (template == null)?server.getTemplate():template;
if (host.isAvailable() && host.isEnabled() && host == server.getHost() && server.isAvailable() && !server.isRunning() && ft != null && ft.isEnabled() && ft.canUpdate() && (version != null || !ft.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
Util.isException(() -> Util.reflect(SubServerContainer.class.getDeclaredField("updating"), server, true));
CreatorTask task = new CreatorTask(player, server, version, x -> {
Util.isException(() -> Util.reflect(SubServerContainer.class.getDeclaredField("updating"), server, false));
((InternalSubServer) server).updating(true);
CreatorTask task = new CreatorTask(player, server, ft, version, x -> {
((InternalSubServer) server).updating(false);
if (callback != null) try {
callback.run(x != null);
callback.accept(x != null);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
@ -405,7 +451,7 @@ public class InternalSubCreator extends SubCreator {
});
this.thread.put(server.getName().toLowerCase(), task);
final SubCreateEvent event = new SubCreateEvent(player, server, version);
final SubCreateEvent event = new SubCreateEvent(player, server, ft, version);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
task.start();
@ -428,7 +474,7 @@ public class InternalSubCreator extends SubCreator {
@Override
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
if (this.thread.containsKey(name.toLowerCase())) {
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive()) {
Executable.terminate(this.thread.get(name.toLowerCase()).process);
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
@ -449,7 +495,7 @@ public class InternalSubCreator extends SubCreator {
@Override
public void waitFor(String name) throws InterruptedException {
while (this.thread.keySet().contains(name.toLowerCase()) && this.thread.get(name.toLowerCase()).isAlive()) {
while (this.thread.containsKey(name.toLowerCase()) && this.thread.get(name.toLowerCase()).isAlive()) {
Thread.sleep(250);
}
}
@ -493,13 +539,13 @@ public class InternalSubCreator extends SubCreator {
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
@Override
public void setLogging(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
log.set(value);
Util.nullpo(value);
log.value(value);
}
@Override
@ -516,49 +562,100 @@ public class InternalSubCreator extends SubCreator {
@Override
public Map<String, ServerTemplate> getTemplates() {
return new TreeMap<String, ServerTemplate>(templates);
TreeMap<String, ServerTemplate> map = new TreeMap<String, ServerTemplate>();
for (Map.Entry<String, ServerTemplate> template : templates.entrySet()) {
if (!template.getValue().isInternal()) map.put(template.getKey(), template.getValue());
}
return map;
}
@Override
public ServerTemplate getTemplate(String name) {
if (Util.isNull(name)) throw new NullPointerException();
return getTemplates().get(name.toLowerCase());
Util.nullpo(name);
ServerTemplate template = templates.getOrDefault(name.toLowerCase(), null);
if (template == null || template.isInternal()) {
return null;
} else {
return template;
}
}
private static Pair<YAMLSection, Map<String, Object>> subdata = null;
private Map<String, Object> getSubData() {
if (subdata == null || host.plugin.config.get() != subdata.key()) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("Address", host.plugin.config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1").replace("0.0.0.0", "127.0.0.1"));
if (host.plugin.config.get().getMap("Settings").getMap("SubData").getString("Password", "").length() > 0) map.put("Password", host.plugin.config.get().getMap("Settings").getMap("SubData").getString("Password"));
subdata = new ContainedPair<>(host.plugin.config.get(), map);
}
return subdata.value();
}
private void generateClient(File dir, ServerType type, String name) throws IOException {
if (new UniversalFile(dir, "subservers.client").exists()) {
Files.delete(new UniversalFile(dir, "subservers.client").toPath());
if (type == ServerType.SPIGOT) {
if (!new UniversalFile(dir, "plugins").exists()) new UniversalFile(dir, "plugins").mkdirs();
if (!new UniversalFile(dir, "plugins:SubServers.Client.jar").exists())
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new UniversalFile(dir, "plugins:SubServers.Client.jar").getPath());
} else if (type == ServerType.FORGE || type == ServerType.SPONGE) {
if (!new UniversalFile(dir, "mods").exists()) new UniversalFile(dir, "mods").mkdirs();
if (!new UniversalFile(dir, "mods:SubServers.Client.jar").exists())
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new UniversalFile(dir, "mods:SubServers.Client.jar").getPath());
}
boolean installed = false;
if (type == ServerType.SPIGOT) {
installed = true;
if (!new File(dir, "plugins").exists()) new File(dir, "plugins").mkdirs();
if (!new File(dir, "plugins/SubServers.Client.jar").exists())
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new File(dir, "plugins/SubServers.Client.jar").getPath());
} else if (type == ServerType.FORGE || type == ServerType.SPONGE) {
installed = true;
if (!new File(dir, "mods").exists()) new File(dir, "mods").mkdirs();
if (!new File(dir, "mods/SubServers.Client.jar").exists())
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new File(dir, "mods/SubServers.Client.jar").getPath());
}
if (installed) {
YAMLSection config = new YAMLSection();
FileWriter writer = new FileWriter(new UniversalFile(dir, "subdata.json"), false);
config.set("Name", name);
config.set("Address", host.plugin.config.get().getMap("Settings").getMap("SubData").getRawString("Address", "127.0.0.1").replace("0.0.0.0", "127.0.0.1"));
if (host.plugin.config.get().getMap("Settings").getMap("SubData").getRawString("Password", "").length() > 0) config.set("Password", host.plugin.config.get().getMap("Settings").getMap("SubData").getRawString("Password"));
writer.write(config.toJSON().toString());
FileWriter writer = new FileWriter(new File(dir, "subdata.json"), false);
config.setAll(getSubData());
writer.write(new Gson().toJson(config.get()));
writer.close();
if (!new UniversalFile(dir, "subdata.rsa.key").exists() && new UniversalFile("SubServers:subdata.rsa.key").exists()) {
Files.copy(new UniversalFile("SubServers:subdata.rsa.key").toPath(), new UniversalFile(dir, "subdata.rsa.key").toPath());
if (!new File(dir, "subdata.rsa.key").exists() && new File("SubServers/subdata.rsa.key").exists()) {
Files.copy(new File("SubServers/subdata.rsa.key").toPath(), new File(dir, "subdata.rsa.key").toPath());
}
}
}
private void generateProperties(File dir, int port) throws IOException {
File file = new File(dir, "server.properties");
if (!file.exists()) file.createNewFile();
InputStream stream = new FileInputStream(file);
String content = Util.readAll(new BufferedReader(new InputStreamReader(stream))).replaceAll("server-port=.*(\r?\n)", "server-port=" + port + "$1").replaceAll("server-ip=.*(\r?\n)", "server-ip=" + host.getAddress().getHostAddress() + "$1");
stream.close();
file.delete();
PrintWriter writer = new PrintWriter(file, "UTF-8");
writer.write(content);
writer.close();
private void updateDirectory(File from, File to, boolean overwrite) {
if (!to.exists()) {
Directories.copy(from, to);
} else if (from.isDirectory() && !Files.isSymbolicLink(from.toPath())) {
String files[] = from.list();
for (String file : files) {
File srcFile = new File(from, file);
File destFile = new File(to, file);
updateDirectory(srcFile, destFile, overwrite);
}
} else {
try {
if (overwrite && (from.length() != to.length() || !Arrays.equals(generateSHA256(to), generateSHA256(from)))) {
if (to.exists()) {
if (to.isDirectory()) Directories.delete(to);
else to.delete();
}
Files.copy(from.toPath(), to.toPath(), LinkOption.NOFOLLOW_LINKS, StandardCopyOption.REPLACE_EXISTING);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} private byte[] generateSHA256(File file) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(file);
byte[] dataBytes = new byte[4096];
int nread;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
fis.close();
return md.digest();
}
}

View File

@ -1,12 +1,12 @@
package net.ME1312.SubServers.Bungee.Host.Internal;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.SubLogFilter;
import net.ME1312.SubServers.Bungee.Host.SubLogger;
import net.ME1312.Galaxi.Library.Container;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.ProxyServer;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
@ -21,12 +21,12 @@ import java.util.regex.Pattern;
* Internal Process Logger Class
*/
public class InternalSubLogger extends SubLogger {
protected Process process;
Process process;
private Object handle;
protected String name;
protected Container<Boolean> log;
String name;
Value<Boolean> log;
private List<SubLogFilter> filters = new CopyOnWriteArrayList<>();
protected File file;
File file;
private PrintWriter writer = null;
private boolean started = false;
private Thread out = null;
@ -41,7 +41,7 @@ public class InternalSubLogger extends SubLogger {
* @param log Console Logging Status
* @param file File to log to (or null for disabled)
*/
protected InternalSubLogger(Process process, Object user, String name, Container<Boolean> log, File file) {
InternalSubLogger(Process process, Object user, String name, Value<Boolean> log, File file) {
this.process = process;
this.handle = user;
this.name = name;
@ -49,6 +49,16 @@ public class InternalSubLogger extends SubLogger {
this.file = file;
}
void init() {
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters) try {
filter.start();
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
}
@Override
public void start() {
started = true;
@ -63,13 +73,6 @@ public class InternalSubLogger extends SubLogger {
}
if (out == null) (out = new Thread(() -> start(process.getInputStream(), false), "SubServers.Bungee::Internal_Log_Spooler(" + name + ')')).start();
if (err == null) (err = new Thread(() -> start(process.getErrorStream(), true), "SubServers.Bungee::Internal_Error_Spooler(" + name + ')')).start();
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters) try {
filter.start();
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
}
@SuppressWarnings("deprecation")
@ -91,48 +94,46 @@ public class InternalSubLogger extends SubLogger {
}
}
private Level level = Level.INFO;
private static final String PATTERN = "^((?:\\s*\\[?([0-9]{2}:[0-9]{2}:[0-9]{2})]?)?[\\s\\/\\\\\\|]*(?:\\[|\\[.*\\/)?(DEBUG|MESSAGE|MSG|" + Pattern.quote(Level.INFO.getLocalizedName()) + "|INFO|" + Pattern.quote(Level.WARNING.getLocalizedName()) + "|WARNING|WARN|ERROR|ERR|" + Pattern.quote(Level.SEVERE.getLocalizedName()) + "|SEVERE)\\]?(?::|\\s*>)?\\s*)";
private void log(String line) {
if (!line.startsWith(">")) {
String msg = line;
Level level;
// REGEX Formatting
String type = "";
Matcher matcher = Pattern.compile("^((?:\\s*\\[?([0-9]{2}:[0-9]{2}:[0-9]{2})]?)?[\\s\\/\\\\\\|]*(?:\\[|\\[.*\\/)?(MESSAGE|INFO|WARNING|WARN|ERROR|ERR|SEVERE)\\]?:?(?:\\s*>)?\\s*)").matcher(msg.replaceAll("\u001B\\[[;\\d]*m", ""));
while (matcher.find()) {
String type = null;
Matcher matcher = Pattern.compile(PATTERN).matcher(msg.replaceAll("\u001B\\[[;\\d]*m", ""));
if (matcher.find()) {
type = matcher.group(3).toUpperCase();
}
msg = msg.replaceAll("^((?:\\s*\\[?([0-9]{2}:[0-9]{2}:[0-9]{2})]?)?[\\s\\/\\\\\\|]*(?:\\[|\\[.*\\/)?(MESSAGE|INFO|WARNING|WARN|ERROR|ERR|SEVERE)\\]?:?(?:\\s*>)?\\s*)", "");
msg = msg.replaceAll(PATTERN, "");
// Determine LOG LEVEL
switch (type) {
case "WARNING":
case "WARN":
level = Level.WARNING;
break;
case "SEVERE":
case "ERROR":
case "ERR":
level = Level.SEVERE;
break;
default:
if (type != null) {
if (type.equalsIgnoreCase(Level.INFO.getLocalizedName())) {
level = Level.INFO;
} else if (type.equalsIgnoreCase(Level.WARNING.getLocalizedName())) {
level = Level.WARNING;
} else if (type.equalsIgnoreCase(Level.SEVERE.getLocalizedName())) {
level = Level.SEVERE;
} else switch (type) {
case "WARNING":
case "WARN":
level = Level.WARNING;
break;
case "SEVERE":
case "ERROR":
case "ERR":
level = Level.SEVERE;
break;
default:
level = Level.INFO;
}
}
// Filter Message
boolean allow = (SubAPI.getInstance().getInternals().sudo == getHandler() && SubAPI.getInstance().getInternals().canSudo) || (log.get() && (SubAPI.getInstance().getInternals().sudo == null || !SubAPI.getInstance().getInternals().canSudo));
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters)
try {
allow = (filter.log(level, msg) && allow);
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
// Log to CONSOLE
if (allow) Logger.get(name).log(level, msg);
// Log to FILTER
log(level, msg);
// Log to FILE
if (writer != null) {
@ -142,49 +143,68 @@ public class InternalSubLogger extends SubLogger {
}
}
void log(Level level, String message) {
// Filter Message
boolean allow = (SubAPI.getInstance().getInternals().sudo == getHandler() && SubAPI.getInstance().getInternals().canSudo) || (log.value() && (SubAPI.getInstance().getInternals().sudo == null || !SubAPI.getInstance().getInternals().canSudo));
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters) {
try {
allow = (filter.log(level, message) && allow);
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
}
// Log to CONSOLE
if (allow || !started) {
Logger.get(name).log(level, message);
}
}
@Override
public void stop() {
try {
if (out != null) out.interrupt();
if (err != null) err.interrupt();
destroy();
level = Level.INFO;
if (started) {
started = false;
if (writer != null) {
PrintWriter writer = this.writer;
this.writer = null;
int l = (("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2;
String s = "";
while (s.length() < l) s += '-';
if (writer != null) {
writer.println(s + " LOG END " + s);
writer.close();
}
}
}
} catch (NullPointerException e) {}
}
void destroy() {
filters.addAll(this.filters);
for (SubLogFilter filter : filters) try {
filter.stop();
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
}
@Override
public void registerFilter(SubLogFilter filter) {
if (Util.isNull(filter)) throw new NullPointerException();
Util.nullpo(filter);
filters.add(filter);
}
@Override
public void unregisterFilter(SubLogFilter filter) {
if (Util.isNull(filter)) throw new NullPointerException();
Util.isException(() -> filters.remove(filter));
}
private void destroy() {
if (started) {
started = false;
List<SubLogFilter> filters = new ArrayList<SubLogFilter>();
filters.addAll(this.filters);
for (SubLogFilter filter : filters) try {
filter.stop();
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running SubLogger Event").printStackTrace();
}
if (writer != null) {
PrintWriter writer = this.writer;
this.writer = null;
int l = (int) Math.floor((("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2);
String s = "";
while (s.length() < l) s += '-';
if (writer != null) {
writer.println(s + " LOG END " + s);
writer.close();
}
}
}
Util.nullpo(filter);
Try.all.run(() -> filters.remove(filter));
}
@Override
@ -199,6 +219,6 @@ public class InternalSubLogger extends SubLogger {
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
}

View File

@ -1,22 +1,29 @@
package net.ME1312.SubServers.Bungee.Host.Internal;
import net.ME1312.SubServers.Bungee.Event.*;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Container;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.Galaxi.Library.UniversalFile;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.*;
import net.ME1312.SubServers.Bungee.Host.*;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer.Edit;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.api.ChatColor;
import java.io.*;
import java.lang.reflect.Field;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@ -27,10 +34,10 @@ import java.util.jar.JarInputStream;
/**
* Internal SubServer Class
*/
public class InternalSubServer extends SubServerContainer {
public class InternalSubServer extends SubServerImpl {
private InternalHost host;
private boolean enabled;
private Container<Boolean> log;
private Value<Boolean> log;
private String dir;
private File directory;
private String executable;
@ -60,9 +67,34 @@ public class InternalSubServer extends SubServerContainer {
* @param restricted Restricted Status
* @throws InvalidServerException
*/
public InternalSubServer(InternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
public static InternalSubServer construct(InternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
try {
return new InternalSubServer(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
} catch (NoSuchMethodError e) {
return new InternalSubServer(host, name, enabled, (Integer) port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
}
/**
* Super Method 2 (newest)
* @see #construct(InternalHost, String, boolean, int, String, boolean, String, String, String, boolean, boolean) for method details
*/
protected InternalSubServer(InternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
if (Util.isNull(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted)) throw new NullPointerException();
init(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
/**
* Super Method 1 (oldest)
* @see #construct(InternalHost, String, boolean, int, String, boolean, String, String, String, boolean, boolean) for method details
*/
protected InternalSubServer(InternalHost host, String name, boolean enabled, Integer port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
init(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
}
private void init(InternalHost host, String name, boolean enabled, int port, String motd, boolean log, String directory, String executable, String stopcmd, boolean hidden, boolean restricted) throws InvalidServerException {
Util.nullpo(host, name, enabled, port, motd, log, directory, executable, stopcmd, hidden, restricted);
this.host = host;
this.enabled = enabled;
this.log = new Container<Boolean>(log);
@ -76,49 +108,48 @@ public class InternalSubServer extends SubServerContainer {
this.logger = new InternalSubLogger(null, this, getName(), this.log, null);
this.thread = null;
this.command = null;
final File[] locations = new File[] {
new File(this.directory, "plugins/SubServers.Client.jar"),
new File(this.directory, "mods/SubServers.Client.jar")
};
if (new UniversalFile(this.directory, "plugins:SubServers.Client.jar").exists()) {
try {
JarInputStream updated = new JarInputStream(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/client.jar"));
JarFile existing = new JarFile(new UniversalFile(this.directory, "plugins:SubServers.Client.jar"));
for (File location : locations) {
if (location.exists()) {
try {
JarInputStream updated = new JarInputStream(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/client.jar"));
JarFile existing = new JarFile(location);
if (existing.getManifest().getMainAttributes().getValue("Implementation-Title") != null && existing.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && existing.getManifest().getMainAttributes().getValue("Specification-Title") != null &&
updated.getManifest().getMainAttributes().getValue("Implementation-Title") != null && updated.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && updated.getManifest().getMainAttributes().getValue("Specification-Title") != null) {
if (new Version(existing.getManifest().getMainAttributes().getValue("Specification-Title")).compareTo(new Version(updated.getManifest().getMainAttributes().getValue("Specification-Title"))) < 0) {
new UniversalFile(this.directory, "plugins:SubServers.Client.jar").delete();
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new UniversalFile(this.directory, "plugins:SubServers.Client.jar").getPath());
if (existing.getManifest().getMainAttributes().getValue("Implementation-Title") != null && existing.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && existing.getManifest().getMainAttributes().getValue("Specification-Title") != null &&
updated.getManifest().getMainAttributes().getValue("Implementation-Title") != null && updated.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && updated.getManifest().getMainAttributes().getValue("Specification-Title") != null) {
if (new Version(existing.getManifest().getMainAttributes().getValue("Specification-Title")).compareTo(new Version(updated.getManifest().getMainAttributes().getValue("Specification-Title"))) < 0) {
location.delete();
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", location.getPath());
}
}
existing.close();
updated.close();
} catch (Throwable e) {
System.out.println("Couldn't auto-update SubServers.Client for subserver: " + name);
e.printStackTrace();
}
existing.close();
updated.close();
} catch (Throwable e) {
System.out.println("Couldn't auto-update SubServers.Client.jar for " + name);
e.printStackTrace();
}
} else if (new UniversalFile(this.directory, "mods:SubServers.Client.jar").exists()) {
try {
JarInputStream updated = new JarInputStream(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/client.jar"));
JarFile existing = new JarFile(new UniversalFile(this.directory, "mods:SubServers.Client.jar"));
if (existing.getManifest().getMainAttributes().getValue("Implementation-Title") != null && existing.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && existing.getManifest().getMainAttributes().getValue("Specification-Title") != null &&
updated.getManifest().getMainAttributes().getValue("Implementation-Title") != null && updated.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && updated.getManifest().getMainAttributes().getValue("Specification-Title") != null) {
if (new Version(existing.getManifest().getMainAttributes().getValue("Specification-Title")).compareTo(new Version(updated.getManifest().getMainAttributes().getValue("Specification-Title"))) < 0) {
new UniversalFile(this.directory, "mods:SubServers.Client.jar").delete();
Util.copyFromJar(SubProxy.class.getClassLoader(), "net/ME1312/SubServers/Bungee/Library/Files/client.jar", new UniversalFile(this.directory, "mods:SubServers.Client.jar").getPath());
}
}
existing.close();
updated.close();
} catch (Throwable e) {
System.out.println("Couldn't auto-update SubServers.Client.jar for " + name);
e.printStackTrace();
}
}
this.lock = false;
}
void registered(boolean value) {
registered = value;
}
void updating(boolean value) {
updating = value;
}
private void run() {
boolean locked = lock;
allowrestart = true;
stopping = false;
started = false;
try {
ProcessBuilder pb = new ProcessBuilder().command(Executable.parse(host.getCreator().getBashDirectory(), executable)).directory(directory);
@ -127,10 +158,12 @@ public class InternalSubServer extends SubServerContainer {
pb.environment().put("host", host.getName());
pb.environment().put("address", host.getAddress().getHostAddress());
pb.environment().put("port", Integer.toString(getAddress().getPort()));
logger.init();
process = pb.start();
Logger.get("SubServers").info("Now starting " + getName());
logger.process = process;
logger.start();
lock = locked = false;
command = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
for (LoggedCommand command : history) if (process.isAlive()) {
this.command.write(command.getCommand());
@ -141,12 +174,16 @@ public class InternalSubServer extends SubServerContainer {
if (process.isAlive()) process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
if (locked) lock = false;
allowrestart = false;
}
logger.destroy();
Logger.get("SubServers").info(getName() + " has stopped");
process = null;
command = null;
started = false;
stopping = false;
history.clear();
SubStoppedEvent event = new SubStoppedEvent(this);
@ -155,9 +192,9 @@ public class InternalSubServer extends SubServerContainer {
if (stopaction == StopAction.REMOVE_SERVER || stopaction == StopAction.RECYCLE_SERVER || stopaction == StopAction.DELETE_SERVER) {
try {
if (stopaction == StopAction.RECYCLE_SERVER) {
host.recycleSubServer(getName());
host.recycleSubServer(null, getName(), false, false);
} else if (stopaction == StopAction.DELETE_SERVER) {
host.deleteSubServer(getName());
host.deleteSubServer(null, getName(), false, false);
} else {
try {
if (host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
@ -194,11 +231,13 @@ public class InternalSubServer extends SubServerContainer {
lock = true;
SubStartEvent event = new SubStartEvent(player, this);
host.plugin.getPluginManager().callEvent(event);
lock = false;
if (!event.isCancelled()) {
(thread = new Thread(this::run, "SubServers.Bungee::Internal_Server_Process_Handler(" + getName() + ')')).start();
return true;
} else return false;
} else {
lock = false;
return false;
}
} else return false;
}
@ -209,6 +248,7 @@ public class InternalSubServer extends SubServerContainer {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
try {
stopping = true;
allowrestart = false;
history.add(new LoggedCommand(player, stopcmd));
if (process != null && process.isAlive()) {
@ -231,6 +271,7 @@ public class InternalSubServer extends SubServerContainer {
SubStopEvent event = new SubStopEvent(player, this, true);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
stopping = true;
allowrestart = false;
if (process != null && process.isAlive()) Executable.terminate(process);
return true;
@ -240,13 +281,16 @@ public class InternalSubServer extends SubServerContainer {
@Override
public boolean command(UUID player, String command) {
if (Util.isNull(command)) throw new NullPointerException();
Util.nullpo(command);
if (thread != null && thread.isAlive()) {
SubSendCommandEvent event = new SubSendCommandEvent(player, this, command);
SubSendCommandEvent event = new SubSendCommandEvent(player, this, command, null);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
if (!event.isCancelled() && (player == null || !DISALLOWED_COMMANDS.matcher(command).find())) {
try {
if (event.getCommand().equalsIgnoreCase(stopcmd)) allowrestart = false;
if (event.getCommand().equalsIgnoreCase(stopcmd)) {
stopping = true;
allowrestart = false;
}
history.add(new LoggedCommand(player, event.getCommand()));
if (process != null && process.isAlive()) {
this.command.write(event.getCommand());
@ -262,16 +306,9 @@ public class InternalSubServer extends SubServerContainer {
} else return false;
}
public int edit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, false);
}
public int permaEdit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, true);
}
@SuppressWarnings({"deprecation", "unchecked"})
private int edit(UUID player, ObjectMap<String> edit, boolean perma) {
@Override
protected int edit(UUID player, ObjectMap<String> edit, boolean perma) {
if (isAvailable()) {
int c = 0;
boolean state = isRunning();
@ -280,14 +317,18 @@ public class InternalSubServer extends SubServerContainer {
for (String key : edit.getKeys()) {
pending.remove(key);
ObjectMapValue value = edit.get(key);
SubEditServerEvent event = new SubEditServerEvent(player, this, new NamedContainer<String, ObjectMapValue>(key, value), perma);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
boolean allowed = true;
if (perma) {
SubEditServerEvent event = new SubEditServerEvent(player, this, new ContainedPair<String, ObjectMapValue>(key, value));
host.plugin.getPluginManager().callEvent(event);
allowed = !event.isCancelled();
}
if (allowed) {
try {
switch (key.toLowerCase()) {
case "name":
if (value.isString() && host.removeSubServer(player, getName())) {
SubServer server = host.addSubServer(player, value.asRawString(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(value.asString(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
ObjectMap<String> config = this.host.plugin.servers.get().getMap("Servers").getMap(getName());
@ -302,14 +343,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "display":
if (value.isString()) {
Field f = ServerContainer.class.getDeclaredField("nick");
f.setAccessible(true);
if (value.isNull() || value.asString().length() == 0 || getName().equals(value.asString())) {
f.set(this, null);
} else {
f.set(this, value.asString());
}
f.setAccessible(false);
setDisplayName(value.asString());
logger.name = getDisplayName();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
if (getName().equals(getDisplayName())) {
@ -334,9 +368,9 @@ public class InternalSubServer extends SubServerContainer {
break;
case "group":
if (value.isList()) {
Util.reflect(ServerContainer.class.getDeclaredField("groups"), this, value.asRawStringList());
Util.reflect(ServerImpl.class.getDeclaredField("groups"), this, value.asStringList());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Group", value.asRawStringList());
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Group", value.asStringList());
this.host.plugin.servers.save();
}
c++;
@ -344,7 +378,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "host":
if (value.isString() && host.removeSubServer(player, getName())) {
SubServer server = this.host.plugin.api.getHost(value.asRawString()).addSubServer(player, getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = this.host.plugin.api.getHost(value.asString()).constructSubServer(getName(), isEnabled(), getAddress().getPort(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Host", server.getHost().getName());
@ -357,9 +391,9 @@ public class InternalSubServer extends SubServerContainer {
break;
case "template":
if (value.isString()) {
Util.reflect(SubServerContainer.class.getDeclaredField("template"), this, value.asRawString());
setTemplate(value.asString());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Template", value.asRawString());
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Template", value.asString());
this.host.plugin.servers.save();
}
c++;
@ -367,7 +401,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "port":
if (value.isNumber() && host.removeSubServer(player, getName())) {
SubServer server = host.addSubServer(player, getName(), isEnabled(), value.asInt(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
SubServer server = host.constructSubServer(getName(), isEnabled(), value.asInt(), getMotd(), isLogging(), getPath(), getExecutable(), getStopCommand(), isHidden(), isRestricted());
if (server != null) {
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Port", server.getAddress().getPort());
@ -380,7 +414,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "motd":
if (value.isString()) {
Util.reflect(BungeeServerInfo.class.getDeclaredField("motd"), this, ChatColor.translateAlternateColorCodes('&', value.asString()));
setMotd(ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(value.asString())));
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Motd", value.asString());
this.host.plugin.servers.save();
@ -390,7 +424,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "log":
if (value.isBoolean()) {
log.set(value.asBoolean());
log.value(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Log", isLogging());
this.host.plugin.servers.save();
@ -405,8 +439,8 @@ public class InternalSubServer extends SubServerContainer {
stop(player);
waitFor();
}
dir = value.asRawString();
directory = new File(getHost().getPath(), value.asRawString());
dir = value.asString();
directory = new File(getHost().getPath(), value.asString());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Directory", getPath());
this.host.plugin.servers.save();
@ -421,9 +455,9 @@ public class InternalSubServer extends SubServerContainer {
stop(player);
waitFor();
}
executable = value.asRawString();
executable = value.asString();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Executable", value.asRawString());
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Executable", value.asString());
this.host.plugin.servers.save();
}
c++;
@ -432,7 +466,7 @@ public class InternalSubServer extends SubServerContainer {
case "stop-cmd":
case "stop-command":
if (value.isString()) {
stopcmd = value.asRawString();
stopcmd = value.asString();
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Stop-Command", getStopCommand());
this.host.plugin.servers.save();
@ -442,7 +476,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "stop-action":
if (value.isString()) {
StopAction action = Util.getDespiteException(() -> StopAction.valueOf(value.asRawString().toUpperCase().replace('-', '_').replace(' ', '_')), null);
StopAction action = Try.all.get(() -> StopAction.valueOf(value.asString().toUpperCase().replace('-', '_').replace(' ', '_')));
if (action != null) {
stopaction = action;
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
@ -484,7 +518,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "restricted":
if (value.isBoolean()) {
Util.reflect(BungeeServerInfo.class.getDeclaredField("restricted"), this, value.asBoolean());
setRestricted(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Restricted", isRestricted());
this.host.plugin.servers.save();
@ -494,7 +528,7 @@ public class InternalSubServer extends SubServerContainer {
break;
case "hidden":
if (value.isBoolean()) {
Util.reflect(ServerContainer.class.getDeclaredField("hidden"), this, value.asBoolean());
setHidden(value.asBoolean());
if (perma && this.host.plugin.servers.get().getMap("Servers").getKeys().contains(getName())) {
this.host.plugin.servers.get().getMap("Servers").getMap(getName()).set("Hidden", isHidden());
this.host.plugin.servers.save();
@ -504,7 +538,10 @@ public class InternalSubServer extends SubServerContainer {
break;
case "whitelist":
if (value.isList()) {
Util.reflect(ServerContainer.class.getDeclaredField("whitelist"), this, value.asUUIDList());
Util.reflect(ServerImpl.class.getDeclaredField("whitelist"), this, value.asUUIDList());
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.WHITELIST_SET, value.asUUIDList()));
}
c++;
}
break;
@ -512,7 +549,7 @@ public class InternalSubServer extends SubServerContainer {
if (forward != null) {
forward.setStopAction(getStopAction());
if (!getName().equals(getDisplayName())) forward.setDisplayName(getDisplayName());
Util.reflect(SubServerContainer.class.getDeclaredField("template"), forward, Util.reflect(SubServerContainer.class.getDeclaredField("template"), this));
forward.setTemplate(getTemplate());
List<String> groups = new ArrayList<String>();
groups.addAll(getGroups());
for (String group : groups) {
@ -524,6 +561,7 @@ public class InternalSubServer extends SubServerContainer {
forward.toggleCompatibility(server);
}
for (String extra : getExtra().getKeys()) forward.addExtra(extra, getExtra(extra));
forward.getHost().addSubServer(player, forward);
if (state) pending.set("state", true);
c += (perma)?forward.permaEdit(player, pending):forward.edit(player, pending);
@ -548,7 +586,7 @@ public class InternalSubServer extends SubServerContainer {
@Override
public boolean isRunning() {
return process != null && process.isAlive();
return (process != null && process.isAlive()) || lock;
}
@Override
@ -569,21 +607,19 @@ public class InternalSubServer extends SubServerContainer {
@Override
public void setEnabled(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("enabled", value), false));
Util.nullpo(value);
enabled = value;
}
@Override
public boolean isLogging() {
return log.get();
return log.value();
}
@Override
public void setLogging(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("log", value), false));
log.set(value);
Util.nullpo(value);
log.value(value);
}
@Override
@ -613,8 +649,7 @@ public class InternalSubServer extends SubServerContainer {
@Override
public void setStopCommand(String value) {
if (Util.isNull(value)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("stop-cmd", value), false));
Util.nullpo(value);
stopcmd = value;
}
@ -625,8 +660,7 @@ public class InternalSubServer extends SubServerContainer {
@Override
public void setStopAction(StopAction action) {
if (Util.isNull(action)) throw new NullPointerException();
host.plugin.getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("stop-action", action), false));
Util.nullpo(action);
stopaction = action;
}
}

View File

@ -1,16 +1,17 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.ExtraDataHandler;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.ClientHandler;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.SubRemoveProxyEvent;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.ExtraDataHandler;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.ClientHandler;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExSyncPlayer;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.api.ProxyServer;
import java.util.*;
@ -18,20 +19,16 @@ import java.util.*;
/**
* Proxy Class
*/
public class Proxy implements ClientHandler, ExtraDataHandler {
private HashMap<Integer, SubDataClient> subdata = new HashMap<Integer, SubDataClient>();
private ObjectMap<String> extra = new ObjectMap<String>();
public class Proxy implements ClientHandler, ExtraDataHandler<String> {
private final HashMap<Integer, SubDataClient> subdata = new HashMap<Integer, SubDataClient>();
private final ObjectMap<String> extra = new ObjectMap<String>();
private final String signature;
private boolean persistent = true;
private boolean persistent = false;
private String nick = null;
private final String name;
@SuppressWarnings("deprecation")
public Proxy(String name) throws IllegalArgumentException {
if (name == null) {
name = Util.getNew(SubAPI.getInstance().getInternals().proxies.keySet(), () -> UUID.randomUUID().toString());
persistent = false;
}
if (name == null) name = Util.getNew(SubAPI.getInstance().getInternals().proxies.keySet(), () -> UUID.randomUUID().toString());
if (name.contains(" ")) throw new IllegalArgumentException("Proxy names cannot have spaces: " + name);
this.name = name;
this.signature = SubAPI.getInstance().signAnonymousObject();
@ -41,21 +38,22 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
@Override
public DataClient[] getSubData() {
LinkedList<Integer> keys = new LinkedList<Integer>(subdata.keySet());
LinkedList<SubDataClient> channels = new LinkedList<SubDataClient>();
Collections.sort(keys);
for (Integer channel : keys) channels.add(subdata.get(channel));
return channels.toArray(new DataClient[0]);
Integer[] keys = subdata.keySet().toArray(new Integer[0]);
DataClient[] channels = new DataClient[keys.length];
Arrays.sort(keys);
for (int i = 0; i < keys.length; ++i) channels[i] = subdata.get(keys[i]);
return channels;
}
@SuppressWarnings("deprecation")
public void setSubData(SubDataClient client, int channel) {
boolean update = false;
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
update = true;
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);
subdata.put(channel, client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) client.setHandler(this);
}
} else {
update = true;
@ -64,9 +62,20 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
if (update) {
DataClient[] subdata = getSubData();
if (subdata[0] == null && subdata.length <= 1 && !persistent) {
ProxyServer.getInstance().getPluginManager().callEvent(new SubRemoveProxyEvent(this));
SubAPI.getInstance().getInternals().proxies.remove(getName().toLowerCase());
if (subdata[0] == null && subdata.length <= 1) {
SubProxy plugin = SubAPI.getInstance().getInternals();
for (UUID id : Util.getBackwards(plugin.rPlayerLinkP, this)) {
plugin.rPlayerLinkS.remove(id);
plugin.rPlayerLinkP.remove(id);
plugin.rPlayers.remove(id);
}
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null && proxy != this) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(getName(), null, (RemotePlayer[]) null));
}
if (!persistent) {
ProxyServer.getInstance().getPluginManager().callEvent(new SubRemoveProxyEvent(this));
SubAPI.getInstance().getInternals().proxies.remove(getName().toLowerCase());
}
}
}
}
@ -108,34 +117,36 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
}
/**
* Test if the proxy is connected to RedisBungee's server
* Determine if the proxy is the Master Proxy
*
* @return Redis Status
* @return Master Proxy Status
*/
@SuppressWarnings({"deprecation", "unchecked"})
public boolean isRedis() {
SubProxy plugin = SubAPI.getInstance().getInternals();
return plugin.redis != null && Util.getDespiteException(() -> plugin.redis("getPlayersOnProxy", new NamedContainer<>(String.class, getName())) != null, false);
public boolean isMaster() {
return SubAPI.getInstance().getMasterProxy() == this;
}
/**
* Get the players on this proxy (via RedisBungee)
* Get the players on this proxy
*
* @return Player Collection
* @return Remote Player Collection
*/
@SuppressWarnings({"deprecation", "unchecked"})
public Collection<NamedContainer<String, UUID>> getPlayers() {
List<NamedContainer<String, UUID>> players = new ArrayList<NamedContainer<String, UUID>>();
@SuppressWarnings("deprecation")
public Collection<RemotePlayer> getPlayers() {
SubProxy plugin = SubAPI.getInstance().getInternals();
if (plugin.redis != null) {
try {
for (UUID player : (Set<UUID>) plugin.redis("getPlayersOnProxy", new NamedContainer<>(String.class, getName())))
players.add(new NamedContainer<>((String) plugin.redis("getNameFromUuid", new NamedContainer<>(UUID.class, player)), player));
} catch (Exception e) {}
ArrayList<RemotePlayer> players = new ArrayList<RemotePlayer>();
for (UUID id : Util.getBackwards(plugin.rPlayerLinkP, this)) {
players.add(plugin.rPlayers.get(id));
}
return players;
}
/**
* Makes it so the proxy object will still exist within the server manager even if it is disconnected
*/
public final void persist() {
persistent = true;
}
/**
* Get the Signature of this Object
*
@ -145,21 +156,26 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
return signature;
}
@Override
public boolean equals(Object obj) {
return obj instanceof Proxy && signature.equals(((Proxy) obj).signature);
}
@Override
public void addExtra(String handle, Object value) {
if (Util.isNull(handle, value)) throw new NullPointerException();
Util.nullpo(handle, value);
extra.set(handle, value);
}
@Override
public boolean hasExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
return extra.getKeys().contains(handle);
}
@Override
public ObjectMapValue getExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
return extra.get(handle);
}
@ -170,7 +186,7 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
@Override
public void removeExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
Util.nullpo(handle);
extra.remove(handle);
}
@ -181,13 +197,10 @@ public class Proxy implements ClientHandler, ExtraDataHandler {
info.set("name", getName());
info.set("display", getDisplayName());
ObjectMap<String> players = new ObjectMap<String>();
for (NamedContainer<String, UUID> player : getPlayers()) {
ObjectMap<String> pinfo = new ObjectMap<String>();
pinfo.set("name", player.name());
players.set(player.get().toString(), pinfo);
}
for (RemotePlayer player : getPlayers())
players.set(player.getUniqueId().toString(), player.getName());
info.set("players", players);
info.set("redis", isRedis());
info.set("master", isMaster());
ObjectMap<Integer> subdata = new ObjectMap<Integer>();
for (int channel : this.subdata.keySet()) subdata.set(channel, (this.subdata.get(channel) == null)?null:this.subdata.get(channel).getID());
info.set("subdata", subdata);

View File

@ -0,0 +1,314 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.SubDataSerializable;
import net.ME1312.SubServers.Bungee.Library.Compatibility.RPSI;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketDisconnectPlayer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketMessagePlayer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketTransferPlayer;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.UUID;
import java.util.function.IntConsumer;
/**
* Remote Player Class
*/
public class RemotePlayer implements net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer, SubDataSerializable {
private ProxiedPlayer local;
private UUID id;
private String name;
private InetSocketAddress ip;
private Proxy proxy;
private Server server;
/**
* Translate a Local Player to a Remote Player
*
* @param player Local Player
*/
public RemotePlayer(ProxiedPlayer player) {
this(player, player.getServer().getInfo());
}
/**
* Translate a Local Player to a Remote Player
*
* @param player Local Player
* @param server Server the player is on
*/
public RemotePlayer(ProxiedPlayer player, ServerInfo server) {
Util.nullpo(player);
this.local = player;
this.id = player.getUniqueId();
this.server = (server instanceof Server)? (Server) server : null;
}
/**
* Search for a Remote Player using their ID
*
* @param name Player Name
* @param id Player UUID
* @param proxy Proxy the player is on
* @param server Server the player is on
* @param ip Player IP Address
*/
public RemotePlayer(String name, UUID id, Proxy proxy, ServerInfo server, InetSocketAddress ip) {
Util.nullpo(name, id, proxy, ip);
this.id = id;
this.name = name;
this.ip = ip;
this.proxy = proxy;
this.server = (server instanceof Server)? (Server) server : null;
}
@Override
public ProxiedPlayer get() {
return local;
}
private static ProxiedPlayer get(UUID player) {
return ProxyServer.getInstance().getPlayer(player);
}
@Override
public UUID getUniqueId() {
if (local != null) {
return local.getUniqueId();
} else return id;
}
@Override
public String getName() {
if (local != null) {
return local.getName();
} else return name;
}
@SuppressWarnings("deprecation")
@Override
public InetSocketAddress getAddress() {
if (local != null) {
return local.getAddress();
} else return ip;
}
/**
* Gets the proxy this player is connected to.
*
* @return the proxy this player is connected to
*/
public Proxy getProxy() {
if (local != null) {
return SubAPI.getInstance().getMasterProxy();
} else return proxy;
}
@Override
public String getProxyName() {
Proxy proxy = getProxy();
return (proxy == null)? null : proxy.getName();
}
private SubDataClient getProxyConnection() {
Proxy proxy = getProxy();
return (proxy == null)? null : (SubDataClient) proxy.getSubData()[0];
}
@Override
public Server getServer() {
return server;
}
@Override
public String getServerName() {
Server server = getServer();
return (server == null)? null : server.getName();
}
@Override
public boolean equals(Object obj) {
return obj instanceof RemotePlayer && getUniqueId().equals(((RemotePlayer) obj).getUniqueId());
}
@Override
public ObjectMap<String> forSubData() {
ObjectMap<String> pinfo = new ObjectMap<String>();
pinfo.set("name", getName());
pinfo.set("id", getUniqueId());
pinfo.set("address", getAddress().getAddress().getHostAddress() + ':' + getAddress().getPort());
if (getServer() != null) pinfo.set("server", getServer().getName());
if (getProxy() != null) pinfo.set("proxy", getProxy().getName());
return pinfo;
}
static {
// These overrides provide for the static methods in BungeeCommon
new RPSI() {
@Override
protected void sendMessage(UUID[] players, String[] messages, IntConsumer response) {
StackTraceElement[] origin = new Throwable().getStackTrace();
PacketMessagePlayer.run(Arrays.asList(players), new ContainedPair<>(messages, null), null, i -> {
try {
response.accept(i);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
ew.printStackTrace();
}
});
}
@Override
protected void sendMessage(UUID[] players, BaseComponent[][] messages, IntConsumer response) {
StackTraceElement[] origin = new Throwable().getStackTrace();
PacketMessagePlayer.run(Arrays.asList(players), new ContainedPair<>(null, messages), null, i -> {
try {
response.accept(i);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
ew.printStackTrace();
}
});
}
@Override
protected void transfer(UUID[] players, String server, IntConsumer response) {
StackTraceElement[] origin = new Throwable().getStackTrace();
PacketTransferPlayer.run(Arrays.asList(players), server, i -> {
try {
response.accept(i);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
ew.printStackTrace();
}
});
}
@Override
protected void disconnect(UUID[] players, String reason, IntConsumer response) {
StackTraceElement[] origin = new Throwable().getStackTrace();
PacketDisconnectPlayer.run(Arrays.asList(players), reason, i -> {
try {
response.accept(i);
} catch (Throwable e) {
Throwable ew = new InvocationTargetException(e);
ew.setStackTrace(origin);
ew.printStackTrace();
}
});
}
};
}
// The following methods all redirect to their BungeeCommon counterparts
public static void broadcastMessage(String... messages) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(messages);
}
public static void broadcastMessage(String message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(message, response);
}
public static void broadcastMessage(String[] messages, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(messages, response);
}
public static void sendMessage(UUID[] players, String... messages) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, messages);
}
public static void sendMessage(UUID[] players, String message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, message, response);
}
public static void sendMessage(UUID[] players, String[] messages, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, messages, response);
}
public static void broadcastMessage(BaseComponent... message) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(message);
}
public static void broadcastMessage(BaseComponent message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(message, response);
}
public static void broadcastMessage(BaseComponent[] message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(message, response);
}
public static void broadcastMessage(BaseComponent[]... messages) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(messages);
}
public static void broadcastMessage(BaseComponent[][] messages, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.broadcastMessage(messages, response);
}
public static void sendMessage(UUID[] players, BaseComponent... message) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, message);
}
public static void sendMessage(UUID[] players, BaseComponent message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, message, response);
}
public static void sendMessage(UUID[] players, BaseComponent[] message, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, message, response);
}
public static void sendMessage(UUID[] players, BaseComponent[]... messages) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, messages);
}
public static void sendMessage(UUID[] players, BaseComponent[][] messages, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.sendMessage(players, messages, response);
}
public static void transfer(UUID[] players, String server) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.transfer(players, server);
}
public static void transfer(UUID[] players, String server, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.transfer(players, server, response);
}
public static void transfer(UUID[] players, ServerInfo server) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.transfer(players, server);
}
public static void transfer(UUID[] players, ServerInfo server, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.transfer(players, server, response);
}
public static void disconnect(UUID... players) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.disconnect(players);
}
public static void disconnect(UUID[] players, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.disconnect(players, response);
}
public static void disconnect(UUID[] players, String reason) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.disconnect(players, reason);
}
public static void disconnect(UUID[] players, String reason, IntConsumer response) {
net.ME1312.SubServers.Bungee.Library.Compatibility.RemotePlayer.disconnect(players, reason, response);
}
}

View File

@ -1,9 +1,9 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.ExtraDataHandler;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.SubData.Server.ClientHandler;
import net.ME1312.SubData.Server.DataClient;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.Collection;
@ -13,7 +13,7 @@ import java.util.UUID;
/**
* Server Interface
*/
public interface Server extends ServerInfo, ClientHandler, ExtraDataHandler {
public interface Server extends ServerInfo, ClientHandler, ExtraDataHandler<String> {
/**
* Link a SubData Client to this Object
@ -58,12 +58,40 @@ public interface Server extends ServerInfo, ClientHandler, ExtraDataHandler {
*/
void removeGroup(String value);
/**
* Commands the Server
*
* @param player Player who's Commanding
* @param target Player who will Send
* @param command Command to Send
*/
boolean command(UUID player, UUID target, String command);
/**
* Commands the Server
*
* @param player Player who's Commanding
* @param command Command to Send
*/
default boolean command(UUID player, String command) {
return command(player, null, command);
}
/**
* Commands the Server
*
* @param command Command to Send
*/
default boolean command(String command) {
return command(null, command);
}
/**
* Get players on this server across all known proxies
*
* @return Player Collection
* @return Remote Player Collection
*/
Collection<NamedContainer<String, UUID>> getGlobalPlayers();
Collection<RemotePlayer> getRemotePlayers();
/**
* If the server is hidden from players
@ -136,6 +164,11 @@ public interface Server extends ServerInfo, ClientHandler, ExtraDataHandler {
*/
void unwhitelist(UUID player);
/**
* Makes it so the server object will still exist within the server manager even if it is disconnected
*/
void persist();
/**
* Get the Signature of this Object
*

View File

@ -1,270 +0,0 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.SubEditServerEvent;
import net.ME1312.SubServers.Bungee.Event.SubNetworkConnectEvent;
import net.ME1312.SubServers.Bungee.Event.SubNetworkDisconnectEvent;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExRunEvent;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExUpdateWhitelist;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.net.InetSocketAddress;
import java.util.*;
/**
* Server Class
*/
public class ServerContainer extends BungeeServerInfo implements Server {
private HashMap<Integer, SubDataClient> subdata = new HashMap<Integer, SubDataClient>();
private ObjectMap<String> extra = new ObjectMap<String>();
private String nick = null;
private List<String> groups = new ArrayList<String>();
private List<UUID> whitelist = new ArrayList<UUID>();
private boolean hidden;
private final String signature;
@SuppressWarnings("deprecation")
public ServerContainer(String name, InetSocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(name, address, motd, restricted);
if (Util.isNull(name, address, motd, hidden, restricted)) throw new NullPointerException();
if (name.contains(" ")) throw new InvalidServerException("Server names cannot have spaces: " + name);
signature = SubAPI.getInstance().signAnonymousObject();
SubAPI.getInstance().getInternals().subprotocol.whitelist(getAddress().getAddress().getHostAddress());
this.hidden = hidden;
subdata.put(0, null);
}
@Override
public DataClient[] getSubData() {
LinkedList<Integer> keys = new LinkedList<Integer>(subdata.keySet());
LinkedList<SubDataClient> channels = new LinkedList<SubDataClient>();
Collections.sort(keys);
for (Integer channel : keys) channels.add(subdata.get(channel));
return channels.toArray(new DataClient[0]);
}
public void setSubData(DataClient client, int channel) {
boolean update = false;
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
update = true;
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);
}
} else {
update = true;
subdata.remove(channel);
}
if (update) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
ObjectMap<String> args = new ObjectMap<String>();
args.set("server", getName());
args.set("channel", channel);
if (client != null) args.set("id", client.getID());
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExRunEvent((client != null)?SubNetworkConnectEvent.class:SubNetworkDisconnectEvent.class, args));
}
}
@Override
public void removeSubData(DataClient client) {
for (Integer channel : Util.getBackwards(subdata, (SubDataClient) client)) setSubData(null, channel);
}
@Override
public String getDisplayName() {
return (nick == null)?getName():nick;
}
@Override
@SuppressWarnings("deprecation")
public void setDisplayName(String value) {
if (value == null || value.length() == 0 || getName().equals(value)) {
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("display", getName()), false));
this.nick = null;
} else {
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("display", value), false));
this.nick = value;
}
}
@Override
public List<String> getGroups() {
return groups;
}
@Override
@SuppressWarnings("deprecation")
public void addGroup(String value) {
if (Util.isNull(value)) throw new NullPointerException();
if (value.length() > 0 && !groups.contains(value)) {
groups.add(value);
Collections.sort(groups);
}
}
@Override
@SuppressWarnings("deprecation")
public void removeGroup(String value) {
if (Util.isNull(value)) throw new NullPointerException();
groups.remove(value);
Collections.sort(groups);
}
@SuppressWarnings({"deprecation", "unchecked"})
@Override
public Collection<NamedContainer<String, UUID>> getGlobalPlayers() {
List<NamedContainer<String, UUID>> players = new ArrayList<NamedContainer<String, UUID>>();
SubProxy plugin = SubAPI.getInstance().getInternals();
if (plugin.redis != null) {
try {
for (UUID player : (Set<UUID>) plugin.redis("getPlayersOnServer", new NamedContainer<>(String.class, getName()))) players.add(new NamedContainer<>((String) plugin.redis("getNameFromUuid", new NamedContainer<>(UUID.class, player)), player));
} catch (Exception e) {}
} else {
for (ProxiedPlayer player : getPlayers()) players.add(new NamedContainer<>(player.getName(), player.getUniqueId()));
}
return players;
}
@Override
public boolean isHidden() {
return hidden;
}
@Override
@SuppressWarnings("deprecation")
public void setHidden(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("hidden", value), false));
this.hidden = value;
}
@SuppressWarnings("deprecation")
public void setMotd(String value) {
if (Util.isNull(value)) throw new NullPointerException();
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("motd", value), false));
try {
Util.reflect(BungeeServerInfo.class.getDeclaredField("motd"), this, value);
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("deprecation")
public void setRestricted(boolean value) {
if (Util.isNull(value)) throw new NullPointerException();
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("restricted", value), false));
try {
Util.reflect(BungeeServerInfo.class.getDeclaredField("restricted"), this, value);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Collection<UUID> getWhitelist() {
return new ArrayList<UUID>(whitelist);
}
/**
* See if a player can access this server
*
* @param player Player
* @return Whitelisted Status
*/
@Override
public boolean canAccess(CommandSender player) {
return (player instanceof ProxiedPlayer && whitelist.contains(((ProxiedPlayer) player).getUniqueId())) || super.canAccess(player);
}
@Override
public boolean isWhitelisted(UUID player) {
return whitelist.contains(player);
}
@Override
public void whitelist(UUID player) {
if (Util.isNull(player)) throw new NullPointerException();
if (!whitelist.contains(player)) whitelist.add(player);
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExUpdateWhitelist(getName(), true, player));
}
@Override
public void unwhitelist(UUID player) {
if (Util.isNull(player)) throw new NullPointerException();
whitelist.remove(player);
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExUpdateWhitelist(getName(), false, player));
}
@Override
public final String getSignature() {
return signature;
}
@Override
public void addExtra(String handle, Object value) {
if (Util.isNull(handle, value)) throw new NullPointerException();
extra.set(handle, value);
}
@Override
public boolean hasExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
return extra.getKeys().contains(handle);
}
@Override
public ObjectMapValue getExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
return extra.get(handle);
}
@Override
public ObjectMap<String> getExtra() {
return extra.clone();
}
@Override
public void removeExtra(String handle) {
if (Util.isNull(handle)) throw new NullPointerException();
extra.remove(handle);
}
@Override
public ObjectMap<String> forSubData() {
ObjectMap<String> info = new ObjectMap<String>();
info.set("type", "Server");
info.set("name", getName());
info.set("display", getDisplayName());
info.set("group", getGroups());
info.set("address", getAddress().getAddress().getHostAddress() + ':' + getAddress().getPort());
info.set("motd", getMotd());
info.set("whitelist", getWhitelist());
info.set("restricted", isRestricted());
info.set("hidden", isHidden());
ObjectMap<String> players = new ObjectMap<String>();
for (NamedContainer<String, UUID> player : getGlobalPlayers()) {
ObjectMap<String> pinfo = new ObjectMap<String>();
pinfo.set("name", player.name());
players.set(player.get().toString(), pinfo);
}
info.set("players", players);
ObjectMap<Integer> subdata = new ObjectMap<Integer>();
for (int channel : this.subdata.keySet()) subdata.set(channel, (this.subdata.get(channel) == null)?null:this.subdata.get(channel).getID());
info.set("subdata", subdata);
info.set("signature", signature);
info.set("extra", getExtra());
return info;
}
}

View File

@ -0,0 +1,344 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Map.ObjectMapValue;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.DataClient;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Event.SubSendCommandEvent;
import net.ME1312.SubServers.Bungee.Host.SubServer.LoggedCommand;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketExControlPlayer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExEditServer.Edit;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.*;
/**
* Server Class
*/
public class ServerImpl extends BungeeServerInfo implements Server {
private HashMap<Integer, SubDataClient> subdata = new HashMap<Integer, SubDataClient>();
private ObjectMap<String> extra = new ObjectMap<String>();
private String nick = null;
private List<String> groups = new ArrayList<String>();
private List<UUID> whitelist = new ArrayList<UUID>();
private boolean hidden;
private final String signature = SubAPI.getInstance().signAnonymousObject();
private volatile boolean persistent = true;
/**
* Construct a new Server data type
*
* @param name Server name
* @param address Server Address
* @param motd Server MOTD
* @param hidden Hidden Status
* @param restricted Restricted Status
* @return
*/
public static ServerImpl construct(String name, SocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
try {
return new ServerImpl(name, address, motd, hidden, restricted);
} catch (NoSuchMethodError e) {
return new ServerImpl(name, (InetSocketAddress) address, motd, hidden, restricted);
}
}
/**
* Super Method 2 (newest)
* @see #construct(String, SocketAddress, String, boolean, boolean) for method details
*/
protected ServerImpl(String name, SocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(name, address, motd, restricted);
init(name, address, motd, hidden, restricted);
}
/**
* Super Method 1 (oldest)
* @see #construct(String, SocketAddress, String, boolean, boolean) for method details
*/
protected ServerImpl(String name, InetSocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(name, address, motd, restricted);
init(name, address, motd, hidden, restricted);
}
@SuppressWarnings("deprecation")
private void init(String name, SocketAddress address, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
Util.nullpo(name, address, motd, hidden, restricted);
if (name.contains(" ")) throw new InvalidServerException("Server names cannot have spaces: " + name);
SubAPI.getInstance().getInternals().subprotocol.whitelist(getAddress().getAddress().getHostAddress());
this.hidden = hidden;
subdata.put(0, null);
}
/**
* Get if this server has been registered
*
* @return Registered status
*/
@SuppressWarnings("deprecation")
protected boolean isRegistered() {
return SubAPI.getInstance().getInternals().exServers.containsKey(getName().toLowerCase());
}
@Override
public DataClient[] getSubData() {
Integer[] keys = subdata.keySet().toArray(new Integer[0]);
DataClient[] channels = new DataClient[keys.length];
Arrays.sort(keys);
for (int i = 0; i < keys.length; ++i) channels[i] = subdata.get(keys[i]);
return channels;
}
public void setSubData(DataClient client, int channel) {
boolean update = false;
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client != null || channel == 0) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
update = true;
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);
}
} else {
update = true;
subdata.remove(channel);
}
if (update) {
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
if (client != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.CONNECTED, channel, client.getID()));
} else {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.DISCONNECTED, channel));
}
}
if (!persistent) {
DataClient[] subdata = getSubData();
if (subdata[0] == null && subdata.length <= 1) {
SubAPI.getInstance().removeServer(getName());
}
}
}
}
@Override
public void removeSubData(DataClient client) {
for (Integer channel : Util.getBackwards(subdata, (SubDataClient) client)) setSubData(null, channel);
}
@Override
public String getDisplayName() {
return (nick == null)?getName():nick;
}
@Override
@SuppressWarnings("deprecation")
public void setDisplayName(String value) {
if (value == null || value.length() == 0 || getName().equals(value)) {
this.nick = null;
} else {
this.nick = value;
}
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.DISPLAY_NAME, getDisplayName()));
}
}
@Override
public List<String> getGroups() {
return groups;
}
@Override
@SuppressWarnings("deprecation")
public void addGroup(String value) {
Util.nullpo(value);
if (value.length() > 0 && !groups.contains(value)) {
groups.add(value);
Collections.sort(groups);
}
}
@Override
@SuppressWarnings("deprecation")
public void removeGroup(String value) {
Util.nullpo(value);
groups.remove(value);
Collections.sort(groups);
}
@Override
public boolean command(UUID player, UUID target, String command) {
Util.nullpo(command);
SubDataClient channel = (SubDataClient) getSubData()[0];
if (channel != null) {
SubSendCommandEvent event = new SubSendCommandEvent(player, this, command, target);
ProxyServer.getInstance().getPluginManager().callEvent(event);
if (!event.isCancelled() && (player == null || !SubServerImpl.DISALLOWED_COMMANDS.matcher(command).find())) {
channel.sendPacket(new PacketExControlPlayer(target, command));
return true;
} else return false;
} else return false;
}
@Override
public Collection<RemotePlayer> getRemotePlayers() {
return SubAPI.getInstance().getRemotePlayers(this).values();
}
@Override
public boolean isHidden() {
return hidden;
}
@Override
public void setHidden(boolean value) {
this.hidden = value;
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.HIDDEN, isHidden()));
}
}
public void setMotd(String value) {
Util.nullpo(value);
try {
Util.reflect(BungeeServerInfo.class.getDeclaredField("motd"), this, value);
for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.MOTD, getMotd()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void setRestricted(boolean value) {
Util.nullpo(value);
try {
Util.reflect(BungeeServerInfo.class.getDeclaredField("restricted"), this, value);
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.RESTRICTED, isRestricted()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* See if a player can access this server
*
* @param player Player
* @return Whitelisted Status
*/
@Override
public boolean canAccess(CommandSender player) {
return super.canAccess(player) || (player instanceof ProxiedPlayer && whitelist.contains(((ProxiedPlayer) player).getUniqueId()));
}
@Override
public Collection<UUID> getWhitelist() {
return new ArrayList<UUID>(whitelist);
}
@Override
public boolean isWhitelisted(UUID player) {
return whitelist.contains(player);
}
@Override
public void whitelist(UUID player) {
Util.nullpo(player);
if (!whitelist.contains(player)) whitelist.add(player);
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.WHITELIST_ADD, player));
}
}
@Override
public void unwhitelist(UUID player) {
Util.nullpo(player);
whitelist.remove(player);
if (isRegistered()) for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) {
((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketOutExEditServer(this, Edit.WHITELIST_REMOVE, player));
}
}
@Override
public final void persist() {
persistent = true;
}
@Override
public final String getSignature() {
return signature;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ServerImpl && signature.equals(((ServerImpl) obj).signature);
}
@Override
public void addExtra(String handle, Object value) {
Util.nullpo(handle, value);
extra.set(handle, value);
}
@Override
public boolean hasExtra(String handle) {
Util.nullpo(handle);
return extra.getKeys().contains(handle);
}
@Override
public ObjectMapValue getExtra(String handle) {
Util.nullpo(handle);
return extra.get(handle);
}
@Override
public ObjectMap<String> getExtra() {
return extra.clone();
}
@Override
public void removeExtra(String handle) {
Util.nullpo(handle);
extra.remove(handle);
}
@Override
public ObjectMap<String> forSubData() {
ObjectMap<String> info = new ObjectMap<String>();
info.set("type", "Server");
info.set("name", getName());
info.set("display", getDisplayName());
info.set("group", getGroups());
info.set("address", getAddress().getAddress().getHostAddress() + ':' + getAddress().getPort());
info.set("motd", getMotd());
info.set("whitelist", getWhitelist());
info.set("restricted", isRestricted());
info.set("hidden", isHidden());
ObjectMap<String> players = new ObjectMap<String>();
for (RemotePlayer player : getRemotePlayers())
players.set(player.getUniqueId().toString(), player.getName());
info.set("players", players);
ObjectMap<Integer> subdata = new ObjectMap<Integer>();
for (int channel : this.subdata.keySet()) subdata.set(channel, (this.subdata.get(channel) == null)?null:this.subdata.get(channel).getID());
info.set("subdata", subdata);
info.set("signature", signature);
info.set("extra", getExtra());
return info;
}
}

View File

@ -1,25 +1,28 @@
package net.ME1312.SubServers.Bungee.Host;
import com.google.common.collect.Range;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidTemplateException;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidTemplateException;
import net.ME1312.SubServers.Bungee.SubAPI;
import com.google.common.collect.Range;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.function.Consumer;
/**
* SubCreator Layout Class
*/
public abstract class SubCreator {
public static class ServerTemplate {
private final boolean dynamic;
private String name;
private String nick = null;
private boolean enabled;
private boolean internal;
private String icon;
private File directory;
private ServerType type;
@ -30,20 +33,28 @@ public abstract class SubCreator {
* Create a SubCreator Template
*
* @param name Template Name
* @param enabled Template Enabled Status
* @param icon Template Item Icon Name
* @param directory Template Directory
* @param build Build Options
* @param options Configuration Options
*/
public ServerTemplate(String name, boolean enabled, String icon, File directory, ObjectMap<String> build, ObjectMap<String> options) {
if (Util.isNull(name, enabled, directory, build, options)) throw new NullPointerException();
this(name, enabled, false, icon, directory, build, options, true);
}
private ServerTemplate(String name, boolean enabled, boolean internal, String icon, File directory, ObjectMap<String> build, ObjectMap<String> options, boolean dynamic) {
Util.nullpo(name, enabled, directory, build, options);
if (name.contains(" ")) throw new InvalidTemplateException("Template names cannot have spaces: " + name);
this.name = name;
this.enabled = enabled;
this.internal = internal;
this.icon = icon;
this.directory = directory;
this.type = (build.contains("Server-Type"))?ServerType.valueOf(build.getRawString("Server-Type").toUpperCase()):ServerType.CUSTOM;
this.type = (build.contains("Server-Type"))?ServerType.valueOf(build.getString("Server-Type").toUpperCase()):ServerType.CUSTOM;
this.build = build;
this.options = options;
this.dynamic = dynamic;
}
/**
@ -95,6 +106,15 @@ public abstract class SubCreator {
enabled = value;
}
/**
* Get if this Template is for Internal use only
*
* @return Internal Status
*/
public boolean isInternal() {
return internal;
}
/**
* Get the Item Icon for this Template
*
@ -149,6 +169,15 @@ public abstract class SubCreator {
return getBuildOptions().getBoolean("Can-Update", false);
}
/**
* Get whether this Template was generated by a SubCreator instance
*
* @return Dynamic Status
*/
public boolean isDynamic() {
return dynamic;
}
/**
* Get the Build Options for this Template
*
@ -204,7 +233,7 @@ public abstract class SubCreator {
* @param callback Callback
* @return Success Status
*/
public abstract boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Callback<SubServer> callback);
public abstract boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback);
/**
* Create a SubServer
@ -230,7 +259,7 @@ public abstract class SubCreator {
* @param callback Callback
* @return Success Status
*/
public boolean create(String name, ServerTemplate template, Version version, Integer port, Callback<SubServer> callback) {
public boolean create(String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback) {
return create(null, name, template, version, port, callback);
}
@ -252,11 +281,50 @@ public abstract class SubCreator {
*
* @param player Player Updating
* @param server Server to Update
* @param template Server Template
* @param version Server Version (may be null)
* @param callback Callback
* @return Success Status
*/
public abstract boolean update(UUID player, SubServer server, Version version, Callback<Boolean> callback);
public abstract boolean update(UUID player, SubServer server, ServerTemplate template, Version version, Consumer<Boolean> callback);
/**
* Update a SubServer
*
* @param player Player Updating
* @param server Server to Update
* @param template Server Template
* @param version Server Version (may be null)
* @return Success Status
*/
public boolean update(UUID player, SubServer server, ServerTemplate template, Version version) {
return update(player, server, template, version, null);
}
/**
* Update a SubServer
*
* @param server Server to Update
* @param template Server Template
* @param version Server Version (may be null)
* @param callback Callback
* @return Success Status
*/
public boolean update(SubServer server, ServerTemplate template, Version version, Consumer<Boolean> callback) {
return update(null, server, template, version, callback);
}
/**
* Update a SubServer
*
* @param server Server to Update
* @param template Server Template
* @param version Server Version (may be null)
* @return Success Status
*/
public boolean update(SubServer server, ServerTemplate template, Version version) {
return update(null, server, template, version);
}
/**
* Update a SubServer
@ -267,19 +335,7 @@ public abstract class SubCreator {
* @return Success Status
*/
public boolean update(UUID player, SubServer server, Version version) {
return update(player, server, version, null);
}
/**
* Update a SubServer
*
* @param server Server to Update
* @param version Server Version (may be null)
* @param callback Callback
* @return Success Status
*/
public boolean update(SubServer server, Version version, Callback<Boolean> callback) {
return update(null, server, version, callback);
return update(player, server, null, version);
}
/**
@ -462,8 +518,28 @@ public abstract class SubCreator {
*/
public abstract ServerTemplate getTemplate(String name);
/**
* Create a SubCreator Template
*
* @param name Template Name
* @param enabled Template Enabled Status
* @param internal Template Internal Status
* @param icon Template Item Icon Name
* @param directory Template Directory
* @param build Build Options
* @param options Configuration Options
*/
protected ServerTemplate loadTemplate(String name, boolean enabled, boolean internal, String icon, File directory, ObjectMap<String> build, ObjectMap<String> options) {
return new ServerTemplate(name, enabled, internal, icon, directory, build, options, false);
}
/**
* Reload SubCreator
*/
public abstract void reload();
@Override
public boolean equals(Object obj) {
return obj instanceof SubCreator && getHost().getSignature().equals(((SubCreator) obj).getHost().getSignature());
}
}

View File

@ -3,6 +3,7 @@ package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import java.io.File;
import java.util.*;
/**
@ -40,7 +41,7 @@ public interface SubServer extends Server {
* @param command Command
*/
public LoggedCommand(String command) {
if (Util.isNull(command)) throw new NullPointerException();
Util.nullpo(command);
this.date = Calendar.getInstance().getTime();
this.sender = null;
this.command = command;
@ -53,7 +54,7 @@ public interface SubServer extends Server {
* @param command Command
*/
public LoggedCommand(UUID sender, String command) {
if (Util.isNull(command)) throw new NullPointerException();
Util.nullpo(command);
this.date = Calendar.getInstance().getTime();
this.sender = sender;
this.command = command;
@ -67,7 +68,7 @@ public interface SubServer extends Server {
* @param command Command
*/
public LoggedCommand(Date date, UUID sender, String command) {
if (Util.isNull(date, command)) throw new NullPointerException();
Util.nullpo(date, command);
this.date = date;
this.sender = sender;
this.command = command;
@ -114,7 +115,9 @@ public interface SubServer extends Server {
*
* @return Success Status
*/
boolean start();
default boolean start() {
return start(null);
}
/**
* Stops the Server
@ -129,7 +132,9 @@ public interface SubServer extends Server {
*
* @return Success Status
*/
boolean stop();
default boolean stop() {
return stop(null);
}
/**
* Terminates the Server
@ -144,24 +149,9 @@ public interface SubServer extends Server {
*
* @return Success Status
*/
boolean terminate();
/**
* Commands the Server
*
* @param player Player who Commanded
* @param command Command to Send
* @return Success Status
*/
boolean command(UUID player, String command);
/**
* Commands the Server
*
* @param command Command to Send
* @return Success Status
*/
boolean command(String command);
default boolean terminate() {
return terminate(null);
}
/**
* Edits the Server
@ -219,6 +209,22 @@ public interface SubServer extends Server {
*/
boolean isRunning();
/**
* If the Server is Online<br>
* <b>This method can only be true when a SubData connection is made!</b>
*
* @return Online Status
*/
boolean isOnline();
/**
* If the Server is Stopping<br>
* <b>This method can only be true when the server is stopped through the server manager!</b>
*
* @return Stopping Status
*/
boolean isStopping();
/**
* Grabs the Host of the Server
*
@ -240,6 +246,13 @@ public interface SubServer extends Server {
*/
void setTemplate(SubCreator.ServerTemplate value);
/**
* Sets the Template this Server was created from
*
* @param value Value
*/
void setTemplate(String value);
/**
* Is this Host Available?
*
@ -310,7 +323,9 @@ public interface SubServer extends Server {
*
* @return Full Server Directory Path
*/
String getFullPath();
default String getFullPath() {
return new File(getHost().getPath(), getPath()).getPath();
}
/**
* Get the Server's Executable String

View File

@ -3,13 +3,14 @@ package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import java.util.*;
import java.util.LinkedList;
import java.util.UUID;
/**
* API-Safe SubServer Layout Class
*/
public abstract class SubServerController {
private final SubServerContainer control;
private final SubServerImpl control;
/**
* Creates a SubServer
@ -22,138 +23,149 @@ public abstract class SubServerController {
* @throws InvalidServerException
*/
public SubServerController(Host host, String name, int port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
control = new SubServerContainer(host, name, port, motd, hidden, restricted) {
@Override
public boolean start() {
if (SubServerController.this.start()) {
started = false;
return true;
} else return false;
}
SubServerImpl control;
try {
control = new ControlledSubServer(host, name, port, motd, hidden, restricted);
} catch (NoSuchMethodError e) {
control = new ControlledSubServer(host, name, (Integer) port, motd, hidden, restricted);
}
this.control = control;
}
@Override
public boolean start(UUID player) {
if (SubServerController.this.start(player)) {
started = false;
return true;
} else return false;
}
private final class ControlledSubServer extends SubServerImpl {
public ControlledSubServer(Host host, String name, int port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
}
@Override
public boolean stop() {
return SubServerController.this.stop();
}
public ControlledSubServer(Host host, String name, Integer port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(host, name, port, motd, hidden, restricted);
}
@Override
public boolean stop(UUID player) {
return SubServerController.this.stop(player);
}
@Override
public boolean start() {
if (SubServerController.this.start()) {
started = false;
return true;
} else return false;
}
@Override
public boolean terminate() {
return SubServerController.this.terminate();
}
@Override
public boolean start(UUID player) {
if (SubServerController.this.start(player)) {
started = false;
return true;
} else return false;
}
@Override
public boolean terminate(UUID player) {
return SubServerController.this.terminate(player);
}
@Override
public boolean stop() {
return SubServerController.this.stop();
}
@Override
public boolean command(String command) {
return SubServerController.this.command(command);
}
@Override
public boolean stop(UUID player) {
return SubServerController.this.stop(player);
}
@Override
public boolean command(UUID player, String command) {
return SubServerController.this.command(player, command);
}
@Override
public boolean terminate() {
return SubServerController.this.terminate();
}
@Override
public int permaEdit(ObjectMap<String> edit) {
return SubServerController.this.edit(edit);
}
@Override
public boolean terminate(UUID player) {
return SubServerController.this.terminate(player);
}
@Override
public int permaEdit(UUID player, ObjectMap<String> edit) {
return SubServerController.this.edit(player, edit);
}
@Override
public boolean command(String command) {
return SubServerController.this.command(command);
}
@Override
public void waitFor() throws InterruptedException {
SubServerController.this.waitFor();
}
@Override
public boolean command(UUID player, String command) {
return SubServerController.this.command(player, command);
}
@Override
public boolean isRunning() {
return SubServerController.this.isRunning();
}
@Override
public int edit(UUID player, ObjectMap<String> edit, boolean perma) {
return SubServerController.this.edit(player, edit, perma);
}
@Override
public Host getHost() {
return SubServerController.this.getHost();
}
@Override
public void waitFor() throws InterruptedException {
SubServerController.this.waitFor();
}
@Override
public boolean isEnabled() {
return SubServerController.this.isEnabled();
}
@Override
public boolean isRunning() {
return SubServerController.this.isRunning();
}
@Override
public void setEnabled(boolean value) {
SubServerController.this.setEnabled(value);
}
@Override
public Host getHost() {
return SubServerController.this.getHost();
}
@Override
public boolean isLogging() {
return SubServerController.this.isLogging();
}
@Override
public boolean isEnabled() {
return SubServerController.this.isEnabled();
}
@Override
public void setLogging(boolean value) {
SubServerController.this.setLogging(value);
}
@Override
public void setEnabled(boolean value) {
SubServerController.this.setEnabled(value);
}
@Override
public SubLogger getLogger() {
return SubServerController.this.getLogger();
}
@Override
public boolean isLogging() {
return SubServerController.this.isLogging();
}
@Override
public LinkedList<LoggedCommand> getCommandHistory() {
return SubServerController.this.getCommandHistory();
}
@Override
public void setLogging(boolean value) {
SubServerController.this.setLogging(value);
}
@Override
public String getPath() {
return SubServerController.this.getPath();
}
@Override
public SubLogger getLogger() {
return SubServerController.this.getLogger();
}
@Override
public String getExecutable() {
return SubServerController.this.getExecutable();
}
@Override
public LinkedList<LoggedCommand> getCommandHistory() {
return SubServerController.this.getCommandHistory();
}
@Override
public String getStopCommand() {
return SubServerController.this.getStopCommand();
}
@Override
public String getPath() {
return SubServerController.this.getPath();
}
@Override
public void setStopCommand(String value) {
SubServerController.this.setStopCommand(value);
}
@Override
public String getExecutable() {
return SubServerController.this.getExecutable();
}
@Override
public StopAction getStopAction() {
return SubServerController.this.getStopAction();
}
@Override
public String getStopCommand() {
return SubServerController.this.getStopCommand();
}
@Override
public void setStopAction(StopAction action) {
SubServerController.this.setStopAction(action);
}
};
@Override
public void setStopCommand(String value) {
SubServerController.this.setStopCommand(value);
}
@Override
public StopAction getStopAction() {
return SubServerController.this.getStopAction();
}
@Override
public void setStopAction(StopAction action) {
SubServerController.this.setStopAction(action);
}
}
/**
@ -219,7 +231,7 @@ public abstract class SubServerController {
/**
* Commands the Server
*
* @param player Player who Commanded
* @param player Player who's Commanding
* @param command Command to Send
* @return Success Status
*/
@ -240,19 +252,10 @@ public abstract class SubServerController {
*
* @param player Player Editing
* @param edit Edits
* @param perma Saves Changes
* @return Success Status
*/
public int edit(UUID player, ObjectMap<String> edit) {
return -1;
}
/**
* Edits the Server
*
* @param edit Edits
* @return Success Status
*/
public int edit(ObjectMap<String> edit) {
protected int edit(UUID player, ObjectMap<String> edit, boolean perma) {
return -1;
}

View File

@ -1,23 +1,28 @@
package net.ME1312.SubServers.Bungee.Host;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Bungee.Event.SubEditServerEvent;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.SubServers.Bungee.SubAPI;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.*;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
/**
* SubServer Layout Class
*/
public abstract class SubServerContainer extends ServerContainer implements SubServer {
private List<NamedContainer<String, String>> incompatibilities = new ArrayList<NamedContainer<String, String>>();
private String template = null;
protected boolean started;
private boolean updating;
public abstract class SubServerImpl extends ServerImpl implements SubServer {
protected static final Pattern DISALLOWED_COMMANDS = Pattern.compile("^/?(?:[^\\s]+:)?sub(?:servers?)?(?:\\s|$)", Pattern.CASE_INSENSITIVE & Pattern.UNICODE_CASE);
private List<Pair<String, String>> incompatibilities = new ArrayList<Pair<String, String>>();
private SubCreator.ServerTemplate templateV = null;
private String templateS = null;
protected boolean registered, started, stopping, updating;
/**
* Creates a SubServer
@ -26,68 +31,101 @@ public abstract class SubServerContainer extends ServerContainer implements SubS
* @param name Server Name
* @param port Port Number
* @param motd Server MOTD
* @param restricted Players will need a permission to join if true
* @param hidden Hidden Status
* @param restricted Restricted Status
*
* @see ServerImpl#ServerImpl(String, SocketAddress, String, boolean, boolean) Super Method 2
* @throws InvalidServerException
*/
public SubServerContainer(Host host, String name, int port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
protected SubServerImpl(Host host, String name, int port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(name, (SocketAddress) new InetSocketAddress(host.getAddress().getHostAddress(), port), motd, hidden, restricted);
}
/**
* Creates a SubServer
*
* @param host Host
* @param name Server Name
* @param port Port Number
* @param motd Server MOTD
* @param hidden Hidden Status
* @param restricted Restricted Status
*
* @see ServerImpl#ServerImpl(String, InetSocketAddress, String, boolean, boolean) Super Method 1
* @throws InvalidServerException
*/
protected SubServerImpl(Host host, String name, Integer port, String motd, boolean hidden, boolean restricted) throws InvalidServerException {
super(name, new InetSocketAddress(host.getAddress().getHostAddress(), port), motd, hidden, restricted);
}
@Override
public boolean start() {
return start(null);
public int edit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, false);
}
public int permaEdit(UUID player, ObjectMap<String> edit) {
return edit(player, edit, true);
}
/**
* Edits the Server
*
* @param player Player Editing
* @param edit Edits
* @param perma Saves Changes
* @return Success Status
*/
protected int edit(UUID player, ObjectMap<String> edit, boolean perma) {
return -1;
}
@Override
public boolean stop() {
return stop(null);
}
@Override
public boolean terminate() {
return terminate(null);
}
@Override
public boolean command(String command) {
return command(null, command);
}
@Override
public int permaEdit(ObjectMap<String> edit) {
return permaEdit(null, edit);
protected final boolean isRegistered() {
return registered;
}
@Override
public boolean isAvailable() {
return !updating && getHost().isAvailable();
return registered && !updating && getHost().isAvailable();
}
@Override
public boolean isOnline() {
return isRunning() && started;
}
@Override
public boolean isStopping() {
return isRunning() && stopping;
}
@Override
public void setTemplate(String template) {
this.templateV = null;
this.templateS = template;
}
@Override
public void setTemplate(SubCreator.ServerTemplate template) {
SubAPI.getInstance().getInternals().getPluginManager().callEvent(new SubEditServerEvent(null, this, new NamedContainer<String, Object>("template", (template != null)?template.getName():null), false));
this.template = (template != null)?template.getName():null;
this.templateV = template;
this.templateS = (template != null)?template.getName():null;
}
@Override
public SubCreator.ServerTemplate getTemplate() {
if (template != null && getHost().getCreator().getTemplates().keySet().contains(template.toLowerCase())) {
return getHost().getCreator().getTemplate(template.toLowerCase());
if (templateV != null) {
return templateV;
} else if (templateS != null && getHost().getCreator().getTemplates().containsKey(templateS.toLowerCase())) {
return getHost().getCreator().getTemplate(templateS.toLowerCase());
} else {
return null;
}
}
@Override
public String getFullPath() {
return new File(getHost().getPath(), getPath()).getPath();
}
@Override
public void toggleCompatibility(SubServer... server) {
for (SubServer s : server) {
if (!equals(s)) {
NamedContainer<String, String> info = new NamedContainer<String, String>(s.getHost().getName(), s.getName());
Pair<String, String> info = new ContainedPair<String, String>(s.getHost().getName(), s.getName());
if (isCompatible(s)) {
incompatibilities.add(info);
if (s.isCompatible(this)) toggleCompatibility(this);
@ -101,17 +139,17 @@ public abstract class SubServerContainer extends ServerContainer implements SubS
@Override
public boolean isCompatible(SubServer server) {
return !incompatibilities.contains(new NamedContainer<String, String>(server.getHost().getName(), server.getName()));
return !incompatibilities.contains(new ContainedPair<String, String>(server.getHost().getName(), server.getName()));
}
@Override
public List<SubServer> getIncompatibilities() {
List<SubServer> servers = new ArrayList<SubServer>();
List<NamedContainer<String, String>> temp = new ArrayList<NamedContainer<String, String>>();
List<Pair<String, String>> temp = new ArrayList<Pair<String, String>>();
temp.addAll(incompatibilities);
for (NamedContainer<String, String> info : temp) {
for (Pair<String, String> info : temp) {
try {
SubServer server = SubAPI.getInstance().getHost(info.name()).getSubServer(info.get());
SubServer server = SubAPI.getInstance().getHost(info.key()).getSubServer(info.value());
if (server == null) throw new NullPointerException();
servers.add(server);
} catch (Throwable e) {
@ -130,7 +168,12 @@ public abstract class SubServerContainer extends ServerContainer implements SubS
return servers;
}
@SuppressWarnings({"deprecation", "unchecked"})
@Override
public boolean equals(Object obj) {
return obj instanceof SubServerImpl && super.equals(obj);
}
@SuppressWarnings("deprecation")
@Override
public ObjectMap<String> forSubData() {
ObjectMap<String> sinfo = super.forSubData();
@ -144,6 +187,8 @@ public abstract class SubServerContainer extends ServerContainer implements SubS
sinfo.set("dir", getPath());
sinfo.set("exec", getExecutable());
sinfo.set("running", isRunning());
sinfo.set("online", isOnline());
sinfo.set("stopping", isStopping());
sinfo.set("stop-cmd", getStopCommand());
sinfo.set("stop-action", getStopAction().toString());
sinfo.set("auto-run", SubAPI.getInstance().getInternals().servers.get().getMap("Servers").getMap(getName(), new ObjectMap<String>()).getBoolean("Run-On-Launch", false));

View File

@ -1,14 +1,12 @@
package net.ME1312.SubServers.Bungee;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.Compatibility.GalaxiInfo;
import net.ME1312.Galaxi.Library.Platform;
import net.ME1312.Galaxi.Library.Try;
import java.security.Security;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Logger;
/**
* SubServers/BungeeCord Launch Class
@ -23,9 +21,11 @@ public final class Launch {
*/
@SuppressWarnings({"deprecation", "unchecked"})
public static void main(String[] args) throws Exception {
System.setProperty("jdk.lang.Process.allowAmbiguousCommands", "true");
System.setProperty("jdk.util.jar.enableMultiRelease", "force");
System.setProperty("apple.laf.useScreenMenuBar", "true");
if (Util.getDespiteException(() -> Class.forName("net.md_5.bungee.BungeeCord") == null, true)) {
if (Try.all.get(() -> Class.forName("net.md_5.bungee.BungeeCord") == null, true)) {
System.out.println("");
System.out.println("*******************************************");
System.out.println("*** Error: BungeeCord.jar Doesn't Exist ***");
@ -47,90 +47,52 @@ public final class Launch {
parser.accepts("noconsole");
joptsimple.OptionSet options = parser.parse(args);
if(options.has("version") || options.has("v")) {
String osarch;
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
String arch = System.getenv("PROCESSOR_ARCHITECTURE");
String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");
osarch = arch != null && arch.endsWith("64") || wow64Arch != null && wow64Arch.endsWith("64")?"x64":"x86";
} else if (System.getProperty("os.arch").endsWith("86")) {
osarch = "x86";
} else if (System.getProperty("os.arch").endsWith("64")) {
osarch = "x64";
} else {
osarch = System.getProperty("os.arch");
}
String javaarch = null;
switch (System.getProperty("sun.arch.data.model")) {
case "32":
javaarch = "x86";
break;
case "64":
javaarch = "x64";
break;
default:
if (!System.getProperty("sun.arch.data.model").equalsIgnoreCase("unknown"))
javaarch = System.getProperty("sun.arch.data.model");
}
Version galaxi = GalaxiInfo.getVersion();
Version galaxibuild = GalaxiInfo.getSignature();
System.out.println("");
System.out.println(System.getProperty("os.name") + ((!System.getProperty("os.name").toLowerCase().startsWith("windows"))?' ' + System.getProperty("os.version"):"") + ((osarch != null)?" [" + osarch + ']':"") + ',');
System.out.println("Java " + System.getProperty("java.version") + ((javaarch != null)?" [" + javaarch + ']':"") + ',');
if (galaxi != null)
System.out.println("GalaxiEngine v" + galaxi.toExtendedString() + ((galaxibuild != null)?" (" + galaxibuild + ')':"") + ',');
System.out.println("BungeeCord" + net.md_5.bungee.Bootstrap.class.getPackage().getImplementationVersion() + ((patched)?" [Patched]":"") + ',');
System.out.println(Platform.getSystemName() + ' ' + Platform.getSystemVersion() + ((Platform.getSystemBuild() != null)?" (" + Platform.getSystemBuild() + ')':"") + ((!Platform.getSystemArchitecture().equals("unknown"))?" [" + Platform.getSystemArchitecture() + ']':"") + ',');
System.out.println("Java " + Platform.getJavaVersion() + ((!Platform.getJavaArchitecture().equals("unknown"))?" [" + Platform.getJavaArchitecture() + ']':"") + ',');
System.out.println("BungeeCord " + net.md_5.bungee.Bootstrap.class.getPackage().getImplementationVersion() + ((patched)?" [Patched]":"") + ',');
System.out.println("SubServers.Bungee v" + SubProxy.version.toExtendedString() + ((SubProxy.class.getPackage().getSpecificationTitle() != null)?" (" + SubProxy.class.getPackage().getSpecificationTitle() + ')':""));
System.out.println("");
} else {
boolean gb = Util.getDespiteException(() -> Class.forName("net.md_5.bungee.util.GalaxiBungeeInfo").getMethod("get").getReturnType().equals(Class.forName("net.ME1312.Galaxi.Plugin.PluginInfo")), false);
if (gb) {
Util.reflect(net.md_5.bungee.log.LoggingOutputStream.class.getMethod("setLogger", Logger.class, String.class), null,
Util.reflect(net.md_5.bungee.log.BungeeLogger.class.getMethod("get", String.class), null, "SubServers"), "net.ME1312.SubServers.Bungee.");
} else {
System.out.println("");
System.out.println("*******************************************");
System.out.println("*** Warning: this build is unofficial ***");
System.out.println("");
System.out.println("*******************************************");
System.out.println("*** Warning: this build is unofficial ***");
System.out.println("*** ***");
System.out.println("*** Please report all issues to ME1312, ***");
System.out.println("*** NOT the Spigot Team. Thank You! ***");
System.out.println("*******************************************");
try {
if (net.md_5.bungee.BungeeCord.class.getPackage().getSpecificationVersion() != null) {
Date date = (new SimpleDateFormat("yyyyMMdd")).parse(net.md_5.bungee.BungeeCord.class.getPackage().getSpecificationVersion());
Calendar line = Calendar.getInstance();
line.add(Calendar.WEEK_OF_YEAR, -8);
if (date.before(line.getTime())) {
System.out.println("*** Warning: BungeeCord is outdated ***");
System.out.println("*** Please download a new build from: ***");
System.out.println("*** http://ci.md-5.net/job/BungeeCord ***");
System.out.println("*** Errors may arise on older versions! ***");
System.out.println("*******************************************");
}
} else throw new Exception();
} catch (Exception e) {
System.out.println("*** Problem checking BungeeCord version ***");
System.out.println("*** BungeeCord could be outdated. ***");
System.out.println("*** ***");
System.out.println("*** Please report all issues to ME1312, ***");
System.out.println("*** NOT the Spigot Team. Thank You! ***");
System.out.println("*** Errors may arise on older versions! ***");
System.out.println("*******************************************");
try {
if (net.md_5.bungee.BungeeCord.class.getPackage().getSpecificationVersion() != null) {
Date date = (new SimpleDateFormat("yyyyMMdd")).parse(net.md_5.bungee.BungeeCord.class.getPackage().getSpecificationVersion());
Calendar line = Calendar.getInstance();
line.add(3, -4);
if (date.before(line.getTime())) {
System.out.println("*** Warning: BungeeCord is outdated ***");
System.out.println("*** Please download a new build from: ***");
System.out.println("*** http://ci.md-5.net/job/BungeeCord ***");
System.out.println("*** Errors may arise on older versions! ***");
System.out.println("*******************************************");
}
} else throw new Exception();
} catch (Exception e) {
System.out.println("*** Problem checking BungeeCord version ***");
System.out.println("*** BungeeCord could be outdated. ***");
System.out.println("*** ***");
System.out.println("*** Errors may arise on older versions! ***");
System.out.println("*******************************************");
}
System.out.println("");
}
System.out.println("");
SubProxy plugin = new SubProxy(System.out, patched);
net.md_5.bungee.api.ProxyServer.class.getMethod("setInstance", net.md_5.bungee.api.ProxyServer.class).invoke(null, plugin);
if (!gb) plugin.getLogger().info("Enabled " + plugin.getBungeeName() + " version " + plugin.getVersion());
plugin.getLogger().info("Enabled " + plugin.getBungeeName() + " version " + plugin.getVersion());
plugin.start();
if (!options.has("noconsole")) {
if (!gb) try {
if (Util.getDespiteException(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands") != null, false)) { // Waterfall Setup
try {
if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands") != null, false)) { // Waterfall Setup
Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands").invoke(null);
} else if (Util.getDespiteException(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("start") != null, false)) {
} else if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("start") != null, false)) {
Class console = Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole");
console.getMethod("start").invoke(console.getConstructor().newInstance());
} else {

View File

@ -1,55 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.util.List;
/**
* Command Layout Class that implements all possible features (Base Version)
*/
public abstract class CommandX extends Command implements TabExecutor {
/**
* Create a Command
*
* @param name Command Name
*/
public CommandX(String name) {
super(name);
}
/**
* Create a Command
*
* @param name Command Name
* @param permission Command Permission
* @param aliases Command Aliases
*/
public CommandX(String name, String permission, String... aliases) {
super(name, permission, aliases);
}
/**
* Suggest Arguments
*
* @param sender Sender
* @param args Arguments (including the final unfinished one)
* @return An Error Message (if there was one, otherwise null) and a List of Suggestions
*/
public abstract NamedContainer<String, List<String>> suggestArguments(CommandSender sender, String[] args);
/**
* Override the BungeeCord Method of {@link #suggestArguments(CommandSender, String[])}
*
* @param sender Sender
* @param args Arguments (including the final unfinished one)
* @return A Collection of Suggestions
*/
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
return suggestArguments(sender, args).get();
}
}

View File

@ -1,57 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Library.Util;
import net.md_5.bungee.api.plugin.Command;
/**
* Galaxi Command Compatibility Class
*/
public class GalaxiCommand {
/**
* Group similar Commands
*
* @param commands Command Classes
*/
@SafeVarargs
public static void group(Class<? extends Command>... commands) {
Util.isException(() -> Util.reflect(GalaxiCommandWrapper.class.getDeclaredConstructor(Class[].class), (Object) commands));
}
/**
* Set the Description of a Command
*
* @param command Command
* @param value Value
* @return The Command
*/
public static Command description(Command command, String value) {
Util.isException(() -> Util.reflect(Class.forName("net.ME1312.Galaxi.Plugin.Command.Command").getMethod("description", String.class), command, value));
return command;
}
/**
* Set the Help Page for a Command
*
* @param command Command
* @param lines Help Page Lines
* @return The Command
*/
public static Command help(Command command, String... lines) {
Util.isException(() -> Util.reflect(Class.forName("net.ME1312.Galaxi.Plugin.Command.Command").getMethod("help", String[].class), command, (Object) lines));
return command;
}
/**
* Set the Usage of a Command
*
* @param command Command
* @param args Argument Placeholders
* @return The Command
*/
public static Command usage(Command command, String... args) {
Util.isException(() -> Util.reflect(Class.forName("net.ME1312.Galaxi.Plugin.Command.Command").getMethod("usage", String[].class), command, (Object) args));
return command;
}
}

View File

@ -1,75 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Galaxi;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Plugin.Command.Command;
import net.ME1312.Galaxi.Plugin.Command.CommandSender;
import net.ME1312.Galaxi.Plugin.Command.CompletionHandler;
import net.ME1312.Galaxi.Plugin.PluginManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
class GalaxiCommandWrapper extends Command implements CompletionHandler {
private HashMap<String, Command> forwards = new HashMap<String, Command>();
private Command data;
@SafeVarargs
GalaxiCommandWrapper(Class<? extends Command>... commands) {
super(Galaxi.getInstance().getAppInfo());
Map<String, Command> registered = Util.getDespiteException(() -> Util.reflect(PluginManager.class.getDeclaredField("commands"), Galaxi.getInstance().getPluginManager()), null);
ArrayList<String> tmp = new ArrayList<String>();
tmp.addAll(registered.keySet());
for (String alias : tmp) {
Command command = registered.get(alias);
for (Class<? extends Command> type : commands) {
if (type.isInstance(command)) {
forwards.put(alias, command);
if (data == null) data = command;
registered.remove(alias);
break;
}
}
}
register(forwards.keySet().toArray(new String[0]));
}
@Override
public void command(CommandSender sender, String label, String[] args) {
if (forwards.keySet().contains(label.toLowerCase())) {
forwards.get(label.toLowerCase()).command(sender, label, args);
} else {
throw new IllegalStateException("Command label not recognised in group: " + forwards.keySet());
}
}
@Override
public String[] complete(CommandSender sender, String label, String[] args) {
if (forwards.keySet().contains(label.toLowerCase())) {
Command command = forwards.get(label.toLowerCase());
if (command.autocomplete() != null) {
return command.autocomplete().complete(sender, label, args);
} else return new String[0];
} else {
throw new IllegalStateException("Command label not recognised in group: " + forwards.keySet());
}
}
@Override
public String description() {
return (data == null)?super.description():data.description();
}
@Override
public String[] help() {
return (data == null)?super.help():data.help();
}
@Override
public String[] usage() {
return (data == null)?super.usage():data.usage();
}
}

View File

@ -1,39 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Event.ConsoleInputEvent;
import net.ME1312.Galaxi.Galaxi;
import net.ME1312.Galaxi.Library.Event.ListenerOrder;
import net.ME1312.Galaxi.Library.Event.Subscribe;
import net.ME1312.SubServers.Bungee.SubProxy;
/**
* Galaxi Event Listener Class
*/
public class GalaxiEventListener {
private SubProxy plugin;
/**
* Create & Register a Galaxi Event Listener
*
* @param plugin Plugin
*/
public GalaxiEventListener(SubProxy plugin) throws Throwable {
this.plugin = plugin;
Galaxi.getInstance().getPluginManager().registerListeners(Galaxi.getInstance().getAppInfo(), this);
plugin.canSudo = true;
}
@Subscribe(order = ListenerOrder.FIRST, override = true)
public void sudo(ConsoleInputEvent e) {
if (plugin.sudo != null) {
e.setCancelled(true);
if (e.getInput().equalsIgnoreCase("exit")) {
plugin.sudo = null;
Logger.get("SubServers").info("Reverting to the BungeeCord Console");
} else {
plugin.sudo.command(e.getInput());
}
}
}
}

View File

@ -1,47 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import java.lang.annotation.Annotation;
import java.util.jar.Manifest;
/**
* Galaxi Info Class
*/
public class GalaxiInfo {
private GalaxiInfo() {}
@SuppressWarnings("unchecked")
private static <A extends Annotation> Class<A> asAnnotation(Class<?> clazz) {
return (Class<A>) clazz;
}
/**
* Get the Galaxi Version
*
* @return Galaxi Version
*/
public static Version getVersion() {
return Util.getDespiteException(() -> Version.fromString((String) Class.forName("net.ME1312.Galaxi.Plugin.App").getMethod("version").invoke(
Class.forName("net.ME1312.Galaxi.Engine.GalaxiEngine").getAnnotation(asAnnotation(Class.forName("net.ME1312.Galaxi.Plugin.App"))))), null);
}
/**
* Get the Galaxi Build Signature
*
* @return Galaxi Build Signature
*/
public static Version getSignature() {
try {
Manifest manifest = new Manifest(Class.forName("net.ME1312.Galaxi.Engine.GalaxiEngine").getResourceAsStream("/META-INF/GalaxiEngine.MF"));
if (manifest.getMainAttributes().getValue("Implementation-Version") != null && manifest.getMainAttributes().getValue("Implementation-Version").length() > 0) {
return new Version(manifest.getMainAttributes().getValue("Implementation-Version"));
} else {
return null;
}
} catch (Throwable e) {
return null;
}
}
}

View File

@ -1,13 +1,19 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import com.google.common.io.Resources;
import net.ME1312.Galaxi.Library.UniversalFile;
import net.ME1312.SubServers.Bungee.SubAPI;
import com.google.common.io.Resources;
import net.md_5.bungee.api.ProxyServer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Logger;
import static java.util.logging.Level.SEVERE;
/**
* JNA Library Loader Class
@ -27,12 +33,13 @@ public class JNA {
public static ClassLoader get() {
if (JNA == null) {
boolean announced = false;
UniversalFile library = new UniversalFile(SubAPI.getInstance().getInternals().dir, "SubServers:Cache:Libraries");
UniversalFile jna = new UniversalFile(library, "jna-" + JNA_VERSION + ".jar");
Logger log = ProxyServer.getInstance().getLogger();
File library = new File(SubAPI.getInstance().getInternals().dir, "SubServers/Cache/Libraries");
File jna = new File(library, "jna-" + JNA_VERSION + ".jar");
jna.getParentFile().mkdirs();
if (!jna.exists()) {
announced = true;
System.out.println(">> Downloading JNA Library v" + JNA_VERSION);
log.info(">> Downloading JNA v" + JNA_VERSION);
try (FileOutputStream fin = new FileOutputStream(jna)) {
Resources.copy(new URL(JNA_DOWNLOAD.replace("$1", "jna")), fin);
} catch (Throwable e) {
@ -40,10 +47,10 @@ public class JNA {
e.printStackTrace();
}
}
UniversalFile platform = new UniversalFile(library, "jna-platform-" + JNA_VERSION + ".jar");
File platform = new File(library, "jna-platform-" + JNA_VERSION + ".jar");
platform.getParentFile().mkdirs();
if (!platform.exists()) {
if (!announced) System.out.println(">> Downloading JNA Library v" + JNA_VERSION);
if (!announced) log.info(">> Downloading JNA platform v" + JNA_VERSION);
announced = true;
try (FileOutputStream fin = new FileOutputStream(platform)) {
Resources.copy(new URL(JNA_DOWNLOAD.replace("$1", "jna-platform")), fin);
@ -53,16 +60,14 @@ public class JNA {
}
}
if (jna.exists() && platform.exists()) {
if (announced) System.out.println(">> Loading JNA Library");
if (announced) log.info(">> JNA download complete");
try {
JNA = new URLClassLoader(new URL[]{jna.toURI().toURL(), platform.toURI().toURL()});
} catch (Throwable e) {
System.out.println(">> Could not load JNA Library:");
e.printStackTrace();
log.log(SEVERE, ">> Couldn't load JNA:", e);
}
} else {
System.out.println(">> Could not load JNA Library:");
new FileNotFoundException().printStackTrace();
log.log(SEVERE, ">> Couldn't load JNA:", new FileNotFoundException());
}
}
return JNA;

View File

@ -0,0 +1,51 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.util.CaseInsensitiveMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* Legacy Server Map Translation Class
*/
public class LegacyServerMap extends CaseInsensitiveMap<ServerInfo> {
public LegacyServerMap() {
}
public LegacyServerMap(Map<String, ServerInfo> map) {
for (Entry<String, ServerInfo> e : map.entrySet()) super.put(e.getKey(), e.getValue());
}
@SuppressWarnings("deprecation")
@Override
public ServerInfo put(String key, ServerInfo value) {
if (value == null) throw new NullPointerException();
ServerInfo n = SubAPI.getInstance().addServer(value.getName(), value.getAddress().getAddress(), value.getAddress().getPort(), value.getMotd(), false, value.isRestricted()),
s = getOrDefault(key, null);
if (n != null)
super.put(n.getName(), n);
return s;
}
@Override
public ServerInfo remove(Object key) {
if (key instanceof String) {
ServerInfo s = getOrDefault(key, null);
if (s != null) {
if (SubAPI.getInstance().removeServer((String) key))
super.remove(key);
return s;
} else return null;
} else return null;
}
@Override
public void clear() {
// Disallow removing all servers
}
}

View File

@ -1,56 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.HashMap;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
/**
* Logger Compatibility Class
*/
public class Logger {
private static final HashMap<String, java.util.logging.Logger> existing = new HashMap<String, java.util.logging.Logger>();
private static SubProxy plugin;
/**
* Get a logger
*
* @param prefix Prefix
* @return Logger
*/
@SuppressWarnings("deprecation")
public static java.util.logging.Logger get(String prefix) {
if (!existing.keySet().contains(prefix)) {
java.util.logging.Logger log = Util.getDespiteException(() -> Util.reflect(Class.forName("net.ME1312.Galaxi.Library.Log.Logger").getDeclaredMethod("toPrimitive"),
Util.reflect(Class.forName("net.ME1312.Galaxi.Library.Log.Logger").getConstructor(String.class), prefix)), null);
if (log == null) {
log = java.util.logging.Logger.getAnonymousLogger();
log.setUseParentHandlers(false);
log.addHandler(new Handler() {
private boolean open = true;
@Override
public void publish(LogRecord record) {
if (open)
plugin.getLogger().log(record.getLevel(), prefix + " > " + record.getMessage(), record.getParameters());
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
open = false;
}
});
}
existing.put(prefix, log);
}
return existing.get(prefix);
}
}

View File

@ -1,9 +1,9 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility;
public class Plugin extends net.md_5.bungee.api.plugin.Plugin {
public final class Plugin extends net.md_5.bungee.api.plugin.Plugin {
@Override
public void onEnable() {
throw new IllegalStateException("SubServers.Bungee does not run as a plugin, but a wrapper. For more information on how to install, visit this page: https://github.com/ME1312/SubServers-2/wiki/Install");
@Deprecated
public Plugin() {
throw new IllegalStateException("SubServers.Bungee does not run as a plugin, but a wrapper. For more information on how to install, please visit this page: https://github.com/ME1312/SubServers-2/wiki/Installation");
}
}

View File

@ -1,74 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Compatibility.mc1_13;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.md_5.bungee.api.CommandSender;
import java.util.LinkedList;
import java.util.List;
/**
* Command Layout Class that implements all possible features (1.13 Version)
*/
public class CommandX extends net.ME1312.SubServers.Bungee.Library.Compatibility.CommandX/* implements TabValidator */ {
public final net.ME1312.SubServers.Bungee.Library.Compatibility.CommandX command;
/**
* Create a Command
*
* @param other CommandX from previous version
*/
public CommandX(net.ME1312.SubServers.Bungee.Library.Compatibility.CommandX other) {
super(other.getName());
command = other;
}
/**
* Override BungeeCord Method for the previously used one
*
* @param sender Sender
* @param args Arguments
*/
@Override
public void execute(CommandSender sender, String[] args) {
command.execute(sender, args);
}
@Override
public NamedContainer<String, List<String>> suggestArguments(CommandSender sender, String[] args) {
return command.suggestArguments(sender, args);
}
/**
* Validate a Command (Override for custom)
*
* @param sender Sender
* @param command Command to validate
* @return NamedContainer with a String error message and a Integer that represents where the command was deemed invalid
*/
public NamedContainer<String, Integer> validateCommand(CommandSender sender, String command) {
List<NamedContainer<String, Integer>> split = new LinkedList<NamedContainer<String, Integer>>();
String cmd = command;
int i;
while ((i = cmd.indexOf((int) ' ')) < 0) {
i++;
String arg = cmd.substring(i);
split.add(new NamedContainer<>(arg.contains(" ")?arg.substring(0, arg.indexOf((int) ' ')):arg, i));
cmd = arg;
}
List<String> args = new LinkedList<String>();
NamedContainer<String, Integer> response = null;
i = 0;
for (NamedContainer<String, Integer> arg : split) {
if (i > 0) {
args.add(arg.name());
NamedContainer<String, List<String>> suggestions = suggestArguments(sender, args.toArray(new String[args.size() - 1]));
if (suggestions.name() != null) response = new NamedContainer<>(suggestions.name(), arg.get());
}
i++;
}
return response;
}
// TODO Override the original validator method
}

View File

@ -0,0 +1,562 @@
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Config.YAMLSection;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.SubAPI;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* SubServers Configuration Updater
*/
public class ConfigUpdater {
private static final Version UNSIGNED = new Version(new SimpleDateFormat("yy'w'ww'zz'").format(Calendar.getInstance().getTime()));
/**
* Update SubServers' config.yml
*
* @param file File to bring up-to-date
*/
public static void updateConfig(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
YAMLSection hosts = new YAMLSection();
YAMLSection host = new YAMLSection();
host.set("Enabled", true);
host.set("Display", "Default");
hosts.set("~", host);
updated.set("Hosts", hosts);
i++;
Logger.get("SubServers").info("Created ./SubServers/config.yml");
} else {
if (was.compareTo(new Version("19w17a")) <= 0) {
if (existing.getMap("Settings", new YAMLSection()).contains("Log-Creator")) for (String name : existing.getMap("Hosts", new YAMLSection()).getKeys())
updated.getMap("Hosts").getMap(name).safeSet("Log-Creator", existing.getMap("Settings").getBoolean("Log-Creator"));
if (existing.getMap("Settings", new YAMLSection()).contains("SubData") && !existing.getMap("Settings", new YAMLSection()).getMap("SubData").contains("Encryption"))
updated.getMap("Settings").getMap("SubData").set("Encryption", "NONE");
if (existing.contains("Servers")) {
YAMLConfig sc = new YAMLConfig(new File(file.getParentFile(), "servers.yml"));
YAMLSection settings = new YAMLSection();
settings.set("Version", was.toString());
settings.set("Run-On-Launch-Timeout", (existing.getMap("Settings", new YAMLSection()).contains("Run-On-Launch-Timeout"))?existing.getMap("Settings").getInt("Run-On-Launch-Timeout"):0);
sc.get().safeSet("Settings", settings);
sc.get().safeSet("Servers", new YAMLSection());
sc.get().getMap("Servers").safeSetAll(existing.getMap("Servers"));
Logger.get("SubServers").info("Created ./SubServers/servers.yml (using existing data)");
sc.save();
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("19w35c")) <= 0) {
if (existing.getMap("Settings", new YAMLSection()).contains("SubData")) {
LinkedList<String> whitelist = new LinkedList<>();
LinkedList<String> newWhitelist = new LinkedList<>();
whitelist.addAll(existing.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getStringList("Allowed-Connections", Collections.emptyList()));
whitelist.addAll(existing.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getStringList("Whitelist", Collections.emptyList()));
boolean warnPls = false;
for (String address : whitelist) {
Matcher regAddress = Pattern.compile("^(\\d{1,3}|%)\\.(\\d{1,3}|%)\\.(\\d{1,3}|%)\\.(\\d{1,3}|%)$").matcher(address);
if (regAddress.find()) {
StringBuilder newAddress = new StringBuilder();
int subnet = -1;
boolean warn = false;
for (int o = 1; o <= 4; o++) {
if (o > 1) newAddress.append('.');
if (subnet == -1) {
if (!regAddress.group(o).equals("%")) {
newAddress.append(regAddress.group(o));
} else {
subnet = 8 * (o - 1);
newAddress.append('0');
}
} else {
if (!regAddress.group(o).equals("%")) warn = warnPls = true;
newAddress.append('0');
}
}
if (subnet < 0) subnet = 32;
if (warn) Logger.get("SubServers").warning("Updating non-standard mask: " + address);
newAddress.append('/');
newAddress.append(subnet);
newWhitelist.add(newAddress.toString());
}
}
updated.getMap("Settings").getMap("SubData").set("Whitelist", newWhitelist);
if (warnPls) Logger.get("SubServers").warning("Non-standard masks have been updated. This may expose SubData to unintended networks!");
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("20w08d")) <= 0) {
if (existing.contains("Hosts")) {
for (String name : existing.getMap("Hosts", new YAMLSection()).getKeys()) {
if (existing.getMap("Hosts").getMap(name).getString("Driver", "BUILT_IN").replace('-', '_').replace(' ', '_').equalsIgnoreCase("BUILT_IN"))
updated.getMap("Hosts").getMap(name).set("Driver", "VIRTUAL");
}
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("20w34a")) <= 0) {
if (existing.getMap("Settings", new YAMLSection()).contains("Smart-Fallback") && existing.getMap("Settings").isBoolean("Smart-Fallback")) {
YAMLSection smart_fallback = new YAMLSection();
smart_fallback.set("Enabled", existing.getMap("Settings").getBoolean("Smart-Fallback"));
smart_fallback.set("Fallback", existing.getMap("Settings").getBoolean("Smart-Fallback"));
updated.getMap("Settings").set("Smart-Fallback", smart_fallback);
}
if (existing.getMap("Settings", new YAMLSection()).contains("Override-Bungee-Commands") && existing.getMap("Settings").isBoolean("Override-Bungee-Commands")) {
List<String> overrides = new LinkedList<>();
if (!existing.getMap("Settings").getBoolean("Override-Bungee-Commands")) {
overrides.add("/server");
overrides.add("/glist");
}
updated.getMap("Settings").set("Disabled-Overrides", overrides);
}
existing = updated.clone();
i++;
} else if (was.compareTo(new Version("21w27b")) <= 0) {
//existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// existing = updated.clone();
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/config.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
if (updated.getMap("Settings", new YAMLSection()).contains("RPEC-Check-Interval")) settings.set("RPEC-Check-Interval", updated.getMap("Settings").getString("RPEC-Check-Interval"));
settings.set("Strict-Server-Linking", updated.getMap("Settings", new YAMLSection()).getBoolean("Strict-Server-Linking", true));
settings.set("Disabled-Overrides", updated.getMap("Settings", new YAMLSection()).getStringList("Disabled-Overrides", Collections.emptyList()));
YAMLSection smart_fallback = new YAMLSection();
smart_fallback.set("Enabled", updated.getMap("Settings", new YAMLSection()).getMap("Smart-Fallback", new YAMLSection()).getBoolean("Enabled", true));
smart_fallback.set("Fallback", updated.getMap("Settings", new YAMLSection()).getMap("Smart-Fallback", new YAMLSection()).getBoolean("Fallback", true));
smart_fallback.set("Reconnect", updated.getMap("Settings", new YAMLSection()).getMap("Smart-Fallback", new YAMLSection()).getBoolean("Reconnect", false));
smart_fallback.set("DNS-Forward", updated.getMap("Settings", new YAMLSection()).getMap("Smart-Fallback", new YAMLSection()).getBoolean("DNS-Forward", false));
settings.set("Smart-Fallback", smart_fallback);
YAMLSection upnp = new YAMLSection();
upnp.set("Forward-Proxy", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-Proxy", true));
upnp.set("Forward-SubData", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-SubData", false));
upnp.set("Forward-Servers", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-Servers", false));
settings.set("UPnP", upnp);
YAMLSection subdata = new YAMLSection();
subdata.set("Address", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Address", "127.0.0.1:4391"));
if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Password")) subdata.set("Password", updated.getMap("Settings").getMap("SubData").getString("Password"));
subdata.set("Encryption", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Encryption", "RSA/AES"));
subdata.set("Whitelist", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getStringList("Whitelist", Collections.emptyList()));
settings.set("SubData", subdata);
rewritten.set("Settings", settings);
YAMLSection hosts = new YAMLSection();
for (String name : updated.getMap("Hosts", new YAMLSection()).getKeys()) {
YAMLSection host = new YAMLSection();
host.set("Enabled", updated.getMap("Hosts").getMap(name).getBoolean("Enabled", false));
host.set("Display", updated.getMap("Hosts").getMap(name).getString("Display", ""));
host.set("Driver", updated.getMap("Hosts").getMap(name).getString("Driver", "VIRTUAL"));
host.set("Address", updated.getMap("Hosts").getMap(name).getString("Address", "127.0.0.1"));
host.set("Port-Range", updated.getMap("Hosts").getMap(name).getString("Port-Range", "25500-25559"));
host.set("Directory", updated.getMap("Hosts").getMap(name).getString("Directory", (host.getString("Driver").equalsIgnoreCase("VIRTUAL"))?"./SubServers/Servers":"./Servers"));
host.set("Git-Bash", updated.getMap("Hosts").getMap(name).getString("Git-Bash", "%ProgramFiles%\\Git"));
host.set("Log-Creator", updated.getMap("Hosts").getMap(name).getBoolean("Log-Creator", true));
if (updated.getMap("Hosts").getMap(name).contains("Extra")) host.set("Extra", updated.getMap("Hosts").getMap(name).getMap("Extra"));
hosts.set(name, host);
}
rewritten.set("Hosts", hosts);
config.set(rewritten);
config.save();
}
}
/**
* Update SubServers' servers.yml
*
* @param file File to bring up-to-date
*/
public static void updateServers(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
YAMLSection servers = new YAMLSection();
servers.set("Example", new YAMLSection());
updated.set("Servers", servers);
i++;
Logger.get("SubServers").info("Created ./SubServers/servers.yml");
} else {
if (was.compareTo(new Version("19w17a")) <= 0) {
if (existing.contains("Servers")) {
for (String name : existing.getMap("Servers", new YAMLSection()).getKeys()) {
if (existing.getMap("Servers").getMap(name).getBoolean("Auto-Restart", true))
updated.getMap("Servers").getMap(name).safeSet("Stop-Action", "RESTART");
if (existing.getMap("Servers").getMap(name).getString("Stop-Action", "NONE").equalsIgnoreCase("DELETE_SERVER"))
updated.getMap("Servers").getMap(name).set("Stop-Action", "RECYCLE_SERVER");
}
}
existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/servers.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
settings.set("Run-On-Launch-Timeout", updated.getMap("Settings", new YAMLSection()).getInt("Run-On-Launch-Timeout", 0));
rewritten.set("Settings", settings);
YAMLSection servers = new YAMLSection();
for (String name : updated.getMap("Servers", new YAMLSection()).getKeys()) {
YAMLSection server = new YAMLSection();
server.set("Enabled", updated.getMap("Servers").getMap(name).getBoolean("Enabled", false));
server.set("Display", updated.getMap("Servers").getMap(name).getString("Display", ""));
server.set("Host", updated.getMap("Servers").getMap(name).getString("Host", "~"));
if (updated.getMap("Servers").getMap(name).contains("Template")) server.set("Template", updated.getMap("Servers").getMap(name).getString("Template"));
server.set("Group", updated.getMap("Servers").getMap(name).getStringList("Groups", Collections.emptyList()));
server.set("Port", updated.getMap("Servers").getMap(name).getInt("Port", 25567));
server.set("Motd", updated.getMap("Servers").getMap(name).getString("Motd", "Some SubServer"));
server.set("Log", updated.getMap("Servers").getMap(name).getBoolean("Log", true));
server.set("Directory", updated.getMap("Servers").getMap(name).getString("Directory", "." + File.separatorChar));
server.set("Executable", updated.getMap("Servers").getMap(name).getString("Executable", "java -Xmx1024M -Djline.terminal=jline.UnsupportedTerminal -jar Spigot.jar"));
server.set("Stop-Command", updated.getMap("Servers").getMap(name).getString("Stop-Command", "stop"));
server.set("Stop-Action", updated.getMap("Servers").getMap(name).getString("Stop-Action", "NONE"));
server.set("Run-On-Launch", updated.getMap("Servers").getMap(name).getBoolean("Run-On-Launch", false));
server.set("Restricted", updated.getMap("Servers").getMap(name).getBoolean("Restricted", false));
server.set("Incompatible", updated.getMap("Servers").getMap(name).getStringList("Incompatible", Collections.emptyList()));
server.set("Hidden", updated.getMap("Servers").getMap(name).getBoolean("Hidden", false));
if (updated.getMap("Servers").getMap(name).contains("Extra")) server.set("Extra", updated.getMap("Servers").getMap(name).getMap("Extra"));
servers.set(name, server);
}
rewritten.set("Servers", servers);
config.set(rewritten);
config.save();
}
}
/**
* Update SubServers' lang.yml
*
* @param file File to bring up-to-date
*/
public static void updateLang(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
i++;
Logger.get("SubServers").info("Created ./SubServers/lang.yml");
} else {
if (was.compareTo(new Version("19w22b")) <= 0) {
if (existing.contains("Lang")) {
updated.getMap("Lang").remove("Interface.Host-Admin.SubServers");
updated.getMap("Lang").remove("Interface.Server-Admin.Command");
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("20w08d")) <= 0) {
if (existing.contains("Lang")) {
LinkedList<String> keys = new LinkedList<>(existing.getMap("Lang").getKeys());
for (String key : keys) if (key.startsWith("Command.")) {
updated.getMap("Lang").remove(key);
}
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("22w07c")) <= 0) {
if (existing.contains("Lang")) {
updated.getMap("Lang").remove("Command.Teleport");
}
existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/lang.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
rewritten.set("Settings", settings);
LinkedHashMap<String, String> def = new LinkedHashMap<String, String>();
def.put("Bungee.Feature.Smart-Fallback", "&6Returning from $str$: &r$msg$");
def.put("Bungee.Feature.Smart-Fallback.Result", "&6You are now on $str$.");
def.put("Bungee.Restricted", "&cYou don't have permission to access this server.");
def.put("Bungee.Ping.Offline", "&6&l[&e&lWarning&6&l] &7Backend server(s) are not running");
def.put("Bungee.Server.Current", "&6You are currently connected to $str$");
def.put("Bungee.Server.Available", "&6You may connect to the following servers at this time:");
def.put("Bungee.Server.List", "&6$str$");
def.put("Bungee.Server.Hover", "$int$ player(s)\\n&oClick to connect to the server");
def.put("Bungee.Server.Divider", "&6, ");
def.put("Bungee.Server.Offline", "&cThe specified server is not currently running.");
def.put("Bungee.Server.Invalid", "&cThe specified server does not exist.");
def.put("Bungee.List.Format", "&a[$str$] &e($int$)&r: ");
def.put("Bungee.List.List", "&f$str$");
def.put("Bungee.List.Divider", "&f, ");
def.put("Bungee.List.Total", "Total players online: $int$");
def.put("Signs.Create", "&aSubServers &2&l\\u00BB&a Server sign activated");
def.put("Signs.Delete", "&aSubServers &2&l\\u00BB&a Server sign removed");
def.put("Signs.Text.Unknown", "&f&oSubServers\\n&3$str$\\n&7Unknown Status\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Signs.Text.Offline", "&c&oSubServers\\n&3$str$\\n&4Offline\\n&7Click to Start");
def.put("Signs.Text.Starting", "&e&oSubServers\\n&3$str$\\n&6Starting\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Signs.Text.Online", "&a&oSubServers\\n&3$str$\\n&2$int$ Online\\n&7Click to Join");
def.put("Signs.Text.Stopping", "&e&oSubServers\\n&3$str$\\n&6Stopping\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Command.Generic.Player-Only", "&cSubServers &4&l\\u00BB&c The console cannot perform this command");
def.put("Command.Generic.Console-Only", "&cSubServers &4&l\\u00BB&c This command is for console use only");
def.put("Command.Generic.Usage", "&7SubServers &8&l\\u00BB&7 Usage: &f$str$");
def.put("Command.Generic.Exception", "&cSubServers &4&l\\u00BB&c An unexpected exception has occurred while parsing this command");
def.put("Command.Generic.Invalid-Subcommand", "&cSubServers &4&l\\u00BB&c Unknown sub-command: &4$str$");
def.put("Command.Generic.Invalid-Permission", "&cSubServers &4&l\\u00BB&c You need &4&n$str$&c to use this command");
def.put("Command.Generic.Invalid-Select-Permission", "&cSubServers &4&l\\u00BB&c You don't have permission to select &4$str$");
def.put("Command.Generic.Unknown-Proxy", "&cSubServers &4&l\\u00BB&c There is no proxy named &4$str$");
def.put("Command.Generic.Unknown-Host", "&cSubServers &4&l\\u00BB&c There is no host named &4$str$");
def.put("Command.Generic.Unknown-Group", "&cSubServers &4&l\\u00BB&c There is no group named &4$str$");
def.put("Command.Generic.Unknown-Server", "&cSubServers &4&l\\u00BB&c There is no server named &4$str$");
def.put("Command.Generic.Unknown-SubServer", "&cSubServers &4&l\\u00BB&c There is no subserver named &4$str$");
def.put("Command.Generic.Unknown-Player", "&cSubServers &4&l\\u00BB&c There is no player named &4$str$");
def.put("Command.Generic.No-Servers-On-Host", "&7SubServers &8&l\\u00BB&7 There are no servers on host &f$str$");
def.put("Command.Generic.No-SubServers-On-Host", "&7SubServers &8&l\\u00BB&7 There are no subservers on host &f$str$");
def.put("Command.Generic.No-Servers-In-Group", "&7SubServers &8&l\\u00BB&7 There are no servers in group &f$str$");
def.put("Command.Generic.No-SubServers-In-Group", "&7SubServers &8&l\\u00BB&7 There are no subservers in group &f$str$");
def.put("Command.Generic.No-Servers-Selected", "&cSubServers &4&l\\u00BB&c No servers were selected");
def.put("Command.Generic.No-SubServers-Selected", "&cSubServers &4&l\\u00BB&c No subservers were selected");
def.put("Command.Help.Header", "&7SubServers &8&l\\u00BB&7 Command Help:");
def.put("Command.Help.Help", " &7Help:&f $str$");
def.put("Command.Help.List", " &7List:&f $str$");
def.put("Command.Help.Version", " &7Version:&f $str$");
def.put("Command.Help.Info", " &7Info:&f $str$");
def.put("Command.Help.Host.Create", " &7Create Server:&f $str$");
def.put("Command.Help.SubServer.Start", " &7Start Server:&f $str$");
def.put("Command.Help.SubServer.Restart", " &7Restart Server:&f $str$");
def.put("Command.Help.SubServer.Stop", " &7Stop Server:&f $str$");
def.put("Command.Help.SubServer.Terminate", " &7Terminate Server:&f $str$");
def.put("Command.Help.SubServer.Command", " &7Command Server:&f $str$");
def.put("Command.Help.SubServer.Update", " &7Update Server:&f $str$");
def.put("Command.Version", "&7SubServers &8&l\\u00BB&7 These are the platforms and versions that are running &f$str$&7:");
def.put("Command.Version.Outdated", "&7$name$ &f$str$ &7is available. You are $int$ version(s) behind.");
def.put("Command.Version.Latest", "&7You are on the latest version.");
def.put("Command.List.Group-Header", "&7SubServers &8&l\\u00BB&7 Group/Server List:");
def.put("Command.List.Host-Header", "&7SubServers &8&l\\u00BB&7 Host/SubServer List:");
def.put("Command.List.Server-Header", "&7SubServers &8&l\\u00BB&7 Server List:");
def.put("Command.List.Proxy-Header", "&7SubServers &8&l\\u00BB&7 Proxy List:");
def.put("Command.List.Header", "&7: ");
def.put("Command.List.Divider", "&7, ");
def.put("Command.List.Empty", "&7(none)");
def.put("Command.Info", "&7SubServers &8&l\\u00BB&7 Info on $str$: &r");
def.put("Command.Info.Unknown", "&cSubServers &4&l\\u00BB&c There is no object with that name");
def.put("Command.Info.Unknown-Type", "&cSubServers &4&l\\u00BB&c There is no object type with that name");
def.put("Command.Info.Unknown-Proxy", "&cSubServers &4&l\\u00BB&c There is no proxy with that name");
def.put("Command.Info.Unknown-Host", "&cSubServers &4&l\\u00BB&c There is no host with that name");
def.put("Command.Info.Unknown-Group", "&cSubServers &4&l\\u00BB&c There is no group with that name");
def.put("Command.Info.Unknown-Server", "&cSubServers &4&l\\u00BB&c There is no server with that name");
def.put("Command.Info.Unknown-Player", "&cSubServers &4&l\\u00BB&c There is no player with that name");
def.put("Command.Info.Format", " -> &7$str$&7: &r");
def.put("Command.Info.List", " - ");
def.put("Command.Start", "&aSubServers &2&l\\u00BB&a Started &2$int$&a subserver(s)");
def.put("Command.Start.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Start.Host-Unavailable", "&cSubServers &4&l\\u00BB&c The host for &4$str$&c is not available");
def.put("Command.Start.Host-Disabled", "&cSubServers &4&l\\u00BB&c The host for &4$str$&c is not enabled");
def.put("Command.Start.Server-Unavailable", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c is not available");
def.put("Command.Start.Server-Disabled", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c is not enabled");
def.put("Command.Start.Server-Incompatible", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c cannot start while incompatible server(s) are running");
def.put("Command.Start.Running", "&7SubServers &8&l\\u00BB&7 &f$int$&7 subserver(s) were already running");
def.put("Command.Restart", "&aSubServers &2&l\\u00BB&a Restarting &2$int$&a subserver(s)");
def.put("Command.Restart.Disappeared", "&cSubServers &4&l\\u00BB&c Could not restart server: Subserver &4$str$&c has disappeared");
def.put("Command.Restart.Host-Unavailable", "&cSubServers &4&l\\u00BB&c Could not restart server: The host for &4$str$&c is no longer available");
def.put("Command.Restart.Host-Disabled", "&cSubServers &4&l\\u00BB&c Could not restart server: The host for &4$str$&c is no longer enabled");
def.put("Command.Restart.Server-Unavailable", "&cSubServers &4&l\\u00BB&c Could not restart server: Subserver &4$str$&c is no longer available");
def.put("Command.Restart.Server-Disabled", "&cSubServers &4&l\\u00BB&c Could not restart server: Subserver &4$str$&c is no longer enabled");
def.put("Command.Restart.Server-Incompatible", "&cSubServers &4&l\\u00BB&c Could not restart server: Subserver &4$str$&c cannot start while incompatible server(s) are running");
def.put("Command.Stop", "&aSubServers &2&l\\u00BB&a Stopping &2$int$&a subserver(s)");
def.put("Command.Stop.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Stop.Not-Running", "&7SubServers &8&l\\u00BB&7 &f$int$&7 subserver(s) were already offline");
def.put("Command.Terminate", "&aSubServers &2&l\\u00BB&a Terminated &2$int$&a subserver(s)");
def.put("Command.Terminate.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Terminate.Not-Running", "&7SubServers &8&l\\u00BB&7 &f$int$&7 subserver(s) were already offline");
def.put("Command.Command", "&aSubServers &2&l\\u00BB&a Sent command to &2$int$&a server(s)");
def.put("Command.Command.Disappeared", "&cSubServers &4&l\\u00BB&c Server &4$str$&c has disappeared");
def.put("Command.Command.No-Command", "&cSubServers &4&l\\u00BB&c No command was entered");
def.put("Command.Command.Not-Running", "&7SubServers &8&l\\u00BB&7 &f$int$&7 server(s) were unavailable");
def.put("Command.Creator", "&aSubServers &2&l\\u00BB&a Creating subserver &2$str$&a");
def.put("Command.Creator.Exists", "&cSubServers &4&l\\u00BB&c There is already a subserver with that name");
def.put("Command.Creator.Unknown-Host", "&cSubServers &4&l\\u00BB&c There is no host with that name");
def.put("Command.Creator.Host-Unavailable", "&cSubServers &4&l\\u00BB&c That host is not available");
def.put("Command.Creator.Host-Disabled", "&cSubServers &4&l\\u00BB&c That host is not enabled");
def.put("Command.Creator.Unknown-Template", "&cSubServers &4&l\\u00BB&c There is no template with that name");
def.put("Command.Creator.Template-Disabled", "&cSubServers &4&l\\u00BB&c That template is not enabled");
def.put("Command.Creator.Template-Invalid", "&cSubServers &4&l\\u00BB&c That template does not support subserver updating");
def.put("Command.Creator.Version-Required", "&cSubServers &4&l\\u00BB&c That template requires a Minecraft version to be specified");
def.put("Command.Creator.Invalid-Port", "&cSubServers &4&l\\u00BB&c Invalid port number");
def.put("Command.Update", "&aSubServers &2&l\\u00BB&a Updating &2$int$&a subserver(s)");
def.put("Command.Update.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Update.Host-Unavailable", "&cSubServers &4&l\\u00BB&c The host for &4$str$&c is not available");
def.put("Command.Update.Host-Disabled", "&cSubServers &4&l\\u00BB&c The host for &4$str$&c is not enabled");
def.put("Command.Update.Server-Unavailable", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c is not available");
def.put("Command.Update.Running", "&cSubServers &4&l\\u00BB&c Cannot update &4$str$&c while it is still running");
def.put("Command.Update.Unknown-Template", "&cSubServers &4&l\\u00BB&c We don't know which template created &4$str$");
def.put("Command.Update.Template-Disabled", "&cSubServers &4&l\\u00BB&c The template that created &4$str$&c is not enabled");
def.put("Command.Update.Template-Invalid", "&cSubServers &4&l\\u00BB&c The template that created &4$str$&c does not support subserver updating");
def.put("Command.Update.Version-Required", "&cSubServers &4&l\\u00BB&c The template that created &4$str$&c requires a Minecraft version to be specified");
def.put("Command.Delete.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Delete.Running", "&cSubServers &4&l\\u00BB&c Cannot delete &4$str$&c while it is still running");
def.put("Command.Delete", "&aSubServers &2&l\\u00BB&a Deleting &2$int$&a subserver(s)");
def.put("Command.Teleport", "&aSubServers &2&l\\u00BB&a Teleporting to &2$str$");
def.put("Command.Teleport.Others", "&aSubServers &2&l\\u00BB&a Teleporting &2$name$&a to &2$str$");
def.put("Command.Teleport.Not-Running", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c is not running");
def.put("Interface.Generic.Back", "&cBack");
def.put("Interface.Generic.Back-Arrow", "&e&l<--");
def.put("Interface.Generic.Next-Arrow", "&e&l-->");
def.put("Interface.Generic.Undo", "&6Undo");
def.put("Interface.Generic.Downloading", "&7SubServers &8&l\\u00BB&7 Downloading:&f $str$");
def.put("Interface.Generic.Downloading.Title", "Downloading...");
def.put("Interface.Generic.Downloading.Title-Color", "&b");
def.put("Interface.Generic.Downloading.Title-Color-Alt", "&3");
def.put("Interface.Generic.Downloading.Response", "&eWaiting for response");
def.put("Interface.Generic.Invalid-Permission", "&4You need &n$str$");
def.put("Interface.Proxy-Menu.Proxy-Player-Count", "&2$int$ Player(s) Online");
def.put("Interface.Proxy-Menu.Proxy-Master", "&8Master Proxy");
def.put("Interface.Proxy-Menu.Proxy-Disconnected", "&4Disconnected");
def.put("Interface.Host-Menu.Title", "Host Menu");
def.put("Interface.Host-Menu.Host-Unavailable", "&4Unavailable");
def.put("Interface.Host-Menu.Host-Disabled", "&4Disabled");
def.put("Interface.Host-Menu.Host-Server-Count", "&9$int$ Server(s)");
def.put("Interface.Host-Menu.No-Hosts", "&c&oThere are No Hosts");
def.put("Interface.Host-Menu.Group-Menu", "&6&lView Servers by Group");
def.put("Interface.Host-Menu.Server-Menu", "&a&lView Servers");
def.put("Interface.Host-Admin.Title", "Host/$str$");
def.put("Interface.Host-Admin.Creator", "&eCreate a SubServer");
def.put("Interface.Host-Admin.SubServers", "&bView SubServers");
def.put("Interface.Host-Admin.Plugins", "&bPlugins...");
def.put("Interface.Host-Creator.Title", "Host/$str$/Create");
def.put("Interface.Host-Creator.Edit-Name", "Change Name");
def.put("Interface.Host-Creator.Edit-Name.Title", "&eSubCreator\\n&6Enter a Name for this Server");
def.put("Interface.Host-Creator.Edit-Name.Message", "&eSubCreator &6&l\\u00BB&e Enter a Name for this Server via Chat");
def.put("Interface.Host-Creator.Edit-Name.Exists", "&cSubCreator &4&l\\u00BB&c There is already a SubServer with that name");
def.put("Interface.Host-Creator.Edit-Name.Exists-Title", "&eSubCreator\\n&cThere is already a SubServer with that name");
def.put("Interface.Host-Creator.Edit-Name.Invalid", "&cSubCreator &4&l\\u00BB&c Invalid Server Name");
def.put("Interface.Host-Creator.Edit-Name.Invalid-Title", "&eSubCreator\\n&cInvalid Server Name");
def.put("Interface.Host-Creator.Edit-Template", "Change Server Template");
def.put("Interface.Host-Creator.Edit-Template.Title", "Host/$str$/Templates");
def.put("Interface.Host-Creator.Edit-Template.No-Templates", "&c&oThere are No Templates");
def.put("Interface.Host-Creator.Edit-Version", "Change Server Version");
def.put("Interface.Host-Creator.Edit-Version.Title", "&eSubCreator\\n&6Enter a Server Version");
def.put("Interface.Host-Creator.Edit-Version.Message", "&eSubCreator &6&l\\u00BB&e Enter a Server Version via Chat");
def.put("Interface.Host-Creator.Edit-Port", "Change Server Port");
def.put("Interface.Host-Creator.Edit-Port.Title", "&eSubCreator\\n&6Enter a Port Number");
def.put("Interface.Host-Creator.Edit-Port.Message", "&eSubCreator &6&l\\u00BB&e Enter a Port Number via Chat");
def.put("Interface.Host-Creator.Edit-Port.Invalid", "&cSubCreator &4&l\\u00BB&c Invalid Port Number");
def.put("Interface.Host-Creator.Edit-Port.Invalid-Title", "&eSubCreator\\n&cInvalid Port Number");
def.put("Interface.Host-Creator.Submit", "&eCreate SubServer");
def.put("Interface.Host-Creator.Form-Incomplete", "&4Buttons above must be green");
def.put("Interface.Host-Plugin.Title", "Host/$str$/Plugins");
def.put("Interface.Host-Plugin.No-Plugins", "&c&oThere are No Plugins Available");
def.put("Interface.Host-SubServer.Title", "Host/$str$/SubServers");
def.put("Interface.Group-Menu.Title", "Group Menu");
def.put("Interface.Group-Menu.Group-Server-Count", "&9$int$ Server(s)");
def.put("Interface.Group-Menu.Ungrouped", "&7(ungrouped)");
def.put("Interface.Group-Menu.Server-Menu", "&a&lView All Servers");
def.put("Interface.Group-SubServer.Title", "Group/$str$/Servers");
def.put("Interface.Group-SubServer.Title-Ungrouped", "Ungrouped Server Menu");
def.put("Interface.Server-Menu.Title", "Server Menu");
def.put("Interface.Server-Menu.Server-Player-Count", "&2$int$ Player(s) Online");
def.put("Interface.Server-Menu.Server-External", "&7External Server");
def.put("Interface.Server-Menu.SubServer-Temporary", "&9Temporary");
def.put("Interface.Server-Menu.SubServer-Offline", "&6Offline");
def.put("Interface.Server-Menu.SubServer-Incompatible", "&4Incompatible with $str$");
def.put("Interface.Server-Menu.SubServer-Unavailable", "&4Unavailable");
def.put("Interface.Server-Menu.SubServer-Disabled", "&4Disabled");
def.put("Interface.Server-Menu.No-Servers", "&c&oThere are No Servers");
def.put("Interface.Server-Menu.Host-Menu", "&b&lView Hosts");
def.put("Interface.Server-Admin.Title", "Server/$str$");
def.put("Interface.Server-Admin.Start", "&aStart SubServer");
def.put("Interface.Server-Admin.Start.Title", "&aStarting SubServer");
def.put("Interface.Server-Admin.Stop", "&cStop SubServer");
def.put("Interface.Server-Admin.Stop.Title", "&cStopping $str$");
def.put("Interface.Server-Admin.Terminate", "&4Terminate SubServer");
def.put("Interface.Server-Admin.Terminate.Title", "&cTerminating $str$");
def.put("Interface.Server-Admin.Command", "&bSend a Command to the Server");
def.put("Interface.Server-Admin.Command.Title", "&eSubServers\\n&6Enter a Command to send via Chat");
def.put("Interface.Server-Admin.Command.Message", "&eSubServers &6&l\\u00BB&e Enter a Command to send via Chat");
def.put("Interface.Server-Admin.Update", "&eUpdate SubServer");
def.put("Interface.Server-Admin.Update.Title", "&eSubServers\\n&6Enter a Server Version to update to");
def.put("Interface.Server-Admin.Update.Message", "&eSubServers &6&l\\u00BB&e Enter a Server Version to update to via Chat");
def.put("Interface.Server-Admin.Plugins", "&bPlugins...");
def.put("Interface.SubServer-Plugin.Title", "Server/$str$/Plugins");
def.put("Interface.SubServer-Plugin.No-Plugins", "&c&oThere are No Plugins Available");
YAMLSection lang = new YAMLSection();
for (String key : def.keySet()) lang.set(key, updated.getMap("Lang", new YAMLSection()).getString(key, def.get(key)));
rewritten.set("Lang", lang);
config.set(rewritten);
config.save();
}
}
}

View File

@ -1,152 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Fallback;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ReconnectHandler;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Smart Reconnect Handler Class
*/
public class SmartReconnectHandler implements ReconnectHandler {
private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>();
@Override
public ServerInfo getServer(ProxiedPlayer player) {
ServerInfo forced = getForcedHost(player.getPendingConnection());
if (forced != null) {
return forced;
} else {
Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener());
if (fallbacks.isEmpty()) {
return null;
} else {
if (player instanceof UserConnection) ((UserConnection) player).setServerJoinQueue(new LinkedList<>(fallbacks.keySet()));
return new LinkedList<Map.Entry<String, ServerInfo>>(fallbacks.entrySet()).getFirst().getValue();
}
}
}
/**
* Grabs the Forced Host Server for this connection
*
* @see AbstractReconnectHandler#getForcedHost(PendingConnection) Essentially the same method, but more ambigous
* @param connection Connection to check
* @return Forced Host Server (or null if there is none)
*/
public static ServerInfo getForcedHost(PendingConnection connection) {
if (connection.getVirtualHost() == null) {
return null;
} else {
String forced = connection.getListener().getForcedHosts().get(connection.getVirtualHost().getHostString());
//if (forced == null && con.getListener().isForceDefault()) { // This is the part of the method that made it ambiguous
// forced = con.getListener().getDefaultServer(); // Aside from that, everything else was fine
//} // :(
return ProxyServer.getInstance().getServerInfo(forced);
}
}
/**
* Generates a <i>smart</i> sorted map of fallback servers using a generated confidence score
*
* @param listener Listener to grab fallback servers from
* @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) {
TreeMap<Integer, List<ServerInfo>> score = new TreeMap<Integer, List<ServerInfo>>(Collections.reverseOrder());
for (String name : listener.getServerPriority()) {
ServerInfo server = SubAPI.getInstance().getServer(name.toLowerCase());
if (server == null) server = ProxyServer.getInstance().getServerInfo(name);
if (server != null) {
boolean valid = true;
int confidence = 0;
if (server instanceof Server) {
if (!((Server) server).isHidden()) confidence++;
if (!((Server) server).isRestricted()) confidence++;
if (((Server) server).getSubData()[0] != null) confidence++;
} if (server instanceof SubServer) {
if (!((SubServer) server).isRunning()) valid = false;
}
List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>();
inspectors.addAll(SmartReconnectHandler.inspectors);
for (FallbackInspector inspector : inspectors) try {
Integer response = inspector.inspect(server);
if (response == null) {
valid = false;
} else {
confidence += response;
}
} catch (Throwable e) {
new InvocationTargetException(e, "Exception while running inspecting fallback server: " + server.getName()).printStackTrace();
}
if (valid) {
List<ServerInfo> servers = (score.keySet().contains(confidence))?score.get(confidence):new LinkedList<ServerInfo>();
servers.add(server);
score.put(confidence, servers);
}
}
}
Random random = new Random();
LinkedHashMap<String, ServerInfo> map = new LinkedHashMap<String, ServerInfo>();
for (List<ServerInfo> servers : score.values()) {
while (!servers.isEmpty()) {
ServerInfo next = servers.get(random.nextInt(servers.size()));
map.put(next.getName(), next);
servers.remove(next);
}
}
return map;
}
/**
* Add a Fallback Server Inspector
*
* @param inspector Inspector
*/
public static void addInspector(FallbackInspector inspector) {
if (Util.isNull(inspector)) throw new NullPointerException();
inspectors.add(inspector);
}
/**
* Remove a Fallback Server Inspector
*
* @param inspector Inspector
*/
public static void removeInspector(FallbackInspector inspector) {
if (Util.isNull(inspector)) throw new NullPointerException();
Util.isException(() -> inspectors.remove(inspector));
}
@Override
public void setServer(ProxiedPlayer player) {
// Ignore server switching
}
@Override
public void save() {
// Nothing to save
}
@Override
public void close() {
// Nothing to close
}
}

View File

@ -0,0 +1,135 @@
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.Galaxi.Library.Directories;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.PrimitiveIterator;
import java.util.regex.Pattern;
/**
* File Scanner Base Class
*/
public abstract class FileScanner {
/**
* Scan a Directory
*
* @param dir Directory
* @param whitelist File Whitelist
*/
protected void scan(File dir, String... whitelist) throws IOException {
List<String> files = Directories.search(dir);
if (files.size() <= 0 || whitelist.length <= 0)
return;
boolean csfs = false;
{
long stamp = Math.round(Math.random() * 100000);
File test1 = new File(dir, '.' + stamp + ".ss_fsc");
File test2 = new File(dir, '.' + stamp + ".SS_FSC");
test1.createNewFile();
if (test2.createNewFile()) {
csfs = true;
test2.delete();
}
test1.delete();
}
LinkedHashMap<Pattern, Boolean> rules = new LinkedHashMap<Pattern, Boolean>();
for (String entry : whitelist) {
boolean mode = !entry.startsWith("!");
if (!mode) entry = entry.substring(1);
String pattern;
if (!entry.startsWith("%")) {
if (entry.startsWith("./"))
entry = entry.substring(1);
StringBuilder rule = new StringBuilder();
if (entry.startsWith("**")) {
entry = entry.substring(2);
rule.append("^.*");
} else if (entry.startsWith("/")) {
rule.append("^");
}
boolean greedyEnding = false;
if (entry.endsWith("**")) {
entry = entry.substring(0, entry.length() - 2);
greedyEnding = true;
} else if (entry.endsWith("/")) {
greedyEnding = true;
}
StringBuilder literal = new StringBuilder();
for (PrimitiveIterator.OfInt i = entry.codePoints().iterator(); i.hasNext(); ) {
int c = i.next();
if ((c == '*' || c == '?' || c == '[') && literal.length() > 0) {
rule.append(Pattern.quote(literal.toString()));
literal = new StringBuilder();
}
switch (c) {
case '[':
for (boolean escaped = false; i.hasNext() && (c != ']' || escaped); c = i.next()) {
if (c == '\\') escaped = !escaped;
else escaped = false;
literal.appendCodePoint(c);
}
if (c == ']' && literal.length() > 1) {
literal.appendCodePoint(c);
rule.append(literal.toString());
}
literal = new StringBuilder();
break;
case '*':
rule.append("[^/]+");
break;
case '?':
rule.append("[^/]");
break;
case '\\':
if (i.hasNext()) c = i.next();
default:
literal.appendCodePoint(c);
break;
}
}
if (literal.length() > 0)
rule.append(Pattern.quote(literal.toString()));
if (greedyEnding)
rule.append(".*");
rule.append("$");
pattern = rule.toString();
} else {
pattern = entry.substring(1);
}
if (csfs) rules.put(Pattern.compile(pattern), mode);
else rules.put(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE), mode);
}
for (String file : files) {
boolean act = false;
for (Map.Entry<Pattern, Boolean> rule : rules.entrySet()) {
if (rule.getKey().matcher('/' + file.replace(File.separatorChar, '/')).find()) act = rule.getValue();
}
if (act) act(dir, file);
}
}
/**
* Perform an action on an included file
*
* @param dir Parent Directory
* @param name File Name
*/
protected abstract void act(File dir, String name) throws IOException;
}

View File

@ -1,456 +0,0 @@
package net.ME1312.SubServers.Bungee.Library;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;
/**
* bStats collects some data for plugin authors.
*
* Check out https://bStats.org/ to learn more about bStats!
*/
public class Metrics {
static {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
final String defaultPackage = new String(
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'n', 'g', 'e', 'e', 'c', 'o', 'r', 'd'});
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure nobody just copy & pastes the example and use the wrong package names
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
// The version of this bStats class
public static final int B_STATS_VERSION = 1;
// The url to which the data is sent
private static final String URL = "https://bStats.org/submitData/bungeecord";
// The plugin
private final SubProxy plugin;
// Is bStats enabled on this server?
private boolean enabled;
// The uuid of the server
private String serverUUID;
// Should failed requests be logged?
private boolean logFailedRequests = false;
// A list with all known metrics class objects including this one
private static final List<Object> knownMetricsInstances = new ArrayList<>();
public Metrics(SubProxy plugin) {
this.plugin = plugin;
try {
loadConfig();
} catch (IOException e) {
// Failed to load configuration
plugin.getLogger().log(Level.WARNING, "Failed to load bStats config!", e);
return;
}
// We are not allowed to send data about this server :(
if (!enabled) {
return;
}
Class<?> usedMetricsClass = getFirstBStatsClass();
if (usedMetricsClass == null) {
// Failed to get first metrics class
return;
}
if (usedMetricsClass == getClass()) {
// We are the first! :)
linkMetrics(this);
startSubmitting();
} else {
// We aren't the first so we link to the first metrics class
try {
usedMetricsClass.getMethod("linkMetrics", Object.class).invoke(null,this);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Failed to link to first metrics class " + usedMetricsClass.getName() + "!", e);
}
}
}
}
/**
* Links an other metrics class with this class.
* This method is called using Reflection.
*
* @param metrics An object of the metrics class to link.
*/
public static void linkMetrics(Object metrics) {
knownMetricsInstances.add(metrics);
}
/**
* Gets the plugin specific data.
* This method is called using Reflection.
*
* @return The plugin specific data.
*/
public JsonObject getPluginData() {
JsonObject data = new JsonObject();
String pluginName = "SubServers 2";
String pluginVersion = plugin.version.toString();
data.addProperty("pluginName", pluginName);
data.addProperty("pluginVersion", pluginVersion);
JsonArray customCharts = new JsonArray();
customCharts.add(new SingleLineChart("managed_hosts", new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return plugin.api.getHosts().size();
}
}).getRequestJsonObject(plugin.getLogger(), logFailedRequests));
customCharts.add(new SingleLineChart("subdata_connected", new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return (plugin.subdata != null)?plugin.subdata.getClients().size():0;
}
}).getRequestJsonObject(plugin.getLogger(), logFailedRequests));
data.add("customCharts", customCharts);
return data;
}
private void startSubmitting() {
new Timer("SubServers.Bungee::Metrics_Uploader").schedule( new TimerTask() {
@Override
public void run() {
// The data collection is async, as well as sending the data
// Bungeecord does not have a main thread, everything is async
submitData();
}
}, TimeUnit.MINUTES.toMillis(2), TimeUnit.MINUTES.toMillis(30));
// Submit the data every 30 minutes, first time after 2 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
}
/**
* Gets the server specific data.
*
* @return The server specific data.
*/
private JsonObject getServerData() {
// Minecraft specific data
int playerAmount = plugin.getOnlineCount();
playerAmount = playerAmount > 500 ? 500 : playerAmount;
int onlineMode = plugin.getConfig().isOnlineMode() ? 1 : 0;
String bungeecordVersion = (plugin.getName().equals("SubServers Platform"))?"SubServers-Bungee-Patched":plugin.getVersion();
int managedServers = plugin.getServers().size();
// OS/Java specific data
String javaVersion = System.getProperty("java.version");
String osName = System.getProperty("os.name");
String osArch = System.getProperty("os.arch");
String osVersion = System.getProperty("os.version");
int coreCount = Runtime.getRuntime().availableProcessors();
JsonObject data = new JsonObject();
data.addProperty("serverUUID", serverUUID);
data.addProperty("playerAmount", playerAmount);
data.addProperty("managedServers", managedServers);
data.addProperty("onlineMode", onlineMode);
data.addProperty("bungeecordVersion", bungeecordVersion);
data.addProperty("javaVersion", javaVersion);
data.addProperty("osName", osName);
data.addProperty("osArch", osArch);
data.addProperty("osVersion", osVersion);
data.addProperty("coreCount", coreCount);
return data;
}
/**
* Collects the data and sends it afterwards.
*/
private void submitData() {
final JsonObject data = getServerData();
final JsonArray pluginData = new JsonArray();
// Search for all other bStats Metrics classes to get their plugin data
for (Object metrics : knownMetricsInstances) {
try {
Object plugin = metrics.getClass().getMethod("getPluginData").invoke(metrics);
if (plugin instanceof JsonObject) {
pluginData.add((JsonObject) plugin);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { }
}
data.add("plugins", pluginData);
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats!", e);
}
}
}
/**
* Loads the bStats configuration.
*
* @throws IOException If something did not work :(
*/
private void loadConfig() throws IOException {
Path configPath = new File(plugin.dir, "plugins").toPath().resolve("bStats");
configPath.toFile().mkdirs();
File configFile = new File(configPath.toFile(), "config.yml");
if (!configFile.exists()) {
writeFile(configFile,
"#bStats collects some data for plugin authors like how many servers are using their plugins.",
"#To honor their work, you should not disable it.",
"#This has nearly no effect on the server performance!",
"#Check out https://bStats.org/ to learn more :)",
"enabled: true",
"serverUuid: \"" + UUID.randomUUID().toString() + "\"",
"logFailedRequests: false");
}
Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
// Load configuration
enabled = configuration.getBoolean("enabled", true);
serverUUID = configuration.getString("serverUuid");
logFailedRequests = configuration.getBoolean("logFailedRequests", false);
}
/**
* Gets the first bStat Metrics class.
*
* @return The first bStats metrics class.
*/
private Class<?> getFirstBStatsClass() {
Path configPath = new File(plugin.dir, "plugins").toPath().resolve("bStats");
configPath.toFile().mkdirs();
File tempFile = new File(configPath.toFile(), "temp.txt");
try {
String className = readFile(tempFile);
if (className != null) {
try {
// Let's check if a class with the given name exists.
return Class.forName(className);
} catch (ClassNotFoundException ignored) { }
}
writeFile(tempFile, getClass().getName());
return getClass();
} catch (IOException e) {
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Failed to get first bStats class!", e);
}
return null;
}
}
/**
* Reads the first line of the file.
*
* @param file The file to read. Cannot be null.
* @return The first line of the file or <code>null</code> if the file does not exist or is empty.
* @throws IOException If something did not work :(
*/
private String readFile(File file) throws IOException {
if (!file.exists()) {
return null;
}
try (
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
) {
return bufferedReader.readLine();
}
}
/**
* Writes a String to a file. It also adds a note for the user,
*
* @param file The file to write to. Cannot be null.
* @param lines The lines to write.
* @throws IOException If something did not work :(
*/
private void writeFile(File file, String... lines) throws IOException {
if (!file.exists()) {
file.createNewFile();
}
try (
FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)
) {
for (String line : lines) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
}
}
/**
* Sends the data to the bStats server.
*
* @param data The data to send.
* @throws Exception If the request failed.
*/
private static void sendData(JsonObject data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null");
}
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
// Add headers
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
// Send data
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.write(compressedData);
outputStream.flush();
outputStream.close();
connection.getInputStream().close(); // We don't care about the response - Just send our data :)
}
/**
* Gzips the given String.
*
* @param str The string to gzip.
* @return The gzipped String.
* @throws IOException If the compression failed.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.close();
return outputStream.toByteArray();
}
/**
* Represents a custom chart.
*/
private static abstract class CustomChart {
// The id of the chart
private final String chartId;
/**
* Class constructor.
*
* @param chartId The id of the chart.
*/
CustomChart(String chartId) {
if (chartId == null || chartId.isEmpty()) {
throw new IllegalArgumentException("ChartId cannot be null or empty!");
}
this.chartId = chartId;
}
JsonObject getRequestJsonObject(Logger logger, boolean logFailedRequests) {
JsonObject chart = new JsonObject();
chart.addProperty("chartId", chartId);
try {
JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
chart.add("data", data);
} catch (Throwable t) {
if (logFailedRequests) {
logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return chart;
}
protected abstract JsonObject getChartData() throws Exception;
}
/**
* Represents a custom single line chart.
*/
private static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObject getChartData() throws Exception {
JsonObject data = new JsonObject();
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
data.addProperty("value", value);
return data;
}
}
}

View File

@ -0,0 +1,100 @@
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.Galaxi.Library.Util;
import java.io.*;
import java.util.*;
/**
* File Replacement Scanner
*/
public class ReplacementScanner extends FileScanner {
private final Map<String, String> replacements = new LinkedHashMap<>();
public ReplacementScanner(Map<String, String> replacements) {
TreeMap<Integer, LinkedList<String>> order = new TreeMap<Integer, LinkedList<String>>(Comparator.reverseOrder());
for (String key : replacements.keySet()) {
int length = key.length();
if (!order.containsKey(length)) order.put(length, new LinkedList<>());
order.get(length).add(key);
}
for (Integer length : order.keySet()) {
for (String key : order.get(length)) {
this.replacements.put(key, replacements.get(key));
}
}
}
/**
* Get the replacements
*
* @return Replacement Map
*/
public Map<String, String> getReplacements() {
return new HashMap<>(replacements);
}
/**
* Make replacements in a File or Directory
*
* @param dir File or Directory
* @param whitelist File Whitelist
*/
public void replace(File dir, String... whitelist) throws IOException {
super.scan(dir, whitelist);
}
protected void act(File dir, String name) throws IOException {
File file = new File(dir, name);
FileInputStream stream = new FileInputStream(file);
String string = Util.readAll(new InputStreamReader(stream));
stream.close();
boolean update = false;
for (Map.Entry<String, String> replacement : replacements.entrySet()) {
String placeholder = "SubServers::" + replacement.getKey();
if (string.contains(placeholder)) {
string = string.replace(placeholder, replacement.getValue());
update = true;
}
}
if (update) {
FileWriter writer = new FileWriter(file, false);
writer.write(string);
writer.close();
}
}
/**
* Make replacements in an Object
*
* @param value Map, Collection, Array, or String
* @return Object with replaced variables
*/
public Object replace(Object value) {
if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, replace(((Map<String, Object>) value).get(key)));
return value;
} else if (value instanceof Collection) {
List<Object> list = new ArrayList<Object>();
for (Object val : (Collection<Object>) value) list.add(replace(val));
return list;
} else if (value.getClass().isArray()) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < ((Object[]) value).length; i++) list.add(replace(((Object[]) value)[i]));
return list;
} else if (value instanceof String) {
return replaceObj((String) value);
} else {
return value;
}
} private String replaceObj(String string) {
for (Map.Entry<String, String> replacement : replacements.entrySet()) string = string.replace('$' + replacement.getKey() + '$', replacement.getValue());
return string;
}
}

View File

@ -1,485 +0,0 @@
package net.ME1312.SubServers.Bungee.Library.Updates;
import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Config.YAMLSection;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.SubAPI;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* SubServers Configuration Updater
*/
public class ConfigUpdater {
private static final Version UNSIGNED = new Version(new SimpleDateFormat("yy'w'ww'zz'").format(Calendar.getInstance().getTime()));
/**
* Update SubServers' config.yml
*
* @param file File to bring up-to-date
*/
public static void updateConfig(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
YAMLSection hosts = new YAMLSection();
YAMLSection host = new YAMLSection();
host.set("Enabled", true);
host.set("Display", "Default");
hosts.set("~", host);
updated.set("Hosts", hosts);
i++;
Logger.get("SubServers").info("Created ./SubServers/config.yml");
} else {
if (was.compareTo(new Version("19w17a")) <= 0) {
if (existing.getMap("Settings", new YAMLSection()).contains("Log-Creator")) for (String name : existing.getMap("Hosts", new YAMLSection()).getKeys())
updated.getMap("Hosts").getMap(name).safeSet("Log-Creator", existing.getMap("Settings").getBoolean("Log-Creator"));
if (existing.getMap("Settings", new YAMLSection()).contains("SubData") && !existing.getMap("Settings", new YAMLSection()).getMap("SubData").contains("Encryption"))
updated.getMap("Settings").getMap("SubData").set("Encryption", "NONE");
if (existing.contains("Servers")) {
YAMLConfig sc = new YAMLConfig(new File(file.getParentFile(), "servers.yml"));
YAMLSection settings = new YAMLSection();
settings.set("Version", was.toString());
settings.set("Run-On-Launch-Timeout", (existing.getMap("Settings", new YAMLSection()).contains("Run-On-Launch-Timeout"))?existing.getMap("Settings").getInt("Run-On-Launch-Timeout"):0);
sc.get().safeSet("Settings", settings);
sc.get().safeSet("Servers", new YAMLSection());
sc.get().getMap("Servers").safeSetAll(existing.getMap("Servers"));
Logger.get("SubServers").info("Created ./SubServers/servers.yml (using existing data)");
sc.save();
}
existing = updated.clone();
i++;
} if (was.compareTo(new Version("19w35c")) <= 0) {
if (existing.getMap("Settings", new YAMLSection()).contains("SubData")) {
LinkedList<String> whitelist = new LinkedList<>();
LinkedList<String> newWhitelist = new LinkedList<>();
whitelist.addAll(existing.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getStringList("Allowed-Connections", Collections.emptyList()));
whitelist.addAll(existing.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getStringList("Whitelist", Collections.emptyList()));
boolean warnPls = false;
for (String address : whitelist) {
Matcher regAddress = Pattern.compile("^(\\d{1,3}|%)\\.(\\d{1,3}|%)\\.(\\d{1,3}|%)\\.(\\d{1,3}|%)$").matcher(address);
if (regAddress.find()) {
StringBuilder newAddress = new StringBuilder();
int subnet = -1;
boolean warn = false;
for (int o = 1; o <= 4; o++) {
if (o > 1) newAddress.append('.');
if (subnet == -1) {
if (!regAddress.group(o).equals("%")) {
newAddress.append(regAddress.group(o));
} else {
subnet = 8 * (o - 1);
newAddress.append('0');
}
} else {
if (!regAddress.group(o).equals("%")) warn = warnPls = true;
newAddress.append('0');
}
}
if (subnet < 0) subnet = 32;
if (warn) Logger.get("SubServers").warning("Updating non-standard mask: " + address);
newAddress.append('/');
newAddress.append(subnet);
newWhitelist.add(newAddress.toString());
}
}
updated.getMap("Settings").getMap("SubData").set("Whitelist", newWhitelist);
if (warnPls) Logger.get("SubServers").warning("Non-standard masks have been updated. This may expose SubData to unintended networks!");
}
existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// existing = updated.clone();
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/config.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
settings.set("Smart-Fallback", updated.getMap("Settings", new YAMLSection()).getBoolean("Smart-Fallback", true));
settings.set("Override-Bungee-Commands", updated.getMap("Settings", new YAMLSection()).getBoolean("Override-Bungee-Commands", true));
YAMLSection upnp = new YAMLSection();
upnp.set("Forward-Proxy", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-Proxy", true));
upnp.set("Forward-SubData", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-SubData", false));
upnp.set("Forward-Servers", updated.getMap("Settings", new YAMLSection()).getMap("UPnP", new YAMLSection()).getBoolean("Forward-Servers", false));
settings.set("UPnP", upnp);
YAMLSection subdata = new YAMLSection();
subdata.set("Address", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getRawString("Address", "127.0.0.1:4391"));
if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Password")) subdata.set("Password", updated.getMap("Settings").getMap("SubData").getRawString("Password"));
subdata.set("Encryption", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getRawString("Encryption", "RSA/AES"));
subdata.set("Whitelist", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getRawStringList("Whitelist", Collections.emptyList()));
settings.set("SubData", subdata);
rewritten.set("Settings", settings);
YAMLSection hosts = new YAMLSection();
for (String name : updated.getMap("Hosts", new YAMLSection()).getKeys()) {
YAMLSection host = new YAMLSection();
host.set("Enabled", updated.getMap("Hosts").getMap(name).getBoolean("Enabled", false));
host.set("Display", updated.getMap("Hosts").getMap(name).getRawString("Display", ""));
host.set("Driver", updated.getMap("Hosts").getMap(name).getRawString("Driver", "BUILT-IN"));
host.set("Address", updated.getMap("Hosts").getMap(name).getRawString("Address", "127.0.0.1"));
host.set("Port-Range", updated.getMap("Hosts").getMap(name).getRawString("Port-Range", "25500-25559"));
host.set("Directory", updated.getMap("Hosts").getMap(name).getRawString("Directory", (host.getRawString("Driver").equalsIgnoreCase("BUILT-IN"))?"./SubServers/Servers":"./Servers"));
host.set("Git-Bash", updated.getMap("Hosts").getMap(name).getRawString("Git-Bash", "%ProgramFiles%\\Git"));
host.set("Log-Creator", updated.getMap("Hosts").getMap(name).getBoolean("Log-Creator", true));
if (updated.getMap("Hosts").getMap(name).contains("Extra")) host.set("Extra", updated.getMap("Hosts").getMap(name).getMap("Extra"));
hosts.set(name, host);
}
rewritten.set("Hosts", hosts);
config.set(rewritten);
config.save();
}
}
/**
* Update SubServers' servers.yml
*
* @param file File to bring up-to-date
*/
public static void updateServers(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
YAMLSection servers = new YAMLSection();
servers.set("Example", new YAMLSection());
updated.set("Servers", servers);
i++;
Logger.get("SubServers").info("Created ./SubServers/servers.yml");
} else {
if (was.compareTo(new Version("19w17a")) <= 0) {
for (String name : existing.getMap("Servers", new YAMLSection()).getKeys()) {
if (existing.getMap("Servers").getMap(name).getBoolean("Auto-Restart", true))
updated.getMap("Servers").getMap(name).safeSet("Stop-Action", "RESTART");
if (existing.getMap("Servers").getMap(name).getRawString("Stop-Action", "NONE").equalsIgnoreCase("DELETE_SERVER"))
updated.getMap("Servers").getMap(name).set("Stop-Action", "RECYCLE_SERVER");
}
existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/servers.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
settings.set("Run-On-Launch-Timeout", updated.getMap("Settings", new YAMLSection()).getInt("Run-On-Launch-Timeout", 0));
rewritten.set("Settings", settings);
YAMLSection servers = new YAMLSection();
for (String name : updated.getMap("Servers", new YAMLSection()).getKeys()) {
YAMLSection server = new YAMLSection();
server.set("Enabled", updated.getMap("Servers").getMap(name).getBoolean("Enabled", false));
server.set("Display", updated.getMap("Servers").getMap(name).getRawString("Display", ""));
server.set("Host", updated.getMap("Servers").getMap(name).getRawString("Host", "~"));
if (updated.getMap("Servers").getMap(name).contains("Template")) server.set("Template", updated.getMap("Servers").getMap(name).getRawString("Template"));
server.set("Group", updated.getMap("Servers").getMap(name).getRawStringList("Groups", Collections.emptyList()));
server.set("Port", updated.getMap("Servers").getMap(name).getInt("Port", 25567));
server.set("Motd", updated.getMap("Servers").getMap(name).getRawString("Motd", "Some SubServer"));
server.set("Log", updated.getMap("Servers").getMap(name).getBoolean("Log", true));
server.set("Directory", updated.getMap("Servers").getMap(name).getRawString("Directory", "." + File.separatorChar));
server.set("Executable", updated.getMap("Servers").getMap(name).getRawString("Executable", "java -Xmx1024M -Djline.terminal=jline.UnsupportedTerminal -jar Spigot.jar"));
server.set("Stop-Command", updated.getMap("Servers").getMap(name).getRawString("Stop-Command", "stop"));
server.set("Stop-Action", updated.getMap("Servers").getMap(name).getRawString("Stop-Action", "NONE"));
server.set("Run-On-Launch", updated.getMap("Servers").getMap(name).getBoolean("Run-On-Launch", false));
server.set("Restricted", updated.getMap("Servers").getMap(name).getBoolean("Restricted", false));
server.set("Incompatible", updated.getMap("Servers").getMap(name).getRawStringList("Incompatible", Collections.emptyList()));
server.set("Hidden", updated.getMap("Servers").getMap(name).getBoolean("Hidden", false));
if (updated.getMap("Servers").getMap(name).contains("Extra")) server.set("Extra", updated.getMap("Servers").getMap(name).getMap("Extra"));
servers.set(name, server);
}
rewritten.set("Servers", servers);
config.set(rewritten);
config.save();
}
}
/**
* Update SubServers' lang.yml
*
* @param file File to bring up-to-date
*/
public static void updateLang(File file) throws IOException {
YAMLConfig config = new YAMLConfig(file);
YAMLSection existing = config.get().clone();
YAMLSection updated = existing.clone();
YAMLSection rewritten = new YAMLSection();
Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0));
Version now = SubAPI.getInstance().getWrapperBuild();
int i = 0;
if (now == null) now = UNSIGNED;
if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) {
i++;
Logger.get("SubServers").info("Created ./SubServers/lang.yml");
} else {
if (was.compareTo(new Version("19w22b")) <= 0) {
updated.getMap("Lang").remove("Interface.Host-Admin.SubServers");
updated.getMap("Lang").remove("Interface.SubServer-Admin.Command");
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
// i++
//}
if (i > 0) Logger.get("SubServers").info("Updated ./SubServers/lang.yml (" + i + " pass" + ((i != 1)?"es":"") + ")");
}
if (i > 0) {
YAMLSection settings = new YAMLSection();
settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString());
rewritten.set("Settings", settings);
YAMLSection lang = new YAMLSection();
lang.set("Bungee.Feature.Smart-Fallback", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Feature.Smart-Fallback", "&6Returning from $str$: &r$msg$"));
lang.set("Bungee.Feature.Smart-Fallback.Result", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Feature.Smart-Fallback.Result", "&6You are now on $str$."));
lang.set("Bungee.Ping.Offline", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Ping.Offline", "&6&l[&e&lWarning&6&l] &7Backend server(s) are not running"));
lang.set("Bungee.Server.Current", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Current", "&6You are currently connected to $str$"));
lang.set("Bungee.Server.Available", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Available", "&6You may connect to the following servers at this time:"));
lang.set("Bungee.Server.List", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.List", "&6$str$"));
lang.set("Bungee.Server.Hover", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Hover", "$int$ player(s)\n&oClick to connect to the server"));
lang.set("Bungee.Server.Divider", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Divider", "&6, "));
lang.set("Bungee.Server.Offline", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Offline", "&cThe specified server is not currently running."));
lang.set("Bungee.Server.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.Server.Invalid", "&cThe specified server does not exist."));
lang.set("Bungee.List.Format", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.List.Format", "&a[$str$] &e($int$)&r: "));
lang.set("Bungee.List.List", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.List.List", "&f$str$"));
lang.set("Bungee.List.Divider", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.List.Divider", "&f, "));
lang.set("Bungee.List.Total", updated.getMap("Lang", new YAMLSection()).getRawString("Bungee.List.Total", "Total players online: $int$"));
lang.set("Command.Generic.Player-Only", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Player-Only", "&cSubServers &4&l\u00BB&c Console cannot run this command"));
lang.set("Command.Generic.Console-Only", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Console-Only", "&cSubServers &4&l\u00BB&c This command is for console use only"));
lang.set("Command.Generic.Usage", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Usage", "&7SubServers &8&l\u00BB&7 Usage: &f$str$"));
lang.set("Command.Generic.Exception", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Exception", "&cSubServers &4&l\u00BB&c An unexpected exception has occurred while parsing this command"));
lang.set("Command.Generic.Invalid-Subcommand", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Invalid-Subcommand", "&cSubServers &4&l\u00BB&c Unknown sub-command: $str$"));
lang.set("Command.Generic.Invalid-Permission", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Invalid-Permission", "&cSubServers &4&l\u00BB&c You need &4&n$str$&c to use this command"));
lang.set("Command.Generic.Unknown-Proxy", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Unknown-Proxy", "&cSubServers &4&l\u00BB&c There is no proxy with that name"));
lang.set("Command.Generic.Unknown-Host", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Unknown-Host", "&cSubServers &4&l\u00BB&c There is no host with that name"));
lang.set("Command.Generic.Unknown-Group", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Unknown-Group", "&cSubServers &4&l\u00BB&c There is no group with that name"));
lang.set("Command.Generic.Unknown-Server", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Unknown-Server", "&cSubServers &4&l\u00BB&c There is no server with that name"));
lang.set("Command.Generic.Unknown-SubServer", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Generic.Unknown-SubServer", "&cSubServers &4&l\u00BB&c There is no subserver with that name"));
lang.set("Command.Help.Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.Header", "&7SubServers &8&l\u00BB&7 Command Help:"));
lang.set("Command.Help.Help", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.Help", " &7Help:&f $str$"));
lang.set("Command.Help.List", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.List", " &7List:&f $str$"));
lang.set("Command.Help.Version", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.Version", " &7Version:&f $str$"));
lang.set("Command.Help.Info", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.Info", " &7Info:&f $str$"));
lang.set("Command.Help.Host.Create", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.Host.Create", " &7Create Server:&f $str$"));
lang.set("Command.Help.SubServer.Start", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Start", " &7Start Server:&f $str$"));
lang.set("Command.Help.SubServer.Restart", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Restart", " &7Restart Server:&f $str$"));
lang.set("Command.Help.SubServer.Stop", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Stop", " &7Stop Server:&f $str$"));
lang.set("Command.Help.SubServer.Terminate", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Terminate", " &7Terminate Server:&f $str$"));
lang.set("Command.Help.SubServer.Command", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Command", " &7Command Server:&f $str$"));
lang.set("Command.Help.SubServer.Update", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Help.SubServer.Update", " &7Update Server:&f $str$"));
lang.set("Command.Version", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Version", "&7SubServers &8&l\u00BB&7 These are the platforms and versions that are running &f$str$&7:"));
lang.set("Command.Version.Outdated", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Version.Outdated", "&7$name$ &f$str$ &7is available. You are $int$ version(s) behind."));
lang.set("Command.Version.Latest", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Version.Latest", "&7You are on the latest version."));
lang.set("Command.List.Group-Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Group-Header", "&7SubServers &8&l\u00BB&7 Group/Server List:"));
lang.set("Command.List.Host-Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Host-Header", "&7SubServers &8&l\u00BB&7 Host/SubServer List:"));
lang.set("Command.List.Server-Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Server-Header", "&7SubServers &8&l\u00BB&7 Server List:"));
lang.set("Command.List.Proxy-Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Proxy-Header", "&7SubServers &8&l\u00BB&7 Proxy List:"));
lang.set("Command.List.Header", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Header", "&7: "));
lang.set("Command.List.Divider", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Divider", "&7, "));
lang.set("Command.List.Empty", updated.getMap("Lang", new YAMLSection()).getRawString("Command.List.Empty", "&7(none)"));
lang.set("Command.Info", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info", "&7SubServers &8&l\u00BB&7 Info on $str$&7: &r"));
lang.set("Command.Info.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown", "&cSubServers &4&l\u00BB&c There is no object with that name"));
lang.set("Command.Info.Unknown-Type", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown-Type", "&cSubServers &4&l\u00BB&c There is no object type with that name"));
lang.set("Command.Info.Unknown-Proxy", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown-Proxy", "&cSubServers &4&l\u00BB&c There is no proxy with that name"));
lang.set("Command.Info.Unknown-Host", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown-Host", "&cSubServers &4&l\u00BB&c There is no host with that name"));
lang.set("Command.Info.Unknown-Group", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown-Group", "&cSubServers &4&l\u00BB&c There is no group with that name"));
lang.set("Command.Info.Unknown-Server", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Unknown-Server", "&cSubServers &4&l\u00BB&c There is no server with that name"));
lang.set("Command.Info.Format", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.Format", " -> &7$str$&7: &r"));
lang.set("Command.Info.List", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Info.List", " - "));
lang.set("Command.Start", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start", "&aSubServers &2&l\u00BB&a Starting SubServer"));
lang.set("Command.Start.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Start.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Start.Host-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Host-Unavailable", "&cSubServers &4&l\u00BB&c That SubServer\u0027s Host is not available"));
lang.set("Command.Start.Host-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Host-Disabled", "&cSubServers &4&l\u00BB&c That SubServer\u0027s Host is not enabled"));
lang.set("Command.Start.Server-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Server-Unavailable", "&cSubServers &4&l\u00BB&c That SubServer is not available"));
lang.set("Command.Start.Server-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Server-Disabled", "&cSubServers &4&l\u00BB&c That SubServer is not enabled"));
lang.set("Command.Start.Server-Incompatible", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Server-Incompatible", "&cSubServers &4&l\u00BB&c That SubServer cannot start while these server(s) are running: &4$str$"));
lang.set("Command.Start.Running", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Start.Running", "&cSubServers &4&l\u00BB&c That SubServer is already running"));
lang.set("Command.Restart", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart", "&aSubServers &2&l\u00BB&a Stopping SubServer"));
lang.set("Command.Restart.Finish", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Finish", "&aSubServers &2&l\u00BB&a Starting SubServer"));
lang.set("Command.Restart.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Restart.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Restart.Disappeared", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Disappeared", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer has disappeared"));
lang.set("Command.Restart.Host-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Host-Unavailable", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer\u0027s Host is no longer available"));
lang.set("Command.Restart.Host-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Host-Disabled", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer\u0027s Host is no longer enabled"));
lang.set("Command.Restart.Server-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Server-Unavailable", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer is no longer available"));
lang.set("Command.Restart.Server-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Server-Disabled", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer is no longer enabled"));
lang.set("Command.Restart.Server-Incompatible", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Restart.Server-Incompatible", "&cSubServers &4&l\u00BB&c Could not restart server: That SubServer cannot start while these server(s) are running: &4$str$"));
lang.set("Command.Stop", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Stop", "&aSubServers &2&l\u00BB&a Stopping SubServer"));
lang.set("Command.Stop.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Stop.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Stop.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Stop.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Stop.Not-Running", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Stop.Not-Running", "&cSubServers &4&l\u00BB&c That SubServer is not running"));
lang.set("Command.Terminate", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Terminate", "&aSubServers &2&l\u00BB&a Stopping SubServer"));
lang.set("Command.Terminate.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Terminate.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Terminate.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Terminate.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Terminate.Not-Running", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Terminate.Not-Running", "&cSubServers &4&l\u00BB&c That SubServer is not running"));
lang.set("Command.Command", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Command", "&aSubServers &2&l\u00BB&a Sending command to SubServer"));
lang.set("Command.Command.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Command.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Command.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Command.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Command.Not-Running", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Command.Not-Running", "&cSubServers &4&l\u00BB&c That SubServer is not running"));
lang.set("Command.Creator", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator", "&aSubServers &2&l\u00BB&a Creating SubServer"));
lang.set("Command.Creator.Exists", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Exists", "&cSubServers &4&l\u00BB&c There is already a SubServer with that name"));
lang.set("Command.Creator.Unknown-Host", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Unknown-Host", "&cSubServers &4&l\u00BB&c There is no Host with that name"));
lang.set("Command.Creator.Host-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Host-Unavailable", "&cSubServers &4&l\u00BB&c That Host is not available"));
lang.set("Command.Creator.Host-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Host-Disabled", "&cSubServers &4&l\u00BB&c That Host is not enabled"));
lang.set("Command.Creator.Unknown-Template", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Unknown-Template", "&cSubServers &4&l\u00BB&c There is no Template with that name"));
lang.set("Command.Creator.Template-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Template-Disabled", "&cSubServers &4&l\u00BB&c That Template is not enabled"));
lang.set("Command.Creator.Version-Required", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Version-Required", "&cSubServers &4&l\u00BB&c That Template requires a Minecraft Version to be specified"));
lang.set("Command.Creator.Invalid-Port", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator.Invalid-Port", "&cSubServers &4&l\u00BB&c Invalid Port Number"));
lang.set("Command.Update", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Creator", "&aSubServers &2&l\u00BB&a Updating SubServer"));
lang.set("Command.Update.Unknown", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Unknown", "&cSubServers &4&l\u00BB&c There is no Server with that name"));
lang.set("Command.Update.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Invalid", "&cSubServers &4&l\u00BB&c That Server is not a SubServer"));
lang.set("Command.Update.Host-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Host-Unavailable", "&cSubServers &4&l\u00BB&c That SubServer\u0027s Host is not available"));
lang.set("Command.Update.Host-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Host-Disabled", "&cSubServers &4&l\u00BB&c That SubServer\u0027s Host is not enabled"));
lang.set("Command.Update.Server-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Server-Unavailable", "&cSubServers &4&l\u00BB&c That SubServer is not available"));
lang.set("Command.Update.Running", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Running", "&cSubServers &4&l\u00BB&c Cannot update servers while they are still running"));
lang.set("Command.Update.Unknown-Template", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Unknown-Template", "&cSubServers &4&l\u00BB&c We don't know which template created that SubServer"));
lang.set("Command.Update.Template-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Template-Disabled", "&cSubServers &4&l\u00BB&c That SubServer's Template is not enabled"));
lang.set("Command.Update.Template-Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Template-Invalid", "&cSubServers &4&l\u00BB&c That SubServer's Template does not support server updating"));
lang.set("Command.Update.Version-Required", updated.getMap("Lang", new YAMLSection()).getRawString("Command.Update.Version-Required", "&cSubServers &4&l\u00BB&c That SubServer's Template requires a Minecraft Version to be specified"));
lang.set("Interface.Generic.Back", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Back", "&cBack"));
lang.set("Interface.Generic.Back-Arrow", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Back-Arrow", "&e&l<--"));
lang.set("Interface.Generic.Next-Arrow", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Next-Arrow", "&e&l-->"));
lang.set("Interface.Generic.Undo", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Undo", "&6Undo"));
lang.set("Interface.Generic.Downloading", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Downloading", "&7SubServers &8&l\u00BB&7 Downloading:&f $str$"));
lang.set("Interface.Generic.Downloading.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Downloading.Title", "Downloading..."));
lang.set("Interface.Generic.Downloading.Title-Color", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Downloading.Title-Color", "&b"));
lang.set("Interface.Generic.Downloading.Title-Color-Alt", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Downloading.Title-Color-Alt", "&3"));
lang.set("Interface.Generic.Downloading.Response", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Downloading.Response", "&eWaiting for response"));
lang.set("Interface.Generic.Invalid-Permission", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Generic.Invalid-Permission", "&4You need &n$str$"));
lang.set("Interface.Proxy-Menu.Proxy-Player-Count", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Proxy-Menu.Proxy-Player-Count", "&2$int$ Player(s) Online"));
lang.set("Interface.Proxy-Menu.Proxy-Master", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Proxy-Menu.Proxy-Master", "&8Master Proxy"));
lang.set("Interface.Proxy-Menu.Proxy-SubData", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Proxy-Menu.Proxy-SubData", "&9SubData Only"));
lang.set("Interface.Proxy-Menu.Proxy-Redis", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Proxy-Menu.Proxy-Redis", "&7Redis Only"));
lang.set("Interface.Proxy-Menu.Proxy-Disconnected", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Proxy-Menu.Proxy-Disconnected", "&4Disconnected"));
lang.set("Interface.Host-Menu.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Title", "Host Menu"));
lang.set("Interface.Host-Menu.Host-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Host-Unavailable", "&4Unavailable"));
lang.set("Interface.Host-Menu.Host-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Host-Disabled", "&4Disabled"));
lang.set("Interface.Host-Menu.Host-Server-Count", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Host-Server-Count", "&9$int$ Server(s)"));
lang.set("Interface.Host-Menu.No-Hosts", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.No-Hosts", "&c&oThere are No Hosts"));
lang.set("Interface.Host-Menu.Group-Menu", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Group-Menu", "&6&lView Servers by Group"));
lang.set("Interface.Host-Menu.Server-Menu", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Menu.Server-Menu", "&a&lView Servers"));
lang.set("Interface.Host-Admin.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Admin.Title", "Host/$str$"));
lang.set("Interface.Host-Admin.Creator", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Admin.Creator", "&eCreate a SubServer"));
lang.set("Interface.Host-Admin.SubServers", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Admin.SubServers", "&bView SubServers"));
lang.set("Interface.Host-Admin.Plugins", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Admin.Plugins", "&bPlugins..."));
lang.set("Interface.Host-Creator.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Title", "Host/$str$/Create"));
lang.set("Interface.Host-Creator.Edit-Name", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name", "Change Name"));
lang.set("Interface.Host-Creator.Edit-Name.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Title", "&eSubCreator\n&6Enter a Name for this Server"));
lang.set("Interface.Host-Creator.Edit-Name.Message", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Message", "&eSubCreator &6&l\u00BB&e Enter a Name for this Server via Chat"));
lang.set("Interface.Host-Creator.Edit-Name.Exists", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Exists", "&cSubCreator &4&l\u00BB&c There is already a SubServer with that name"));
lang.set("Interface.Host-Creator.Edit-Name.Exists-Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Exists-Title", "&eSubCreator\n&cThere is already a SubServer with that name"));
lang.set("Interface.Host-Creator.Edit-Name.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Invalid", "&cSubCreator &4&l\u00BB&c Invalid Server Name"));
lang.set("Interface.Host-Creator.Edit-Name.Invalid-Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Name.Invalid-Title", "&eSubCreator\n&cInvalid Server Name"));
lang.set("Interface.Host-Creator.Edit-Template", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Template", "Change Server Template"));
lang.set("Interface.Host-Creator.Edit-Template.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Template.Title", "Host/$str$/Templates"));
lang.set("Interface.Host-Creator.Edit-Template.No-Templates", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Template.No-Templates", "&c&oThere are No Templates"));
lang.set("Interface.Host-Creator.Edit-Version", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Version", "Change Server Version"));
lang.set("Interface.Host-Creator.Edit-Version.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Version.Title", "&eSubCreator\n&6Enter a Server Version"));
lang.set("Interface.Host-Creator.Edit-Version.Message", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Version.Message", "&eSubCreator &6&l\u00BB&e Enter a Server Version via Chat"));
lang.set("Interface.Host-Creator.Edit-Port", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Port", "Change Server Port"));
lang.set("Interface.Host-Creator.Edit-Port.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Port.Title", "&eSubCreator\n&6Enter a Port Number"));
lang.set("Interface.Host-Creator.Edit-Port.Message", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Port.Message", "&eSubCreator &6&l\u00BB&e Enter a Port Number via Chat"));
lang.set("Interface.Host-Creator.Edit-Port.Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Port.Invalid", "&cSubCreator &4&l\u00BB&c Invalid Port Number"));
lang.set("Interface.Host-Creator.Edit-Port.Invalid-Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Edit-Port.Invalid-Title", "&eSubCreator\n&cInvalid Port Number"));
lang.set("Interface.Host-Creator.Submit", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Submit", "&eCreate SubServer"));
lang.set("Interface.Host-Creator.Form-Incomplete", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Creator.Form-Incomplete", "&4Buttons above must be green"));
lang.set("Interface.Host-Plugin.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Plugin.Title", "Host/$str$/Plugins"));
lang.set("Interface.Host-Plugin.No-Plugins", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-Plugin.No-Plugins", "&c&oThere are No Plugins Available"));
lang.set("Interface.Host-SubServer.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Host-SubServer.Title", "Host/$str$/SubServers"));
lang.set("Interface.Group-Menu.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Group-Menu.Title", "Group Menu"));
lang.set("Interface.Group-Menu.Group-Server-Count", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Group-Menu.Group-Server-Count", "&9$int$ Server(s)"));
lang.set("Interface.Group-Menu.No-Groups", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Group-Menu.No-Groups", "&c&oThere are No Groups"));
lang.set("Interface.Group-Menu.Server-Menu", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Group-Menu.Server-Menu", "&a&lView All Servers"));
lang.set("Interface.Group-SubServer.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Group-SubServer.Title", "Group/$str$/Servers"));
lang.set("Interface.Server-Menu.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.Title", "Server Menu"));
lang.set("Interface.Server-Menu.Server-Player-Count", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.Server-Player-Count", "&2$int$ Player(s) Online"));
lang.set("Interface.Server-Menu.Server-External", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.Server-External", "&7External Server"));
lang.set("Interface.Server-Menu.SubServer-Temporary", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Temporary", "&9Temporary"));
lang.set("Interface.Server-Menu.SubServer-Offline", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Offline", "&6Offline"));
lang.set("Interface.Server-Menu.SubServer-Incompatible", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Incompatible", "&4Incompatible with $str$"));
lang.set("Interface.Server-Menu.SubServer-Unavailable", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Unavailable", "&4Unavailable"));
lang.set("Interface.Server-Menu.SubServer-Disabled", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Disabled", "&4Disabled"));
lang.set("Interface.Server-Menu.SubServer-Invalid", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.SubServer-Invalid", "&4Cannot be managed by SubServers"));
lang.set("Interface.Server-Menu.No-Servers", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.No-Servers", "&c&oThere are No Servers"));
lang.set("Interface.Server-Menu.Host-Menu", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.Server-Menu.Host-Menu", "&b&lView Hosts"));
lang.set("Interface.SubServer-Admin.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Title", "SubServer/$str$"));
lang.set("Interface.SubServer-Admin.Start", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Start", "&aStart SubServer"));
lang.set("Interface.SubServer-Admin.Start.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Start.Title", "&aStarting SubServer"));
lang.set("Interface.SubServer-Admin.Stop", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Stop", "&cStop SubServer"));
lang.set("Interface.SubServer-Admin.Stop.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Stop.Title", "&cStopping $str$"));
lang.set("Interface.SubServer-Admin.Terminate", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Terminate", "&4Terminate SubServer"));
lang.set("Interface.SubServer-Admin.Terminate.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Terminate.Title", "&cTerminating $str$"));
lang.set("Interface.SubServer-Admin.Command", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Command", "&bSend a Command to the SubServer"));
lang.set("Interface.SubServer-Admin.Command.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Command.Title", "&eSubServers\n&6Enter a Command to send via Chat"));
lang.set("Interface.SubServer-Admin.Command.Message", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Command.Message", "&eSubServers &6&l\u00BB&e Enter a Command to send via Chat"));
lang.set("Interface.SubServer-Admin.Update", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Update", "&eUpdate SubServer"));
lang.set("Interface.SubServer-Admin.Update.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Update.Title", "&eSubServers\n&6Enter a Server Version to update to"));
lang.set("Interface.SubServer-Admin.Update.Message", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Update.Message", "&eSubServers &6&l\u00BB&e Enter a Server Version to update to via Chat"));
lang.set("Interface.SubServer-Admin.Plugins", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Admin.Plugins", "&bPlugins..."));
lang.set("Interface.SubServer-Plugin.Title", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Plugin.Title", "SubServer/$str$/Plugins"));
lang.set("Interface.SubServer-Plugin.No-Plugins", updated.getMap("Lang", new YAMLSection()).getRawString("Interface.SubServer-Plugin.No-Plugins", "&c&oThere are No Plugins Available"));
rewritten.set("Lang", lang);
config.set(rewritten);
config.save();
}
}
}

View File

@ -6,6 +6,7 @@ import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.api.ChatColor;
import java.net.InetAddress;
@ -27,8 +28,7 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
* @param plugin SubPlugin
*/
public PacketAddServer(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -56,26 +56,26 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
try {
String name = data.getRawString(0x0001);
String name = data.getString(0x0001);
boolean subserver = data.getBoolean(0x0002);
ObjectMap<String> opt = new ObjectMap<>((Map<String, ?>)data.getObject(0x0003));
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
if (plugin.api.getServers().keySet().contains(name.toLowerCase())) {
if (plugin.api.getServers().containsKey(name.toLowerCase())) {
client.sendPacket(new PacketAddServer(3, tracker));
} else {
if (!subserver) {
if (plugin.api.addServer(player, name, InetAddress.getByName(opt.getRawString("address").split(":")[0]), Integer.parseInt(opt.getRawString("address").split(":")[1]),
ChatColor.translateAlternateColorCodes('&', opt.getString("motd")), opt.getBoolean("hidden"), opt.getBoolean("restricted")) != null) {
if (plugin.api.addServer(player, name, InetAddress.getByName(opt.getString("address").split(":")[0]), Integer.parseInt(opt.getString("address").split(":")[1]),
ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(opt.getString("motd"))), opt.getBoolean("hidden"), opt.getBoolean("restricted")) != null) {
client.sendPacket(new PacketAddServer(0, tracker));
} else {
client.sendPacket(new PacketAddServer(1, tracker));
}
} else if (!plugin.api.getHosts().keySet().contains(opt.getRawString("host").toLowerCase())) {
} else if (!plugin.api.getHosts().containsKey(opt.getString("host").toLowerCase())) {
client.sendPacket(new PacketAddServer(4, tracker));
} else {
if (plugin.api.getHost(opt.getRawString("host")).addSubServer(player, name, opt.getBoolean("enabled"), opt.getInt("port"), ChatColor.translateAlternateColorCodes('&', opt.getString("motd")),
opt.getBoolean("log"), opt.getRawString("dir"), opt.getRawString("exec"), opt.getRawString("stop-cmd"), opt.getBoolean("hidden"), opt.getBoolean("restricted")) != null) {
if (plugin.api.getHost(opt.getString("host")).addSubServer(player, name, opt.getBoolean("enabled"), opt.getInt("port"), ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(opt.getString("motd"))),
opt.getBoolean("log"), opt.getString("dir"), opt.getString("exec"), opt.getString("stop-cmd"), opt.getBoolean("hidden"), opt.getBoolean("restricted")) != null) {
client.sendPacket(new PacketAddServer(0, tracker));
} else {
client.sendPacket(new PacketAddServer(1, tracker));
@ -87,9 +87,4 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,6 +1,5 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
@ -9,12 +8,13 @@ import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Check Permission Packet
*/
public class PacketCheckPermission implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
static HashMap<UUID, Callback<Boolean>[]> callbacks = new HashMap<UUID, Callback<Boolean>[]>();
static HashMap<UUID, Consumer<Boolean>[]> callbacks = new HashMap<UUID, Consumer<Boolean>[]>();
private UUID player;
private String permission;
private UUID tracker;
@ -32,7 +32,7 @@ public class PacketCheckPermission implements PacketObjectIn<Integer>, PacketObj
* @param callback Callbacks
*/
@SafeVarargs
public PacketCheckPermission(UUID player, String permission, Callback<Boolean>... callback) {
public PacketCheckPermission(UUID player, String permission, Consumer<Boolean>... callback) {
this.player = player;
this.permission = permission;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
@ -50,11 +50,6 @@ public class PacketCheckPermission implements PacketObjectIn<Integer>, PacketObj
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) throws Throwable {
client.sendPacket(new PacketCheckPermissionResponse(data.getUUID(0x0001), data.getRawString(0x0002), (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
client.sendPacket(new PacketCheckPermissionResponse(data.getUUID(0x0001), data.getString(0x0002), (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -1,14 +1,15 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.md_5.bungee.api.ProxyServer;
import java.util.UUID;
import java.util.function.Consumer;
import static net.ME1312.SubServers.Bungee.Network.Packet.PacketCheckPermission.callbacks;
@ -33,7 +34,7 @@ public class PacketCheckPermissionResponse implements PacketObjectIn<Integer>, P
* @param tracker Receiver ID
*/
public PacketCheckPermissionResponse(UUID player, String permission, UUID tracker) {
this.result = Util.getDespiteException(() -> ProxyServer.getInstance().getPlayer(player).hasPermission(permission), false);
this.result = Try.all.get(() -> ProxyServer.getInstance().getPlayer(player).hasPermission(permission), false);
this.tracker = tracker;
}
@ -47,12 +48,6 @@ public class PacketCheckPermissionResponse implements PacketObjectIn<Integer>, P
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) throws Throwable {
for (Callback<Boolean> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data.getBoolean(0x0001));
callbacks.remove(data.getUUID(0x0000));
}
@Override
public int version() {
return 0x0001;
for (Consumer<Boolean> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
}
}

View File

@ -1,12 +1,12 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.Map;
@ -26,8 +26,7 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
* @param plugin SubPlugin
*/
public PacketCommandServer(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -51,27 +50,28 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
try {
String server = data.getRawString(0x0001);
String command = data.getRawString(0x0002);
UUID player = (data.contains(0x0003)?data.getUUID(0x0003):null);
String server = data.getString(0x0001);
String command = data.getString(0x0002);
UUID player = (data.contains(0x0003)?data.getUUID(0x0003):null);
UUID target = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!server.equals("*") && !servers.keySet().contains(server.toLowerCase())) {
if (!server.equals("*") && !servers.containsKey(server.toLowerCase())) {
client.sendPacket(new PacketCommandServer(3, tracker));
} else if (!server.equals("*") && !(servers.get(server.toLowerCase()) instanceof SubServer)) {
} else if (!server.equals("*") && !(target == null && servers.get(server.toLowerCase()) instanceof SubServer) && servers.get(server.toLowerCase()).getSubData()[0] == null) {
client.sendPacket(new PacketCommandServer(4, tracker));
} else if (!server.equals("*") && !((SubServer) servers.get(server.toLowerCase())).isRunning()) {
} else if (!server.equals("*") && servers.get(server.toLowerCase()) instanceof SubServer && !((SubServer) servers.get(server.toLowerCase())).isRunning()) {
client.sendPacket(new PacketCommandServer(5, tracker));
} else {
if (server.equals("*")) {
boolean sent = false;
for (Server next : servers.values()) {
if (next instanceof SubServer && ((SubServer) next).isRunning()) {
if (((SubServer) next).command(player, command)) {
sent = true;
}
if (target == null) {
sent |= next.command(player, command);
} else {
sent |= next.command(player, target, command);
}
}
if (sent) {
@ -80,10 +80,10 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
client.sendPacket(new PacketCommandServer(1, tracker));
}
} else {
if (((SubServer) servers.get(server.toLowerCase())).command(player, command)) {
client.sendPacket(new PacketCommandServer(0, tracker));
if (target == null) {
client.sendPacket(new PacketCommandServer((servers.get(server.toLowerCase()).command(player, command))? 0 : 1, tracker));
} else {
client.sendPacket(new PacketCommandServer(1, tracker));
client.sendPacket(new PacketCommandServer((servers.get(server.toLowerCase()).command(player, target, command))? 0 : 1, tracker));
}
}
}
@ -92,9 +92,4 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,11 +1,11 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.UUID;
@ -50,9 +50,9 @@ public class PacketCreateServer implements PacketObjectIn<Integer>, PacketObject
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
try {
String name = data.getRawString(0x0001);
String host = data.getRawString(0x0002);
String template = data.getRawString(0x0003);
String name = data.getString(0x0001);
String host = data.getString(0x0002);
String template = data.getString(0x0003);
Version version = (data.contains(0x0004)?data.getVersion(0x0004):null);
Integer port = (data.contains(0x0005)?data.getInt(0x0005):null);
UUID player = (data.contains(0x0006)?data.getUUID(0x0006):null);
@ -60,15 +60,15 @@ public class PacketCreateServer implements PacketObjectIn<Integer>, PacketObject
if (name.contains(" ")) {
client.sendPacket(new PacketCreateServer(3, tracker));
} else if (plugin.api.getSubServers().keySet().contains(name.toLowerCase()) || SubCreator.isReserved(name)) {
} else if (plugin.api.getSubServers().containsKey(name.toLowerCase()) || SubCreator.isReserved(name)) {
client.sendPacket(new PacketCreateServer(4, tracker));
} else if (!plugin.hosts.keySet().contains(host.toLowerCase())) {
} else if (!plugin.hosts.containsKey(host.toLowerCase())) {
client.sendPacket(new PacketCreateServer(5, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).isAvailable()) {
client.sendPacket(new PacketCreateServer(6, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).isEnabled()) {
client.sendPacket(new PacketCreateServer(7, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplates().keySet().contains(template.toLowerCase())) {
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplates().containsKey(template.toLowerCase())) {
client.sendPacket(new PacketCreateServer(8, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplate(template).isEnabled()) {
client.sendPacket(new PacketCreateServer(9, tracker));
@ -91,9 +91,4 @@ public class PacketCreateServer implements PacketObjectIn<Integer>, PacketObject
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -26,8 +26,7 @@ public class PacketDeleteServer implements PacketObjectIn<Integer>, PacketObject
* @param plugin SubPlugin
*/
public PacketDeleteServer(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -53,13 +52,13 @@ public class PacketDeleteServer implements PacketObjectIn<Integer>, PacketObject
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
try {
String name = data.getRawString(0x0001);
String name = data.getString(0x0001);
boolean recycle = data.getBoolean(0x0002);
boolean force = data.getBoolean(0x0003);
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketDeleteServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketDeleteServer(4, tracker));
@ -99,9 +98,4 @@ public class PacketDeleteServer implements PacketObjectIn<Integer>, PacketObject
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -0,0 +1,101 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Merger;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Proxy;
import net.ME1312.SubServers.Bungee.Host.RemotePlayer;
import net.ME1312.SubServers.Bungee.SubAPI;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.*;
import java.util.function.IntConsumer;
/**
* Disconnect Player Packet
*/
public class PacketDisconnectPlayer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private int response;
private UUID tracker;
/**
* New PacketDisconnectPlayer (In)
*/
public PacketDisconnectPlayer() {
}
/**
* New PacketDisconnectPlayer (Out)
*
* @param response Response ID
* @param tracker Receiver ID
*/
public PacketDisconnectPlayer(int response, UUID tracker) {
this.response = response;
this.tracker = tracker;
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> json = new ObjectMap<Integer>();
if (tracker != null) json.set(0x0000, tracker);
json.set(0x0001, response);
return json;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
run(data.getUUIDList(0x0001), data.contains(0x0002)?data.getString(0x0002):null, i -> {
client.sendPacket(new PacketDisconnectPlayer(i, tracker));
});
}
@SuppressWarnings("deprecation")
public static void run(List<UUID> ids, String reason, IntConsumer callback) {
try {
Container<Integer> failures = new Container<>(0);
HashMap<Proxy, List<UUID>> requests = new HashMap<Proxy, List<UUID>>();
for (UUID id : ids) {
ProxiedPlayer local;
RemotePlayer remote;
if ((local = ProxyServer.getInstance().getPlayer(id)) != null) {
if (reason != null) {
local.disconnect(reason);
} else local.disconnect();
} else if ((remote = SubAPI.getInstance().getRemotePlayer(id)) != null && remote.getProxy().getSubData()[0] != null) {
Proxy proxy = remote.getProxy();
List<UUID> list = requests.getOrDefault(proxy, new ArrayList<>());
list.add(id);
requests.put(proxy, list);
} else {
++failures.value;
}
}
if (requests.size() == 0) {
callback.accept(failures.value);
} else {
Merger merge = new Merger(() -> {
callback.accept(failures.value);
});
for (Map.Entry<Proxy, List<UUID>> entry : requests.entrySet()) {
merge.reserve();
((SubDataClient) entry.getKey().getSubData()[0]).sendPacket(new PacketExDisconnectPlayer(entry.getValue(), reason, r -> {
failures.value += r.getInt(0x0001);
merge.release();
}));
}
}
} catch (Throwable e) {
e.printStackTrace();
callback.accept(-1);
}
}
}

View File

@ -1,21 +1,21 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.UUID;
import java.util.*;
/**
* Download Group Info Packet
*/
public class PacketDownloadGroupInfo implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private String group;
private String[] groups;
private UUID tracker;
/**
@ -24,51 +24,58 @@ public class PacketDownloadGroupInfo implements PacketObjectIn<Integer>, PacketO
* @param plugin SubPlugin
*/
public PacketDownloadGroupInfo(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketDownloadGroupInfo (Out)
*
* @param plugin SubPlugin
* @param group Group (or null for all)
* @param groups Groups (or null for all)
* @param tracker Receiver ID
*/
public PacketDownloadGroupInfo(SubProxy plugin, String group, UUID tracker) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.group = group;
public PacketDownloadGroupInfo(SubProxy plugin, List<String> groups, UUID tracker) {
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (groups != null) {
this.groups = new String[groups.size()];
for (int i = 0; i < this.groups.length; ++i) this.groups[i] = groups.get(i).toLowerCase();
Arrays.sort(this.groups);
}
}
@SuppressWarnings("unchecked")
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
if (tracker != null) data.set(0x0000, tracker);
ObjectMap<String> groups = new ObjectMap<String>();
for (String group : plugin.api.getGroups().keySet()) {
if (this.group == null || this.group.length() <= 0 || this.group.equalsIgnoreCase(group)) {
ObjectMap<String> servers = new ObjectMap<String>();
for (Server server : plugin.api.getGroup(group)) {
servers.set(server.getName(), server.forSubData());
if (this.groups == null || this.groups.length > 0) {
ObjectMap<String> groups = new ObjectMap<String>();
for (Map.Entry<String, List<Server>> group : plugin.api.getGroups().entrySet()) {
if (this.groups == null || Arrays.binarySearch(this.groups, group.getKey().toLowerCase()) >= 0) {
ObjectMap<String> servers = new ObjectMap<String>();
for (Server server : group.getValue()) {
servers.set(server.getName(), server.forSubData());
}
groups.set(group.getKey(), servers);
}
groups.set(group, servers);
}
data.set(0x0001, groups);
} else {
ObjectMap<String> ungrouped = new ObjectMap<String>();
for (Server server : plugin.api.getServers().values()) {
if (server.getGroups().size() <= 0) ungrouped.set(server.getName(), server.forSubData());
}
data.set(0x0001, Collections.emptyMap());
data.set(0x0002, ungrouped);
}
data.set(0x0001, groups);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadGroupInfo(plugin, (data.contains(0x0001))?data.getRawString(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
client.sendPacket(new PacketDownloadGroupInfo(plugin, (data.contains(0x0001))?data.getStringList(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -1,13 +1,15 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Host;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
@ -15,7 +17,7 @@ import java.util.UUID;
*/
public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private String host;
private String[] hosts;
private UUID tracker;
/**
@ -24,25 +26,27 @@ public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketOb
* @param plugin SubPlugin
*/
public PacketDownloadHostInfo(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketDownloadHostInfo (Out)
*
* @param plugin SubPlugin
* @param host Host (or null for all)
* @param hosts Hosts (or null for all)
* @param tracker Receiver ID
*/
public PacketDownloadHostInfo(SubProxy plugin, String host, UUID tracker) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.host = host;
public PacketDownloadHostInfo(SubProxy plugin, List<String> hosts, UUID tracker) {
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (hosts != null) {
this.hosts = new String[hosts.size()];
for (int i = 0; i < this.hosts.length; ++i) this.hosts[i] = hosts.get(i).toLowerCase();
Arrays.sort(this.hosts);
}
}
@SuppressWarnings("unchecked")
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
@ -50,7 +54,7 @@ public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketOb
ObjectMap<String> hosts = new ObjectMap<String>();
for (Host host : plugin.api.getHosts().values()) {
if (this.host == null || this.host.length() <= 0 || this.host.equalsIgnoreCase(host.getName())) {
if (this.hosts == null || this.hosts.length <= 0 || Arrays.binarySearch(this.hosts, host.getName().toLowerCase()) >= 0) {
hosts.set(host.getName(), host.forSubData());
}
}
@ -60,11 +64,6 @@ public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketOb
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadHostInfo(plugin, (data.contains(0x0001))?data.getRawString(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
client.sendPacket(new PacketDownloadHostInfo(plugin, (data.contains(0x0001))?data.getStringList(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -1,9 +1,9 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.LinkedHashMap;
@ -52,9 +52,4 @@ public class PacketDownloadLang implements PacketObjectIn<Integer>, PacketObject
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadLang(plugin, (data != null && data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,11 +1,12 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.api.config.ListenerInfo;
import java.util.LinkedList;
@ -43,13 +44,18 @@ public class PacketDownloadPlatformInfo implements PacketObjectIn<Integer>, Pack
ObjectMap<Integer> data = new ObjectMap<Integer>();
if (tracker != null) data.set(0x0000, tracker);
ObjectMap<String> info = new ObjectMap<String>();
ObjectMap<String> subservers = new ObjectMap<String>();
subservers.set("version", plugin.api.getWrapperVersion().toString());
if (plugin.api.getWrapperBuild() != null) subservers.set("build", plugin.api.getWrapperBuild().toString());
subservers.set("last-reload", plugin.resetDate);
subservers.set("proxies", plugin.api.getProxies().size());
subservers.set("hosts", plugin.api.getHosts().size());
subservers.set("subservers", plugin.api.getSubServers().size());
info.set("subservers", subservers);
ObjectMap<String> bungee = new ObjectMap<String>();
bungee.set("version", plugin.api.getProxyVersion().toString());
bungee.set("disabled-cmds", plugin.getConfig().getDisabledCommands());
@ -66,12 +72,16 @@ public class PacketDownloadPlatformInfo implements PacketObjectIn<Integer>, Pack
}
bungee.set("listeners", listeners);
info.set("bungee", bungee);
ObjectMap<String> minecraft = new ObjectMap<String>();
LinkedList<String> mcversions = new LinkedList<String>();
for (Version version : plugin.api.getGameVersion()) mcversions.add(version.toString());
minecraft.set("version", mcversions);
minecraft.set("players", plugin.api.getGlobalPlayers().size());
minecraft.set("players", plugin.api.getRemotePlayers().size());
info.set("minecraft", minecraft);
ObjectMap<String> system = new ObjectMap<String>();
ObjectMap<String> os = new ObjectMap<String>();
os.set("name", System.getProperty("os.name"));
@ -81,6 +91,8 @@ public class PacketDownloadPlatformInfo implements PacketObjectIn<Integer>, Pack
java.set("version", System.getProperty("java.version"));
system.set("java", java);
info.set("system", system);
data.set(0x0001, info);
return data;
}
@ -89,9 +101,4 @@ public class PacketDownloadPlatformInfo implements PacketObjectIn<Integer>, Pack
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadPlatformInfo(plugin, (data != null && data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -0,0 +1,82 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.RemotePlayer;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.List;
import java.util.UUID;
/**
* Download Player Info Packet
*/
public class PacketDownloadPlayerInfo implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private String[] names;
private UUID[] ids;
private UUID tracker;
/**
* New PacketDownloadPlayerInfo (In)
*
* @param plugin SubPlugin
*/
public PacketDownloadPlayerInfo(SubProxy plugin) {
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketDownloadPlayerInfo (Out)
*
* @param plugin SubPlugin
* @param names Player names (or null for all)
* @param ids Player IDs (or null for all)
* @param tracker Receiver ID
*/
public PacketDownloadPlayerInfo(SubProxy plugin, List<String> names, List<UUID> ids, UUID tracker) {
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (ids != null) {
this.ids = new UUID[ids.size()];
for (int i = 0; i < this.ids.length; ++i) this.ids[i] = ids.get(i);
}
if (names != null) {
this.names = new String[names.size()];
for (int i = 0; i < this.names.length; ++i) this.names[i] = names.get(i);
}
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
if (tracker != null) data.set(0x0000, tracker);
ObjectMap<String> players = new ObjectMap<String>();
if (ids == null && names == null) {
for (RemotePlayer player : plugin.api.getRemotePlayers().values()) {
players.set(player.getUniqueId().toString(), player.forSubData());
}
} else {
if (ids != null) for (UUID id : ids) {
RemotePlayer player = plugin.api.getRemotePlayer(id);
if (player != null) players.set(player.getUniqueId().toString(), player.forSubData());
}
if (names != null) for (String name : names) {
RemotePlayer player = plugin.api.getRemotePlayer(name);
if (player != null) players.set(player.getUniqueId().toString(), player.forSubData());
}
}
data.set(0x0001, players);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadPlayerInfo(plugin, (data.contains(0x0001))?data.getStringList(0x0001):null, (data.contains(0x0002))?data.getUUIDList(0x0002):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -1,76 +0,0 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.NamedContainer;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubServers.Bungee.SubProxy;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.UUID;
/**
* Download Player List Packet
*/
public class PacketDownloadPlayerList implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private UUID tracker;
/**
* New PacketDownloadPlayerList (In)
*
* @param plugin SubPlugin
*/
public PacketDownloadPlayerList(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
}
/**
* New PacketDownloadPlayerList (Out)
*
* @param plugin SubPlugin
* @param tracker Receiver ID
*/
public PacketDownloadPlayerList(SubProxy plugin, UUID tracker) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.tracker = tracker;
}
@SuppressWarnings("unchecked")
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
if (tracker != null) data.set(0x0000, tracker);
ObjectMap<String> players = new ObjectMap<String>();
for (NamedContainer<String, UUID> player : plugin.api.getGlobalPlayers()) {
ObjectMap<String> pinfo = new ObjectMap<String>();
pinfo.set("name", player.get());
if (plugin.redis != null) {
try {
pinfo.set("server", ((ServerInfo) plugin.redis("getServerFor", new NamedContainer<>(UUID.class, player.get()))).getName());
} catch (Exception e) {
e.printStackTrace();
}
} else {
pinfo.set("server", plugin.getPlayer(player.get()).getServer().getInfo().getName());
}
players.set(player.get().toString(), pinfo);
}
data.set(0x0001, players);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadPlayerList(plugin, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,13 +1,15 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Proxy;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Proxy;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
@ -15,7 +17,7 @@ import java.util.UUID;
*/
public class PacketDownloadProxyInfo implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private String proxy;
private String[] proxies;
private UUID tracker;
/**
@ -24,25 +26,27 @@ public class PacketDownloadProxyInfo implements PacketObjectIn<Integer>, PacketO
* @param plugin SubPlugin
*/
public PacketDownloadProxyInfo(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketDownloadProxyInfo (Out)
*
* @param plugin SubPlugin
* @param proxy Proxy (or null for all)
* @param proxies Proxies (or null for all)
* @param tracker Receiver ID
*/
public PacketDownloadProxyInfo(SubProxy plugin, String proxy, UUID tracker) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.proxy = proxy;
public PacketDownloadProxyInfo(SubProxy plugin, List<String> proxies, UUID tracker) {
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (proxies != null) {
this.proxies = new String[proxies.size()];
for (int i = 0; i < this.proxies.length; ++i) this.proxies[i] = proxies.get(i).toLowerCase();
Arrays.sort(this.proxies);
}
}
@SuppressWarnings("unchecked")
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
@ -50,22 +54,19 @@ public class PacketDownloadProxyInfo implements PacketObjectIn<Integer>, PacketO
ObjectMap<String> proxies = new ObjectMap<String>();
for (Proxy proxy : plugin.api.getProxies().values()) {
if (this.proxy == null || this.proxy.equalsIgnoreCase(proxy.getName())) {
if (this.proxies == null || Arrays.binarySearch(this.proxies, proxy.getName().toLowerCase()) >= 0) {
proxies.set(proxy.getName(), proxy.forSubData());
}
}
data.set(0x0001, proxies);
if ((this.proxy == null || this.proxy.length() <= 0) && plugin.api.getMasterProxy() != null) data.set(0x0002, plugin.api.getMasterProxy().forSubData());
if (this.proxies != null && plugin.api.getMasterProxy() != null && (this.proxies.length <= 0 || Arrays.binarySearch(this.proxies, plugin.api.getMasterProxy().getName().toLowerCase()) >= 0)) {
data.set(0x0002, plugin.api.getMasterProxy().forSubData());
}
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadProxyInfo(plugin, (data.contains(0x0001))?data.getRawString(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
client.sendPacket(new PacketDownloadProxyInfo(plugin, (data.contains(0x0001))?data.getStringList(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -1,13 +1,15 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.Server;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
@ -15,7 +17,7 @@ import java.util.UUID;
*/
public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private String server;
private String[] servers;
private UUID tracker;
/**
@ -24,25 +26,27 @@ public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, Packet
* @param plugin SubPlugin
*/
public PacketDownloadServerInfo(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketDownloadServerInfo (Out)
*
* @param plugin SubPlugin
* @param server Server (or null for all)
* @param servers Servers (or null for all)
* @param tracker Receiver ID
*/
public PacketDownloadServerInfo(SubProxy plugin, String server, UUID tracker) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.server = server;
public PacketDownloadServerInfo(SubProxy plugin, List<String> servers, UUID tracker) {
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (servers != null) {
this.servers = new String[servers.size()];
for (int i = 0; i < this.servers.length; ++i) this.servers[i] = servers.get(i).toLowerCase();
Arrays.sort(this.servers);
}
}
@SuppressWarnings("unchecked")
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
@ -50,7 +54,7 @@ public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, Packet
ObjectMap<String> servers = new ObjectMap<String>();
for (Server server : plugin.api.getServers().values()) {
if (this.server == null || this.server.length() <= 0 || this.server.equalsIgnoreCase(server.getName())) {
if (this.servers == null || this.servers.length <= 0 || Arrays.binarySearch(this.servers, server.getName().toLowerCase()) >= 0) {
servers.set(server.getName(), server.forSubData());
}
}
@ -60,11 +64,6 @@ public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, Packet
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
client.sendPacket(new PacketDownloadServerInfo(plugin, (data.contains(0x0001))?data.getRawString(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
@Override
public int version() {
return 0x0001;
client.sendPacket(new PacketDownloadServerInfo(plugin, (data.contains(0x0001))?data.getStringList(0x0001):null, (data.contains(0x0000))?data.getUUID(0x0000):null));
}
}

View File

@ -27,8 +27,7 @@ public class PacketEditServer implements PacketObjectIn<Integer>, PacketObjectOu
* @param plugin SubPlugin
*/
public PacketEditServer(SubProxy plugin) {
if (Util.isNull(plugin)) throw new NullPointerException();
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -68,13 +67,13 @@ public class PacketEditServer implements PacketObjectIn<Integer>, PacketObjectOu
public void receive(SubDataClient client, ObjectMap<Integer> data) {
UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null);
try {
String name = data.getRawString(0x0001);
String name = data.getString(0x0001);
ObjectMap<String> edit = new ObjectMap<>((Map<String, ?>)data.getObject(0x0002));
boolean perma = data.getBoolean(0x0003);
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketEditServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketEditServer(4, tracker));
@ -96,9 +95,4 @@ public class PacketEditServer implements PacketObjectIn<Integer>, PacketObjectOu
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,20 +1,21 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.External.ExternalSubServer;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Add Server External Host Packet
*/
public class PacketExAddServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Callback<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Callback<ObjectMap<Integer>>[]>();
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private String name;
private boolean enabled;
private int port;
@ -32,32 +33,30 @@ public class PacketExAddServer implements PacketObjectIn<Integer>, PacketObjectO
/**
* New PacketExAddServer (Out)
*
* @param name Name of Server
* @param enabled Enabled Status
* @param log Logging Status
* @param directory Directory
* @param executable Executable
*/
@SafeVarargs
public PacketExAddServer(String name, boolean enabled, int port, boolean log, String directory, String executable, String stopcmd, UUID running, Callback<ObjectMap<Integer>>... callback) {
if (Util.isNull(name, enabled, log, directory, executable, callback)) throw new NullPointerException();
this.name = name;
this.enabled = enabled;
this.port = port;
this.log = log;
this.directory = directory;
this.executable = executable;
this.stopcmd = stopcmd;
public PacketExAddServer(ExternalSubServer server, UUID running, Consumer<ObjectMap<Integer>>... callback) {
if (callback == null) throw new NullPointerException();
this.name = server.getName();
this.enabled = server.isEnabled();
this.port = server.getAddress().getPort();
this.log = server.isLogging();
this.directory = server.getPath();
this.executable = server.getExecutable();
this.stopcmd = server.getStopCommand();
this.running = running;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(tracker, callback);
}
public String peek() {
return name;
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
if (tracker != null) data.set(0x0000, tracker);
data.set(0x0000, tracker);
data.set(0x0001, name);
data.set(0x0002, enabled);
data.set(0x0003, port);
@ -65,18 +64,12 @@ public class PacketExAddServer implements PacketObjectIn<Integer>, PacketObjectO
data.set(0x0005, directory);
data.set(0x0006, executable);
data.set(0x0007, stopcmd);
if (running != null) data.set(0x0008, running.toString());
if (running != null) data.set(0x0008, running);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Callback<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data);
callbacks.remove(data.getUUID(0x0000));
}
@Override
public int version() {
return 0x0001;
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -1,17 +1,19 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubServers.Bungee.Host.External.ExternalHost;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketIn;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.External.ExternalHost;
import net.ME1312.SubServers.Bungee.Host.External.ExternalSubCreator;
import net.ME1312.SubServers.Bungee.SubProxy;
/**
* External Host Configuration Packet
*/
public class PacketExConfigureHost implements PacketIn, PacketObjectOut<Integer> {
public class PacketExConfigureHost implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private ExternalHost host;
@ -34,30 +36,15 @@ public class PacketExConfigureHost implements PacketIn, PacketObjectOut<Integer>
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, plugin.config.get().getMap("Hosts").getMap(host.getName()).clone());
ObjectMap<String> templates = new ObjectMap<String>();
for (SubCreator.ServerTemplate template : host.getCreator().getTemplates().values()) {
ObjectMap<String> tinfo = new ObjectMap<String>();
tinfo.set("enabled", template.isEnabled());
tinfo.set("display", template.getDisplayName());
tinfo.set("icon", template.getIcon());
tinfo.set("build", template.getBuildOptions().clone());
tinfo.set("settings", template.getConfigOptions().clone());
templates.set(template.getName(), tinfo);
}
data.set(0x0001, templates);
return data;
}
@SuppressWarnings("unchecked")
@Override
public void receive(SubDataClient client) {
public void receive(SubDataClient client, ObjectMap<Integer> data) {
if (client.getHandler() != null && client.getHandler() instanceof ExternalHost && plugin.config.get().getMap("Hosts").getKeys().contains(((ExternalHost) client.getHandler()).getName())) {
client.sendPacket(new PacketExConfigureHost(plugin, (ExternalHost) client.getHandler()));
Try.all.run(() -> Util.reflect(ExternalSubCreator.class.getDeclaredField("enableRT"), ((ExternalHost) client.getHandler()).getCreator(), ((data == null || data.getBoolean(0x0000, false))?null:false)));
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -0,0 +1,56 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* External Player Control Packet
*/
public class PacketExControlPlayer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private String command;
private UUID target;
private UUID tracker;
/**
* New PacketExControlPlayer (In)
*/
public PacketExControlPlayer() {}
/**
* New PacketExControlPlayer (Out)
*
* @param target Target Player
* @param command Command to send
* @param callback Callbacks
*/
@SafeVarargs
public PacketExControlPlayer(UUID target, String command, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(command, callback);
this.target = target;
this.command = command;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(tracker, callback);
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, tracker);
data.set(0x0001, command);
if (target != null) data.set(0x0002, target);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -1,26 +1,26 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.External.ExternalSubServer;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.util.Arrays;
/**
* Edit External Server Packet
* Control External Server Packet
*/
public class PacketExEditServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
public class PacketExControlServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubProxy plugin;
private SubServer server;
private UpdateType type;
private Action type;
private Object[] args;
public enum UpdateType {
public enum Action {
// Actions
START(1, String.class),
COMMAND(2, String.class),
@ -35,7 +35,7 @@ public class PacketExEditServer implements PacketObjectIn<Integer>, PacketObject
private short value;
private Class<?>[] args;
UpdateType(int value, Class<?>... args) {
Action(int value, Class<?>... args) {
this.value = (short) value;
this.args = args;
}
@ -50,30 +50,31 @@ public class PacketExEditServer implements PacketObjectIn<Integer>, PacketObject
}
/**
* New PacketExEditServer (In)
* New PacketExControlServer (In)
* @param plugin SubPlugin
*/
public PacketExEditServer(SubProxy plugin) {
public PacketExControlServer(SubProxy plugin) {
this.plugin = plugin;
}
/**
* New PacketExEditServer (Out)
* New PacketExControlServer (Out)
*
* @param server SubServer
* @param type Update Type
* @param arguments Arguments
*/
public PacketExEditServer(SubServer server, UpdateType type, Object... arguments) {
if (arguments.length != type.getArguments().length) throw new IllegalArgumentException(((arguments.length > type.getArguments().length)?"Too many":"Not enough") + " arguments for type: " + type.toString());
int i = 0;
while (i < arguments.length) {
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getCanonicalName());
i++;
}
public PacketExControlServer(SubServer server, Action type, Object... arguments) {
if (arguments.length < type.getArguments().length) throw new IllegalArgumentException("Not enough arguments for type: " + type);
this.server = server;
this.type = type;
this.args = arguments;
this.args = new Object[type.getArguments().length];
for (int i = 0; i < type.getArguments().length; ++i) {
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getTypeName());
args[i] = arguments[i];
}
}
@Override
@ -88,7 +89,7 @@ public class PacketExEditServer implements PacketObjectIn<Integer>, PacketObject
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
try {
ExternalSubServer server = (ExternalSubServer) plugin.api.getSubServer(data.getRawString(0x0000));
ExternalSubServer server = (ExternalSubServer) plugin.api.getSubServer(data.getString(0x0000));
switch (data.getInt(0x0001)) {
case 1:
Util.reflect(ExternalSubServer.class.getDeclaredMethod("falsestart"), server);
@ -101,9 +102,4 @@ public class PacketExEditServer implements PacketObjectIn<Integer>, PacketObject
e.printStackTrace();
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -1,28 +1,29 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.SubCreator;
import net.ME1312.SubServers.Bungee.Host.SubServer;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Create Server External Host Packet
*/
public class PacketExCreateServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Callback<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Callback<ObjectMap<Integer>>[]>();
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private UUID player;
private String name;
private SubCreator.ServerTemplate template;
private Version version;
private int port;
private String dir;
private Boolean mode;
private UUID log;
private UUID tracker = null;
@ -36,19 +37,22 @@ public class PacketExCreateServer implements PacketObjectIn<Integer>, PacketObje
/**
* New PacketExCreateServer (Out)
*
* @param player Player
* @param server Server to Update
* @param template Server Template
* @param version Server Version
* @param log Log Address
* @param callback Callbacks
*/
@SafeVarargs
public PacketExCreateServer(SubServer server, Version version, UUID log, Callback<ObjectMap<Integer>>... callback) {
if (Util.isNull(server, log, callback)) throw new NullPointerException();
public PacketExCreateServer(UUID player, SubServer server, SubCreator.ServerTemplate template, Version version, UUID log, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(server, template, log, callback);
this.player = player;
this.name = server.getName();
this.template = server.getTemplate();
this.template = template;
this.version = version;
this.port = server.getAddress().getPort();
this.dir = server.getPath();
this.mode = template == server.getTemplate();
this.log = log;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(tracker, callback);
@ -57,22 +61,23 @@ public class PacketExCreateServer implements PacketObjectIn<Integer>, PacketObje
/**
* New PacketExCreateServer (Out)
*
* @param player Player
* @param name Server Name
* @param template Server Template
* @param version Server Version
* @param port Server Port Number
* @param directory Server Directory
* @param log Log Address
* @param callback Callbacks
*/
@SafeVarargs
public PacketExCreateServer(String name, SubCreator.ServerTemplate template, Version version, int port, String directory, UUID log, Callback<ObjectMap<Integer>>... callback) {
if (Util.isNull(name, template, port, log, callback)) throw new NullPointerException();
public PacketExCreateServer(UUID player, String name, SubCreator.ServerTemplate template, Version version, int port, UUID log, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(name, template, port, log, callback);
this.player = player;
this.name = name;
this.template = template;
this.version = version;
this.port = port;
this.dir = directory;
this.mode = null;
this.log = log;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(tracker, callback);
@ -86,23 +91,32 @@ public class PacketExCreateServer implements PacketObjectIn<Integer>, PacketObje
} else {
data.set(0x0000, tracker);
data.set(0x0002, name);
data.set(0x0003, template.getName());
if (template.isDynamic()) {
ObjectMap<String> template = new ObjectMap<>();
template.set("name", this.template.getName());
template.set("display", this.template.getDisplayName());
template.set("enabled", this.template.isEnabled());
template.set("icon", this.template.getIcon());
template.set("dir", this.template.getDirectory().toString());
template.set("build", this.template.getBuildOptions().clone());
template.set("def", this.template.getConfigOptions().clone());
data.set(0x0003, template);
} else {
data.set(0x0003, template.getName());
}
data.set(0x0004, version);
data.set(0x0005, port);
data.set(0x0006, dir);
data.set(0x0007, log);
data.set(0x0006, log);
if (mode != null)
data.set(0x0007, mode);
if (player != null)
data.set(0x0008, player);
}
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Callback<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data);
callbacks.remove(data.getUUID(0x0000));
}
@Override
public int version() {
return 0x0001;
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -1,20 +1,20 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Delete Server External Host Packet
*/
public class PacketExDeleteServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Callback<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Callback<ObjectMap<Integer>>[]>();
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private String name;
private ObjectMap<String> info;
private boolean recycle;
@ -33,8 +33,8 @@ public class PacketExDeleteServer implements PacketObjectIn<Integer>, PacketObje
* @param callback Callbacks
*/
@SafeVarargs
public PacketExDeleteServer(String name, ObjectMap<String> info, boolean recycle, Callback<ObjectMap<Integer>>... callback) {
if (Util.isNull(name, info, callback)) throw new NullPointerException();
public PacketExDeleteServer(String name, ObjectMap<String> info, boolean recycle, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(name, info, callback);
this.name = name;
this.info = info;
this.recycle = recycle;
@ -44,26 +44,16 @@ public class PacketExDeleteServer implements PacketObjectIn<Integer>, PacketObje
@Override
public ObjectMap<Integer> send(SubDataClient client) {
if (tracker == null) {
return null;
} else {
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, tracker);
data.set(0x0001, name);
data.set(0x0002, info);
if (recycle) data.set(0x0003, true);
return data;
}
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, tracker);
data.set(0x0001, name);
data.set(0x0002, info);
if (recycle) data.set(0x0003, true);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Callback<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data);
callbacks.remove(data.getUUID(0x0000));
}
@Override
public int version() {
return 0x0001;
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -0,0 +1,57 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Disconnect External Player Packet
*/
public class PacketExDisconnectPlayer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private List<UUID> players;
private String reason;
private UUID id;
/**
* New PacketExDisconnectPlayer (In)
*/
public PacketExDisconnectPlayer() {}
/**
* New PacketExDisconnectPlayer (Out)
*
* @param players Players
* @param reason Reason
* @param callback Callbacks
*/
@SafeVarargs
public PacketExDisconnectPlayer(List<UUID> players, String reason, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(players, callback);
this.players = players;
this.reason = reason;
this.id = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(id, callback);
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, id);
data.set(0x0001, players);
if (reason != null) data.set(0x0002, reason);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -1,15 +1,24 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.UniversalFile;
import net.ME1312.SubServers.Bungee.Host.External.ExternalHost;
import net.ME1312.Galaxi.Library.Directories;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubData.Server.Library.DataSize;
import net.ME1312.SubData.Server.Protocol.PacketIn;
import net.ME1312.SubData.Server.Protocol.PacketStreamOut;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.SubServers.Bungee.Host.External.ExternalHost;
import net.ME1312.SubServers.Bungee.Host.External.ExternalSubCreator;
import net.ME1312.SubServers.Bungee.Host.SubCreator.ServerTemplate;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.SubProxy;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* External Host Template Download Packet
@ -36,8 +45,30 @@ public class PacketExDownloadTemplates implements PacketIn, PacketStreamOut {
@Override
public void send(SubDataClient client, OutputStream stream) throws Throwable {
try {
Util.zip(new UniversalFile(plugin.dir, "SubServers:Templates"), stream);
stream.close();
if (client.getBlockSize() < DataSize.MBB) client.tempBlockSize(DataSize.MBB);
HashMap<String, ServerTemplate> map = Try.all.getOrSupply(() -> Util.reflect(ExternalSubCreator.class.getDeclaredField("templates"), ((ExternalHost) client.getHandler()).getCreator()), HashMap::new);
File dir = new File(plugin.dir, "SubServers/Templates");
ZipOutputStream zip = new ZipOutputStream(stream);
byte[] buffer = new byte[4096];
for (String file : Directories.search(dir)) {
int index = file.indexOf(File.separatorChar);
if (index != -1 && !map.containsKey(file.substring(0, index).toLowerCase())) {
zip.putNextEntry(new ZipEntry(file.replace(File.separatorChar, '/')));
FileInputStream in = new FileInputStream(dir.getAbsolutePath() + File.separator + file);
int len;
while ((len = in.read(buffer)) != -1) {
zip.write(buffer, 0, len);
}
in.close();
}
}
zip.close();
Try.all.run(() -> Util.reflect(ExternalSubCreator.class.getDeclaredField("enableRT"), host.getCreator(), true));
} catch (Exception e) {
Logger.get("SubData").info("Problem encoding template files for Host: " + host.getName());
e.printStackTrace();
@ -50,9 +81,4 @@ public class PacketExDownloadTemplates implements PacketIn, PacketStreamOut {
client.sendPacket(new PacketExDownloadTemplates(plugin, (ExternalHost) client.getHandler()));
}
}
@Override
public int version() {
return 0x0001;
}
}

View File

@ -0,0 +1,59 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Message External Player Packet
*/
public class PacketExMessagePlayer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private List<UUID> players;
private List<String> legacy, raw;
private UUID id;
/**
* New PacketExMessagePlayer (In)
*/
public PacketExMessagePlayer() {}
/**
* New PacketExMessagePlayer (Out)
*
* @param players Players
* @param legacy Messages (Legacy)
* @param raw Messages (JSON)
* @param callback Callbacks
*/
@SafeVarargs
public PacketExMessagePlayer(List<UUID> players, List<String> legacy, List<String> raw, Consumer<ObjectMap<Integer>>... callback) {
this.players = players;
this.legacy = legacy;
this.raw = raw;
this.id = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(id, callback);
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
data.set(0x0000, id);
if (players != null) data.set(0x0001, players);
if (legacy != null) data.set(0x0002, legacy);
if (raw != null) data.set(0x0003, raw);
return data;
}
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -1,20 +1,20 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.SubData.Server.SubDataClient;
import net.ME1312.Galaxi.Library.Callback.Callback;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
import java.util.HashMap;
import java.util.UUID;
import java.util.function.Consumer;
/**
* Create Server External Host Packet
*/
public class PacketExRemoveServer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private static HashMap<UUID, Callback<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Callback<ObjectMap<Integer>>[]>();
private static HashMap<UUID, Consumer<ObjectMap<Integer>>[]> callbacks = new HashMap<UUID, Consumer<ObjectMap<Integer>>[]>();
private String name;
private UUID tracker;
@ -30,8 +30,8 @@ public class PacketExRemoveServer implements PacketObjectIn<Integer>, PacketObje
* @param callback Callbacks
*/
@SafeVarargs
public PacketExRemoveServer(String name, Callback<ObjectMap<Integer>>... callback) {
if (Util.isNull(name, callback)) throw new NullPointerException();
public PacketExRemoveServer(String name, Consumer<ObjectMap<Integer>>... callback) {
Util.nullpo(name, callback);
this.name = name;
this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID);
callbacks.put(tracker, callback);
@ -47,12 +47,6 @@ public class PacketExRemoveServer implements PacketObjectIn<Integer>, PacketObje
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Callback<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data);
callbacks.remove(data.getUUID(0x0000));
}
@Override
public int version() {
return 0x0001;
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

Some files were not shown because too many files have changed in this diff Show More