Compare commits

...

175 Commits

Author SHA1 Message Date
ayunami2000
cd1f0e916d lax said no more fly D: 2022-05-31 14:32:36 -04:00
ayunami2000
c500eeb2d5 update flag 2022-05-18 20:58:43 -04:00
ayunami2000
53e60118ea remove secure mode download 2022-05-18 20:56:06 -04:00
ayunami2000
98713f2760 Merge branch 'LAX1DUDE-main' 2022-05-18 20:51:57 -04:00
ayunami2000
108f34c201 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-05-18 20:51:27 -04:00
LAX1DUDE
0604943075 updated secure mode to 22w20b (update bungee too please) 2022-05-16 23:19:27 -07:00
LAX1DUDE
50b2b9b785 added 22w20b secure mode certificate 2022-05-16 22:09:32 -07:00
LAX1DUDE
7ce8ff5d03 22w20b changed F+6 message, revert minor lag fix 2022-05-16 21:39:13 -07:00
LAX1DUDE
a07883f25a changed F+6 message, revert minor lag fix 2022-05-16 21:38:34 -07:00
LAX1DUDE
2807ac9a10 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft 2022-05-16 21:11:44 -07:00
LAX1DUDE
9bac97828b 22w20a made PNG loading faster, made F+6 hide the coords off the screen, improved buffer flip system 2022-05-16 21:11:37 -07:00
LAX1DUDE
5abca8310b made F+6 hide the coords, improved framebuffer swap system 2022-05-16 21:09:23 -07:00
LAX1DUDE
fb890d77f5 replaced baislsl's PNG decoder with the browser's native PNG decoder 2022-05-15 22:27:31 -07:00
LAX1DUDE
4d4c0de29b
update readme for secure mode info 2022-05-15 02:38:56 -07:00
LAX1DUDE
2c8ca1ec60 made secure offline download 2022-05-15 02:25:38 -07:00
LAX1DUDE
0f13401420 added secure mode downloads 2022-05-15 02:12:01 -07:00
LAX1DUDE
31762ef125 added secure mode certs directory 2022-05-15 01:43:44 -07:00
LAX1DUDE
75c43e8a29 patched bungee issues 2022-05-15 00:20:56 -07:00
LAX1DUDE
e7e763f9f8 22w19a merged ayunami's map PR 2022-05-14 22:57:54 -07:00
LAX1DUDE
a80b0e8d28 added configurable main menu link 2022-05-14 22:50:01 -07:00
LAX1DUDE
75cdac50a4
Merge pull request #163 from LAX1DUDE/image-maps
Image maps
2022-05-14 18:37:04 -07:00
ayunami2000
8d6704b234 Final fix in image mode detection. 2022-04-30 10:00:05 -04:00
ayunami2000
2cfd8965bf Fix sample files. 2022-04-30 09:27:20 -04:00
ayunami2000
ea8f631d15 Fix red and blue being swapped 2022-04-30 09:16:17 -04:00
ayunami2000
ae6a8e8653 Add image element support to maps. 2022-04-30 03:25:34 -04:00
ayunami2000
400e4e4e58 fix assets lol 2022-04-26 20:08:43 -04:00
ayunami2000
9e80cb2e8f Merge branch 'LAX1DUDE-main' 2022-04-26 20:07:52 -04:00
ayunami2000
d897685edb Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-04-26 20:07:14 -04:00
LAX1DUDE
7e3b21f70c 22w16h fixed chunk flickering 2022-04-23 20:03:57 -07:00
LAX1DUDE
3436ffa97c fixed chunk flickering 2022-04-23 20:03:15 -07:00
LAX1DUDE
03d4511523 22w16g improved occlusion query stability (reduced "chunk flickering") 2022-04-22 20:40:37 -07:00
LAX1DUDE
df09eb33b5 22w16f improved occlusion query stability under lag 2022-04-22 13:20:22 -07:00
LAX1DUDE
7659bc095d improved occlusion query stability 2022-04-22 00:26:04 -07:00
LAX1DUDE
b8cf84e97c 22w16d video playback fixes, fixed line endings in unix scripts 2022-04-21 13:17:50 -07:00
LAX1DUDE
8655ed05f0 22w16c fixed sound trigonometry again because I'm a dumbass 2022-04-20 17:47:57 -07:00
LAX1DUDE
3b0229e87b 22w16b fixed sound trigonometry 2022-04-20 17:20:04 -07:00
LAX1DUDE
c2e448a440 22w16a Added MP4 Video playback in maps, fixed 3D audio trigonometry 2022-04-20 05:14:20 -07:00
LAX1DUDE
fd6a37d472 Added MP4 Video playback in maps, fixed 3D audio trigonometry 2022-04-20 05:13:40 -07:00
ayunami2000
d76407b836 disallow play pause buttons lol 2022-04-18 11:29:25 -04:00
ayunami2000
25c61eb4a1 fix invidious api 2022-04-17 13:21:51 -04:00
ayunami2000
ae0ff1579d Merge branch 'LAX1DUDE-main' 2022-04-16 11:25:49 -04:00
ayunami2000
582a3bb925 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-04-16 11:24:41 -04:00
LAX1DUDE
2b48c1a954 22w15d Fixed more texture bleeding, fixed clamping in entity shadows 2022-04-16 01:03:26 -07:00
LAX1DUDE
af82d23f20 Fixed texture bleeding, fixed clamping in entity shadows 2022-04-16 01:01:40 -07:00
LAX1DUDE
1714cb1bda 22w15c Added full RGB map packets for ayunami2000 2022-04-15 22:57:38 -07:00
LAX1DUDE
c2cd26b6a3 Merge branch 'AyunamiMap' 2022-04-15 22:41:04 -07:00
LAX1DUDE
9564621e78 Added full RGB map packets for ayunami2000 2022-04-15 22:38:43 -07:00
LAX1DUDE
e615e1bc9a 22w15b Fixed corrupt color code, fixed 'hide_down' flag for default server list 2022-04-15 14:56:50 -07:00
LAX1DUDE
632fc4bc5d Fixed corrupt color code, fixed 'hide_down' flag for default server list 2022-04-15 14:53:30 -07:00
LAX1DUDE
5e17fe9cc0 22w15a Fixed item shading bug, added 2FA command for ayonull's server list, added 'hide_down' flag to default server list 2022-04-15 01:29:45 -07:00
LAX1DUDE
a91336f03e Added 2FA command for ayonull's server list, added 'hide_down' flag to default server list 2022-04-14 23:28:49 -07:00
LAX1DUDE
ed0af28196 oops 2022-04-14 22:45:13 -07:00
LAX1DUDE
d115c2da03
Update README Screenshot 2022-04-13 23:20:59 -07:00
LAX1DUDE
3c64a115dd
Update README.md 2022-04-13 23:11:31 -07:00
ayunami2000
1a99d20c88 make it so proxy and vanilla protocol are OFF by default 2022-04-10 22:22:08 -04:00
LAX1DUDE
25db198623
Update README.md 2022-04-10 15:44:07 -07:00
LAX1DUDE
59784560f5 22w14d Undo screen flickering glitch (framebuffer swap rate) 2022-04-10 14:27:14 -07:00
LAX1DUDE
3dc8627192 Added note mentioning that file:/// URLs are invalid 2022-04-09 23:06:43 -07:00
LAX1DUDE
767864ad1a 22w14c Made some (maybe) performance changes 2022-04-09 22:43:20 -07:00
ayunami2000
38fa645a25 me when forgor a feature
i forgor 💀
2022-04-09 14:05:25 -04:00
ayunami2000
492c76a1c0 me when dumbass (it was me) 2022-04-09 14:04:23 -04:00
ayunami2000
efce711ed1 fix fard proxy toggle button 2022-04-09 14:02:00 -04:00
ayunami2000
9c61e50041
Merge pull request #9 from ayunami2000/updated
Updated to latest eaglercraft stuff
2022-04-09 13:58:37 -04:00
ayunami2000
939e3a57ef remove now useless clipboard code 2022-04-09 13:57:14 -04:00
ayunami2000
ff32a46310 add toggle proxy button 2022-04-09 13:55:27 -04:00
ayunami2000
67eb726630 update assets 2022-04-09 13:46:12 -04:00
ayunami2000
1f1c95f5a5 remove unnecessary files 2022-04-09 13:45:08 -04:00
ayunami2000
aa22f121a2 Merge branch 'LAX1DUDE-main' into updated 2022-04-09 13:43:40 -04:00
ayunami2000
cf83efb61a fard? 2022-04-09 13:43:33 -04:00
ayunami2000
8b136844bd Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-04-09 13:42:31 -04:00
LAX1DUDE
6946edc396 22w14b (FREE) Fixed copy paste crash 2022-04-08 21:02:08 -07:00
LAX1DUDE
bec1a03fa2 22w14a (FREE) Fixed 9 bugs and added 3 new features for online server lists
Fixes:
 - server-icon.png can now be any size
 - fixed (0 remaining) in MOTD
 - fixed key event
 - fixed opaque pixels in armor
 - fixed mipmap layout
 - fixed font map interpolation bleeding
 - fixed enchanting GUI
 - fixed bungee log crash
 - fixed duplicate stat uuid

New Features:
 - added DoS protection
 - added MOTD cache hints
 - added UUID to query responses
2022-04-08 01:32:46 -07:00
LAX1DUDE
3490b84ed4 22w13i (Optional) Removed a random debug message 2022-04-03 00:25:32 -07:00
LAX1DUDE
c2168eb8be Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft 2022-04-02 20:43:17 -07:00
LAX1DUDE
a74740224f 22w13h Deleted 'End of Stream' check entirely. Should fix the crash, but in exchange for the client not to detect some server crashes anymore 2022-04-02 20:43:12 -07:00
LAX1DUDE
584da7596f
Added EaglercraftBungee event handler 'documentation' to README 2022-04-02 17:37:19 -07:00
LAX1DUDE
aaefa415e9 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft 2022-04-02 14:25:06 -07:00
LAX1DUDE
d38ef42666 made EaglerMOTDPlugin.jar external 2022-04-02 14:25:03 -07:00
LAX1DUDE
4c8bdcc91a
Update README.md 2022-04-02 14:04:31 -07:00
LAX1DUDE
d7ca745e92 (22w13g) Fixed 'EaglerMOTDPlugin.jar' memory leak 2022-04-02 10:55:35 -07:00
LAX1DUDE
8432d32bea 22w13g Fixed 'Address already in use: bind' on EaglercraftBungee, fixed faulty '1.8' indicator on skin preview 2022-04-02 01:49:15 -07:00
LAX1DUDE
5c32202ee7 22w13f Actually fixed stuck CTRL, restored vanilla ban commands by default, bungeecord ban commands begin with /eag- 2022-04-01 16:53:50 -07:00
LAX1DUDE
4f72bb5fd4 22w13e Test fix to 'End of Stream', fixed ENTER on macOs, fixed stuck CTRL in copy 2022-04-01 14:53:34 -07:00
LAX1DUDE
436315c15e 22w13d LAST 'FREE' UPDATE [part 5] fixed sneaking on 1.8 skins, added ?server= option for the client index.html to auto connect to a specific server 2022-03-31 20:03:46 -07:00
LAX1DUDE
e132a59aa3 22w13c LAST 'FREE' UPDATE [part 4] fixed the upgrade message for pre-22w13 replit users 2022-03-31 16:30:07 -07:00
LAX1DUDE
fb39eff885 22w13c LAST 'FREE' UPDATE [part 3] Fixed block crack animation z-fighting 2022-03-31 16:06:36 -07:00
LAX1DUDE
86e4c8d04b 22w13b LAST 'FREE' UPDATE [part 2] Fixed more bugs 2022-03-31 15:13:35 -07:00
LAX1DUDE
a7790fe6c1 11w13a LAST 'FREE' UPDATE! All bugs fixed and tons of new features 2022-03-31 00:28:29 -07:00
LAX1DUDE
026233b6e4 11w13a LAST 'FREE' UPDATE! All bugs fixed and tons of new features
This is (hopefully) the last 'cracked' update to Eaglercraft, the next update will require a microsoft account

- Fixed rainbow graphics driver problem
- Added server Icons, MOTD, players online and ping to server list
- Copy and paste has been added
- Added F+2 screenshot support
- Added 'Alex' player model for skins
- Fixed arrows in player glitch
- Fixed broken XP orbs
- Fixed palleted PNG file loader
- Fixed text selection
- Added player/IP/wildcard/regex bans
- Added IP address forwarding for proxies
- Fixed offset mouse coords
2022-03-30 23:54:47 -07:00
LAX1DUDE
259f93ccd5 FIXED RAINBOW GLITCH!!! 2022-03-30 17:14:38 -07:00
LAX1DUDE
b56976955b added timeout for NetClientHandler 2022-03-30 17:13:38 -07:00
LAX1DUDE
280137bd97 Update GuiDisconnected.java 2022-03-30 17:13:19 -07:00
LAX1DUDE
ed2c09a052 added alex skins 2022-03-30 17:12:27 -07:00
LAX1DUDE
f7a4ddebd6 added getServerURI 2022-03-30 17:10:03 -07:00
LAX1DUDE
d69742f10c fixed some EntityList weirdness 2022-03-30 17:08:08 -07:00
LAX1DUDE
050bf47771 Added copy/paste and screenshot 2022-03-30 17:05:47 -07:00
LAX1DUDE
7a2a314928 added MOTD and javascript query system 2022-03-30 17:00:53 -07:00
LAX1DUDE
09fdd00900 Added user/ip/wildcard/regex ban commands 2022-03-30 16:46:54 -07:00
LAX1DUDE
94a8c3f6e9 fixed PNG loader to support indexed color 2022-03-21 01:26:04 -07:00
LAX1DUDE
3e17d57250 Merge branch 'auth' 2022-03-20 23:04:04 -07:00
LAX1DUDE
f6a47fd9fe fixed stray references to java.util.Random 2022-03-20 23:01:44 -07:00
LAX1DUDE
67546094f1
Update README.md 2022-03-13 20:41:34 -07:00
LAX1DUDE
1172088b4b 22w10d fixed chat gui crash when closed 2022-03-11 14:26:32 -08:00
LAX1DUDE
2a28e69e31 fixed chat gui crash when closed 2022-03-11 14:26:06 -08:00
LAX1DUDE
ca7c681ab9 22w10c fixed eating glitch 2022-03-10 14:17:41 -08:00
LAX1DUDE
61655de7d3 removed singleplayer button entirely so people stfu 2022-03-10 14:16:53 -08:00
LAX1DUDE
93e18d1721 fixed eating glitch 2022-03-10 14:16:17 -08:00
LAX1DUDE
1232657fa5 22w10b (beta) reduced classes.js size by 400kB and removed all residual integrated server code 2022-03-09 21:09:43 -08:00
LAX1DUDE
0bc20dec09 removed residual integrated server code 2022-03-09 21:05:16 -08:00
LAX1DUDE
2a011f6766 22w10a fixed skin issue, added 'run' command for mac, fixed bukkit server security issue 2022-03-09 18:59:46 -08:00
LAX1DUDE
37bfa17c72 fixed skin issue 2022-03-09 17:51:58 -08:00
ayunami2000
dc6494f22a
Update music.js 2022-02-22 07:29:27 -05:00
LAX1DUDE
9f2bcf7e9d (security) fixed bungeecord InitialHandler username sanitizer 2022-02-19 14:03:45 -08:00
LAX1DUDE
04711c08f7
Update README.md 2022-02-17 13:34:23 -08:00
LAX1DUDE
081dd6ce3f 22w07a Fixed the cock sucking ender dragon and patched SoundManager a fourth time 2022-02-16 15:22:36 -08:00
LAX1DUDE
ae5f2f4e7a Fixed the cock sucking ender dragon and patched SoundManager a fourth time 2022-02-16 15:21:39 -08:00
LAX1DUDE
925638241b removed random 'bukkit-server' directory 2022-02-11 01:40:28 -08:00
LAX1DUDE
a4aab640d7 tried fixing AudioListener crash again 2022-02-10 21:09:55 -08:00
LAX1DUDE
dedbd795dc (Important Update) Changed crash screen to show a link to your github repository instead of listing all my personal contact information. Edit net.lax1dude.eaglercraft.ConfigConstants.forkMe to change the repository URL in your fork 2022-02-10 14:23:41 -08:00
LAX1DUDE
1b53d73998 deleted the default server template off of the offline version completely because people are blind 2022-02-09 21:04:53 -08:00
LAX1DUDE
38746b746f changed the default server template again because people don't seem to understand that '127.0.0.1' is not a replacement server 2022-02-09 18:58:15 -08:00
LAX1DUDE
1b2b0779e9 removed demo servers 2022-02-08 14:00:28 -08:00
LAX1DUDE
d18827c272
Update README.md 2022-02-06 14:02:04 -08:00
LAX1DUDE
6d28ac9779 Update .gitignore 2022-02-03 14:40:02 -08:00
LAX1DUDE
48d2a01720
Update README.md 2022-02-01 15:59:05 -08:00
ayunami2000
4d4adf128d fix everything 2022-02-01 18:38:42 -05:00
ayunami2000
fb2cbccb4a add comment about bad code 2022-02-01 17:57:06 -05:00
ayunami2000
303cf54460 fix bug lol 2022-02-01 17:36:18 -05:00
ayunami2000
62c1ae2f8b proxy work + custom settings 2022-02-01 17:01:42 -05:00
ayunami2000
a2e2ca0a5f cache fix 2022-02-01 08:30:51 -05:00
ayunami2000
08d67a5267 quick patch of random proxy chooser 2022-02-01 08:29:48 -05:00
ayunami2000
5bb2bb7d8a add proxy but actually build this time 2022-01-31 21:23:14 -05:00
ayunami2000
7708a5b79a add proxy 2022-01-31 21:21:30 -05:00
ayunami2000
1e2e93448e cache fix 2022-01-31 20:27:13 -05:00
ayunami2000
ceb5b8f2b3 add proxy checking thingy 2022-01-31 20:26:04 -05:00
ayunami2000
a71351177b add credit policy 2022-01-30 23:51:11 -05:00
ayunami2000
5b9c460ddc push update 2022-01-28 01:45:47 -05:00
ayunami2000
d1577a0652 fix == to .equals(...), add proxy server 2022-01-28 01:41:47 -05:00
ayunami2000
f48e22f761 add sonk 2022-01-27 15:56:43 -05:00
ayunami2000
93bf07370c Merge branch 'LAX1DUDE-main' 2022-01-25 18:29:47 -05:00
ayunami2000
bbe59600eb agus sus 2022-01-25 18:29:31 -05:00
ayunami2000
b08e48ac88 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-01-25 18:28:18 -05:00
ayunami2000
5134c31f9f fix contact info in crash report 2022-01-25 18:22:34 -05:00
ayunami2000
077efc4109
Polyfill for iOS
I made this change on my iPhone in Safari
2022-01-25 02:09:19 -05:00
LAX1DUDE
11997de8f8 22w04b fix invalid mob spawner nullpointerexception crash 2022-01-24 22:53:06 -08:00
LAX1DUDE
6f06daa2a5 fix invalid mob spawner nullpointerexception 2022-01-24 22:39:23 -08:00
LAX1DUDE
3d73f98d49 amended offline download notice 2022-01-24 17:17:09 -08:00
LAX1DUDE
1c970bec10 removed survival from the default server lists 2022-01-24 16:57:07 -08:00
LAX1DUDE
f764d3d3d2 22w04a fixed mob spawner, fixed beacon 2022-01-24 16:20:35 -08:00
LAX1DUDE
79ba9f2580 fixed mob spawner, fixed beacon 2022-01-24 16:19:55 -08:00
ayunami2000
fd107c08bd browser cache bad !! 2022-01-24 18:39:03 -05:00
ayunami2000
16cffaeeec make it build on desktop + allow websocket urls to work even when using a proxy 2022-01-24 18:37:20 -05:00
ayunami2000
51edb68a01 replace my server with pixelcraft 2022-01-24 18:09:49 -05:00
ayunami2000
6802d36ed7 make music default to 25% 2022-01-24 17:57:51 -05:00
ayunami2000
7da266019e add AWESOME MUSIC!!
this took a long time to create the song list
2022-01-24 17:53:38 -05:00
ayunami2000
3422e4e859 Merge branch 'LAX1DUDE-main' 2022-01-24 03:41:27 -05:00
ayunami2000
4400596e68 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-01-24 03:40:58 -05:00
ayunami2000
5136201907 make maps better 2022-01-24 03:20:02 -05:00
ayunami2000
cba395325d help firefox users 2022-01-24 02:42:26 -05:00
LAX1DUDE
6b91ac0576 22w03c fixed illegal NPOT mipmapping, fixed SoundManager class, fixed Enderman player model rendering problems 2022-01-23 23:04:11 -08:00
ayunami2000
da87df7f1e fix fard credits to direct complaints to me 2022-01-24 02:04:11 -05:00
LAX1DUDE
f87b6180de fixed illegal NPOT mipmapping, fixed SoundManager class, fixed Enderman glitch 2022-01-23 22:45:22 -08:00
ayunami2000
dccea5d01d default to using vanilla, update default server 2022-01-24 01:38:52 -05:00
ayunami2000
0be8dd502b add proxy server support 2022-01-24 01:33:39 -05:00
ayunami2000
432521daad Merge branch 'LAX1DUDE-main' 2022-01-23 21:37:13 -05:00
ayunami2000
8ab33cbfbc fardxd 2022-01-23 21:35:50 -05:00
ayunami2000
83b1af05b7 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-01-23 21:34:58 -05:00
ayunami2000
b3892841f0
Merge pull request #4 from ayunami2000/encryption
add encryption (means you can join real 1.5.2 servers!!)
2022-01-23 21:29:02 -05:00
LAX1DUDE
27e0225c4b fixed offline version glitch 2022-01-21 21:13:58 -08:00
LAX1DUDE
4d627f434b (SECURITY!!!) Remove lax1dude, lax2dude from default ops.txt in stable-download 2022-01-20 02:52:40 -08:00
LAX1DUDE
8b98cd1101 added a build of CompilePackage to the repository as a jar and a simple readme.txt to go with it with instructions 2022-01-19 16:51:01 -08:00
ayunami2000
9283bfe009 Merge branch 'LAX1DUDE-main' 2022-01-19 08:16:16 -05:00
ayunami2000
66c4fa3233 fix 2022-01-19 08:15:39 -05:00
ayunami2000
651e20e061 Merge branch 'main' of https://github.com/LAX1DUDE/eaglercraft into LAX1DUDE-main 2022-01-19 08:12:37 -05:00
LAX1DUDE
211e08ba7d 22w03b added missing ender dragon sound FX and fixed file chooser issue
I'm gonna prefix my commits and the main menu with real version tags from now on to make it easier for admins to check if a newer version has been released
2022-01-18 23:48:00 -08:00
418 changed files with 363204 additions and 28366 deletions

5
.gitattributes vendored
View File

@ -1,6 +1,7 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
*.bat text eol=crlf
*.sh text eol=lf
gradlew text eol=lf

2
.gitignore vendored
View File

@ -12,3 +12,5 @@ stable-download/java/spigot_command/world_nether/*
stable-download/java/spigot_command/world_the_end/*
stable-download/java/spigot_command/server.log
stable-download/java/bungee_command/proxy*
stable-download/web_
lwjgl-rundir/_eagstorage*

1
.idea/.name Normal file
View File

@ -0,0 +1 @@
classes.js

View File

@ -1,3 +1,5 @@
# ayuncraft
An [Eaglercraft](https://github.com/LAX1DUDE/eaglercraft) fork
if you want to use this code, be sure to link back to this repo!! (or else i WILL get on your ass)

View File

@ -37,11 +37,11 @@ dependencies {
teavm {
compileScopes = null;
minifying = true;
minifying = false;
maxTopLevelNames = 10000;
properties = null;
debugInformationGenerated = false;
sourceMapsGenerated = false;
sourceMapsGenerated = true;
sourceFilesCopied = false;
incremental = false;
transformers = null;
@ -50,7 +50,7 @@ teavm {
targetDirectory = file("javascript");
/** The directory to monitor to decide if compile is up-to-date or not */
//sourceDirectory = [file("src/main/java"),file("../minecrafthtml5mcp/src")];
sourceDirectory = file("src");
/** How to name the result file. */
targetFileName = "classes.js";
@ -63,7 +63,7 @@ teavm {
classesToPreserve = null;
stopOnErrors = false;
optimizationLevel = "FULL"; //org.teavm.vm.TeaVMOptimizationLevel.SIMPLE;
optimizationLevel = "ADVANCED"; //org.teavm.vm.TeaVMOptimizationLevel.SIMPLE;
fastGlobalAnalysis = false;
targetType = "JAVASCRIPT"; //org.teavm.tooling.TeaVMTargetType.JAVASCRIPT;
cacheDirectory = null;

View File

@ -1,3 +0,0 @@
# Updated 9/27/20 12:38 AM by Minecraft 1.5.2
# victim name | ban date | banned by | banned until | reason

View File

@ -1,3 +0,0 @@
# Updated 9/27/20 12:38 AM by Minecraft 1.5.2
# victim name | ban date | banned by | banned until | reason

View File

@ -1,45 +0,0 @@
# This is the main configuration file for Bukkit.
# As you can see, there's actually not that much to configure without any plugins.
# For a reference for any variable inside this file, check out the bukkit wiki at
# http://wiki.bukkit.org/Bukkit.yml
settings:
allow-end: true
warn-on-overload: true
permissions-file: permissions.yml
update-folder: update
ping-packet-limit: 100
use-exact-login-location: false
plugin-profiling: false
connection-throttle: 4000
query-plugins: true
deprecated-verbose: default
shutdown-message: Server closed
spawn-limits:
monsters: 70
animals: 15
water-animals: 5
ambient: 15
chunk-gc:
period-in-ticks: 600
load-threshold: 0
ticks-per:
animal-spawns: 400
monster-spawns: 1
autosave: 0
auto-updater:
enabled: true
on-broken:
- warn-console
- warn-ops
on-update:
- warn-console
- warn-ops
preferred-channel: rb
host: dl.bukkit.org
suggest-channels: true
database:
username: bukkit
isolation: SERIALIZABLE
driver: org.sqlite.JDBC
password: walrus
url: jdbc:sqlite:{DIR}{NAME}.db

View File

@ -1,56 +0,0 @@
# This is the help configuration file for Bukkit.
#
# By default you do not need to modify this file. Help topics for all plugin commands are automatically provided by
# or extracted from your installed plugins. You only need to modify this file if you wish to add new help pages to
# your server or override the help pages of existing plugin commands.
#
# This file is divided up into the following parts:
# -- general-topics: lists admin defined help topics
# -- index-topics: lists admin defined index topics
# -- amend-topics: lists topic amendments to apply to existing help topics
# -- ignore-plugins: lists any plugins that should be excluded from help
#
# Examples are given below. When amending command topic, the string <text> will be replaced with the existing value
# in the help topic. Color codes can be used in topic text. The color code character is & followed by 0-F.
# ================================================================
#
# Set this to true to list the individual command help topics in the master help.
# command-topics-in-master-index: true
#
# Each general topic will show up as a separate topic in the help index along with all the plugin command topics.
# general-topics:
# Rules:
# shortText: Rules of the server
# fullText: |
# &61. Be kind to your fellow players.
# &B2. No griefing.
# &D3. No swearing.
# permission: topics.rules
#
# Each index topic will show up as a separate sub-index in the help index along with all the plugin command topics.
# To override the default help index (displayed when the user executes /help), name the index topic "Default".
# index-topics:
# Ban Commands:
# shortText: Player banning commands
# preamble: Moderator - do not abuse these commands
# permission: op
# commands:
# - /ban
# - /ban-ip
# - /banlist
#
# Topic amendments are used to change the content of automatically generated plugin command topics.
# amended-topics:
# /stop:
# shortText: Stops the server cold....in its tracks!
# fullText: <text> - This kills the server.
# permission: you.dont.have
#
# Any plugin in the ignored plugins list will be excluded from help. The name must match the name displayed by
# the /plugins command. Ignore "Bukkit" to remove the standard bukkit commands from the index. Ignore "All"
# to completely disable automatic help topic generation.
# ignore-plugins:
# - PluginNameOne
# - PluginNameTwo
# - PluginNameThree

View File

@ -1,2 +0,0 @@
lax2dude
lax1dude

View File

@ -1,4 +0,0 @@
# http://mcstats.org
opt-out: false
guid: c015ae6f-e6ca-48d6-b4af-6e1cb5825cb9
debug: false

View File

@ -1,3 +0,0 @@
@echo off
java -Xmx512M -Xms512M -jar craftbukkit-1.5.2-R1.0.jar
pause

View File

@ -1,30 +0,0 @@
#Minecraft server properties
#Sun Sep 27 00:38:00 PDT 2020
generator-settings=
allow-nether=true
level-name=world
enable-query=false
allow-flight=false
server-port=25501
level-type=DEFAULT
enable-rcon=false
force-gamemode=true
level-seed=
server-ip=
max-build-height=256
spawn-npcs=true
white-list=false
spawn-animals=true
hardcore=false
snooper-enabled=true
texture-pack=
online-mode=false
pvp=true
difficulty=1
gamemode=1
max-players=20
spawn-monsters=true
generate-structures=true
view-distance=10
spawn-protection=16
motd=A Minecraft Server

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
י<D7A0>g<EFBFBD>D´<44>Mם³<D79D>צ<>

Binary file not shown.

View File

@ -1 +0,0 @@
{_¸+PEc¹ <20>Í°|aã

View File

@ -1 +0,0 @@
ûÚå<EFBFBD>å<EFBFBD>D¶£OΊ§¿ïh

View File

@ -19,7 +19,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.MissingResourceException;
import net.md_5.bungee.protocol.packet.DefinedPacket;
import io.netty.channel.ChannelException;
import java.util.Iterator;
import io.netty.util.concurrent.GenericFutureListener;
import java.net.SocketAddress;
import io.netty.channel.EventLoopGroup;
@ -28,7 +27,6 @@ import io.netty.util.AttributeKey;
import net.md_5.bungee.netty.PipelineUtils;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.util.concurrent.Future;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import net.md_5.bungee.api.config.ListenerInfo;
@ -38,7 +36,7 @@ import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.command.ConsoleCommandSender;
import java.util.concurrent.TimeUnit;
import java.util.Calendar;
import java.util.ArrayList;
import java.io.IOException;
import jline.UnsupportedTerminal;
import java.io.OutputStream;
@ -50,9 +48,19 @@ import jline.internal.Log;
import java.io.PrintStream;
import com.google.common.io.ByteStreams;
import net.md_5.bungee.command.CommandFind;
import net.md_5.bungee.command.CommandGlobalBan;
import net.md_5.bungee.command.CommandGlobalBanIP;
import net.md_5.bungee.command.CommandGlobalBanRegex;
import net.md_5.bungee.command.CommandGlobalBanReload;
import net.md_5.bungee.command.CommandGlobalBanWildcard;
import net.md_5.bungee.command.CommandGlobalCheckBan;
import net.md_5.bungee.command.CommandGlobalListBan;
import net.md_5.bungee.command.CommandGlobalUnban;
import net.md_5.bungee.command.CommandSend;
import net.md_5.bungee.command.CommandPerms;
import net.md_5.bungee.command.CommandBungee;
import net.md_5.bungee.command.CommandClearRatelimit;
import net.md_5.bungee.command.CommandConfirmCode;
import net.md_5.bungee.command.CommandAlert;
import net.md_5.bungee.command.CommandIP;
import net.md_5.bungee.command.CommandServer;
@ -61,10 +69,9 @@ import net.md_5.bungee.command.CommandEnd;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.command.CommandReload;
import java.util.concurrent.ExecutorService;
import net.md_5.bungee.scheduler.BungeeScheduler;
import net.md_5.bungee.config.YamlConfig;
import net.md_5.bungee.eaglercraft.PluginEaglerAuth;
import net.md_5.bungee.eaglercraft.BanList;
import net.md_5.bungee.eaglercraft.PluginEaglerSkins;
import net.md_5.bungee.eaglercraft.WebSocketListener;
@ -99,6 +106,8 @@ public class BungeeCord extends ProxyServer {
public final ScheduledThreadPoolExecutor executors;
public final MultithreadEventLoopGroup eventLoops;
private final Timer saveThread;
private final Timer reloadBanThread;
private final Timer closeInactiveSockets;
private Collection<Channel> listeners;
private Collection<WebSocketListener> wsListeners;
private final Map<String, UserConnection> connections;
@ -111,6 +120,7 @@ public class BungeeCord extends ProxyServer {
private final TaskScheduler scheduler;
private ConsoleReader consoleReader;
private final Logger logger;
private Collection<Command> banCommands;
public static BungeeCord getInstance() {
return (BungeeCord) ProxyServer.getInstance();
@ -122,6 +132,8 @@ public class BungeeCord extends ProxyServer {
this.executors = new BungeeThreadPool(new ThreadFactoryBuilder().setNameFormat("Bungee Pool Thread #%1$d").build());
this.eventLoops = (MultithreadEventLoopGroup) new NioEventLoopGroup(Runtime.getRuntime().availableProcessors(), new ThreadFactoryBuilder().setNameFormat("Netty IO Thread #%1$d").build());
this.saveThread = new Timer("Reconnect Saver");
this.reloadBanThread = new Timer("Ban List Reload");
this.closeInactiveSockets = new Timer("close Inactive WebSockets");
this.listeners = new HashSet<Channel>();
this.wsListeners = new HashSet<WebSocketListener>();
this.connections = (Map<String, UserConnection>) new CaseInsensitiveMap();
@ -131,6 +143,7 @@ public class BungeeCord extends ProxyServer {
this.pluginChannels = new HashSet<String>();
this.pluginsFolder = new File("plugins");
this.scheduler = new BungeeScheduler();
this.banCommands = new ArrayList();
this.getPluginManager().registerCommand(null, new CommandReload());
this.getPluginManager().registerCommand(null, new CommandEnd());
this.getPluginManager().registerCommand(null, new CommandList());
@ -141,6 +154,8 @@ public class BungeeCord extends ProxyServer {
this.getPluginManager().registerCommand(null, new CommandPerms());
this.getPluginManager().registerCommand(null, new CommandSend());
this.getPluginManager().registerCommand(null, new CommandFind());
this.getPluginManager().registerCommand(null, new CommandClearRatelimit());
this.getPluginManager().registerCommand(null, new CommandConfirmCode());
this.registerChannel("BungeeCord");
Log.setOutput(new PrintStream(ByteStreams.nullOutputStream()));
AnsiConsole.systemInstall();
@ -154,6 +169,42 @@ public class BungeeCord extends ProxyServer {
}
}
public void reconfigureBanCommands(boolean replaceBukkit) {
if(banCommands.size() > 0) {
for(Command c : banCommands) {
this.getPluginManager().unregisterCommand(c);
}
banCommands.clear();
}
Command cBan = new CommandGlobalBan(replaceBukkit);
Command cUnban = new CommandGlobalUnban(replaceBukkit);
Command cBanReload = new CommandGlobalBanReload(replaceBukkit);
Command cBanIP = new CommandGlobalBanIP(replaceBukkit);
Command cBanWildcard = new CommandGlobalBanWildcard(replaceBukkit);
Command cBanRegex = new CommandGlobalBanRegex(replaceBukkit);
Command cBanCheck = new CommandGlobalCheckBan(replaceBukkit);
Command cBanList = new CommandGlobalListBan(replaceBukkit);
banCommands.add(cBan);
banCommands.add(cUnban);
banCommands.add(cBanReload);
banCommands.add(cBanIP);
banCommands.add(cBanWildcard);
banCommands.add(cBanRegex);
banCommands.add(cBanCheck);
banCommands.add(cBanList);
this.getPluginManager().registerCommand(null, cBan);
this.getPluginManager().registerCommand(null, cUnban);
this.getPluginManager().registerCommand(null, cBanReload);
this.getPluginManager().registerCommand(null, cBanIP);
this.getPluginManager().registerCommand(null, cBanWildcard);
this.getPluginManager().registerCommand(null, cBanRegex);
this.getPluginManager().registerCommand(null, cBanCheck);
this.getPluginManager().registerCommand(null, cBanList);
}
public static void main(final String[] args) throws Exception {
final BungeeCord bungee = new BungeeCord();
ProxyServer.setInstance(bungee);
@ -186,6 +237,25 @@ public class BungeeCord extends ProxyServer {
BungeeCord.this.getReconnectHandler().save();
}
}, 0L, TimeUnit.MINUTES.toMillis(5L));
this.reloadBanThread.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
BanList.maybeReloadBans(null);
}
}, 0L, TimeUnit.SECONDS.toMillis(3L));
this.closeInactiveSockets.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
for(WebSocketListener lst : BungeeCord.this.wsListeners) {
lst.closeInactiveSockets();
ListenerInfo info = lst.getInfo();
if(info.getRateLimitIP() != null) info.getRateLimitIP().deleteClearLimiters();
if(info.getRateLimitLogin() != null) info.getRateLimitLogin().deleteClearLimiters();
if(info.getRateLimitMOTD() != null) info.getRateLimitMOTD().deleteClearLimiters();
if(info.getRateLimitQuery() != null) info.getRateLimitQuery().deleteClearLimiters();
}
}
}, 0L, TimeUnit.SECONDS.toMillis(10L));
}
public void startListeners() {

View File

@ -4,13 +4,10 @@
package net.md_5.bungee;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.connection.PendingConnection;
import java.beans.ConstructorProperties;
import net.md_5.bungee.util.CaseInsensitiveSet;
import java.util.HashSet;
import net.md_5.bungee.api.config.TexturePackInfo;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.event.PermissionCheckEvent;
import java.util.Collections;
import java.net.InetSocketAddress;
@ -36,10 +33,14 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import net.md_5.bungee.api.ChatColor;
import java.util.Objects;
import java.util.WeakHashMap;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.protocol.packet.DefinedPacket;
import com.google.common.base.Preconditions;
import java.util.Iterator;
import java.util.Map;
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.score.Scoreboard;
import net.md_5.bungee.protocol.packet.PacketCCSettings;
@ -71,6 +72,7 @@ public final class UserConnection implements ProxiedPlayer {
private final Scoreboard serverSentScoreboard;
private String displayName;
private final Connection.Unsafe unsafe;
private final Map<String, Object> attachment = new WeakHashMap();
public void init() {
this.displayName = this.name;
@ -383,4 +385,9 @@ public final class UserConnection implements ProxiedPlayer {
public String getDisplayName() {
return this.displayName;
}
@Override
public Map<String, Object> getAttachment() {
return attachment;
}
}

View File

@ -12,7 +12,7 @@ public enum ChatColor {
BLACK('0'), DARK_BLUE('1'), DARK_GREEN('2'), DARK_AQUA('3'), DARK_RED('4'), DARK_PURPLE('5'), GOLD('6'), GRAY('7'), DARK_GRAY('8'), BLUE('9'), GREEN('a'), AQUA('b'), RED('c'), LIGHT_PURPLE('d'), YELLOW('e'), WHITE('f'), MAGIC('k'),
BOLD('l'), STRIKETHROUGH('m'), UNDERLINE('n'), ITALIC('o'), RESET('r');
public static final char COLOR_CHAR = '§';
public static final char COLOR_CHAR = '\u00A7';
private static final Pattern STRIP_COLOR_PATTERN;
private static final Map<Character, ChatColor> BY_CHAR;
private final char code;
@ -20,7 +20,7 @@ public enum ChatColor {
private ChatColor(final char code) {
this.code = code;
this.toString = new String(new char[] { '§', code });
this.toString = new String(new char[] { '\u00A7', code });
}
@Override
@ -39,7 +39,7 @@ public enum ChatColor {
final char[] b = textToTranslate.toCharArray();
for (int i = 0; i < b.length - 1; ++i) {
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
b[i] = '§';
b[i] = '\u00A7';
b[i + 1] = Character.toLowerCase(b[i + 1]);
}
}
@ -51,7 +51,7 @@ public enum ChatColor {
}
static {
STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('\u00A7') + "[0-9A-FK-OR]");
BY_CHAR = new HashMap<Character, ChatColor>();
for (final ChatColor colour : values()) {
ChatColor.BY_CHAR.put(colour.code, colour);

View File

@ -5,6 +5,7 @@
package net.md_5.bungee.api;
import java.util.Collection;
import java.util.Map;
public interface CommandSender {
String getName();
@ -22,4 +23,6 @@ public interface CommandSender {
boolean hasPermission(final String p0);
void setPermission(final String p0, final boolean p1);
Map<String, Object> getAttachment();
}

View File

@ -0,0 +1,25 @@
package net.md_5.bungee.api;
import java.util.List;
public interface MOTD extends QueryConnection {
public void sendToUser();
public String getLine1();
public String getLine2();
public List<String> getPlayerList();
public int[] getBitmap();
public int getOnlinePlayers();
public int getMaxPlayers();
public String getSubType();
public void setLine1(String p);
public void setLine2(String p);
public void setPlayerList(List<String> p);
public void setPlayerList(String... p);
public void setBitmap(int[] p);
public void setOnlinePlayers(int i);
public void setMaxPlayers(int i);
}

View File

@ -0,0 +1,70 @@
package net.md_5.bungee.api;
import java.net.InetAddress;
import org.json.JSONObject;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.eaglercraft.EaglercraftBungee;
public interface QueryConnection {
public InetAddress getRemoteAddress();
public ListenerInfo getListener();
public String getAccept();
public void setReturnType(String type);
public String getReturnType();
public int availableRequests();
public default JSONObject readRequestData() {
String s = readRequestString();
return s == null ? null : new JSONObject(s);
}
public String readRequestString();
public long getConnectionTimestamp();
public default long getConnectionAge() {
return System.currentTimeMillis() - getConnectionTimestamp();
}
public default void writeResponse(JSONObject msg) {
JSONObject toSend = new JSONObject();
toSend.put("type", getReturnType());
toSend.put("name", BungeeCord.getInstance().config.getServerName());
toSend.put("brand", EaglercraftBungee.brand);
toSend.put("vers", EaglercraftBungee.version);
toSend.put("cracked", EaglercraftBungee.cracked);
toSend.put("secure", false);
toSend.put("time", System.currentTimeMillis());
toSend.put("uuid", BungeeCord.getInstance().config.getUuid());
toSend.put("data", msg);
writeResponseRaw(toSend.toString());
}
public default void writeResponse(String msg) {
JSONObject toSend = new JSONObject();
toSend.put("type", getReturnType());
toSend.put("name", BungeeCord.getInstance().config.getServerName());
toSend.put("brand", EaglercraftBungee.brand);
toSend.put("vers", EaglercraftBungee.version);
toSend.put("cracked", EaglercraftBungee.cracked);
toSend.put("secure", false);
toSend.put("time", System.currentTimeMillis());
toSend.put("uuid", BungeeCord.getInstance().config.getUuid());
toSend.put("data", msg);
writeResponseRaw(toSend.toString());
}
public void writeResponseRaw(String msg);
public void writeResponseBinary(byte[] blob);
public void keepAlive(boolean yes);
public boolean shouldKeepAlive();
public boolean isClosed();
public void close();
}

View File

@ -0,0 +1,66 @@
package net.md_5.bungee.api;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class ServerIcon {
public static int[] createServerIcon(BufferedImage awtIcon) {
BufferedImage icon = awtIcon;
boolean gotScaled = false;
if(icon.getWidth() != 64 || icon.getHeight() != 64) {
icon = new BufferedImage(64, 64, awtIcon.getType());
Graphics2D g = (Graphics2D) icon.getGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ?
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setBackground(Color.BLACK);
g.clearRect(0, 0, 64, 64);
int ow = awtIcon.getWidth();
int oh = awtIcon.getHeight();
int nw, nh;
float aspectRatio = (float)oh / (float)ow;
if(aspectRatio >= 1.0f) {
nw = (int)(64 / aspectRatio);
nh = 64;
}else {
nw = 64;
nh = (int)(64 * aspectRatio);
}
g.drawImage(awtIcon, (64 - nw) / 2, (64 - nh) / 2, (64 - nw) / 2 + nw, (64 - nh) / 2 + nh, 0, 0, awtIcon.getWidth(), awtIcon.getHeight(), null);
g.dispose();
gotScaled = true;
}
int[] pxls = icon.getRGB(0, 0, 64, 64, new int[4096], 0, 64);
if(gotScaled) {
for(int i = 0; i < pxls.length; ++i) {
if((pxls[i] & 0xFFFFFF) == 0) {
pxls[i] = 0;
}
}
}
return pxls;
}
public static int[] createServerIcon(InputStream f) {
try {
return createServerIcon(ImageIO.read(f));
}catch(Throwable t) {
return null;
}
}
public static int[] createServerIcon(File f) {
try {
return createServerIcon(ImageIO.read(f));
}catch(Throwable t) {
return null;
}
}
}

View File

@ -25,4 +25,8 @@ public interface ConfigurationAdapter {
Collection<String> getPermissions(final String p0);
AuthServiceInfo getAuthSettings();
Map<String, Object> getMap();
void forceSave();
}

View File

@ -4,12 +4,17 @@
package net.md_5.bungee.api.config;
import java.beans.ConstructorProperties;
import java.io.File;
import net.md_5.bungee.api.ServerIcon;
import net.md_5.bungee.api.tab.TabListHandler;
import net.md_5.bungee.eaglercraft.WebSocketRateLimiter;
import java.util.Map;
import java.net.InetSocketAddress;
public class ListenerInfo {
private final String hostString;
private final InetSocketAddress host;
private final String motd;
private final int maxPlayers;
@ -18,13 +23,27 @@ public class ListenerInfo {
private final String fallbackServer;
private final boolean forceDefault;
private final boolean websocket;
private final boolean forwardIp;
private final Map<String, String> forcedHosts;
private final TexturePackInfo texturePack;
private final Class<? extends TabListHandler> tabList;
private final String serverIcon;
private final int[] serverIconCache;
private boolean serverIconLoaded;
private boolean serverIconSet;
private final boolean allowMOTD;
private final boolean allowQuery;
private final MOTDCacheConfiguration cacheConfig;
private final WebSocketRateLimiter rateLimitIP;
private final WebSocketRateLimiter rateLimitLogin;
private final WebSocketRateLimiter rateLimitMOTD;
private final WebSocketRateLimiter rateLimitQuery;
@ConstructorProperties({ "host", "motd", "maxPlayers", "tabListSize", "defaultServer", "fallbackServer", "forceDefault", "websocket", "forcedHosts", "texturePack", "tabList" })
public ListenerInfo(final InetSocketAddress host, final String motd, final int maxPlayers, final int tabListSize, final String defaultServer, final String fallbackServer, final boolean forceDefault, final boolean websocket,
final Map<String, String> forcedHosts, final TexturePackInfo texturePack, final Class<? extends TabListHandler> tabList) {
public ListenerInfo(final String hostString, final InetSocketAddress host, final String motd, final int maxPlayers, final int tabListSize, final String defaultServer, final String fallbackServer, final boolean forceDefault, final boolean websocket,
final boolean forwardIp, final Map<String, String> forcedHosts, final TexturePackInfo texturePack, final Class<? extends TabListHandler> tabList, final String serverIcon, final MOTDCacheConfiguration cacheConfig,
final boolean allowMOTD, final boolean allowQuery, final WebSocketRateLimiter rateLimitIP, final WebSocketRateLimiter rateLimitLogin, final WebSocketRateLimiter rateLimitMOTD, final WebSocketRateLimiter rateLimitQuery) {
this.hostString = hostString;
this.host = host;
this.motd = motd;
this.maxPlayers = maxPlayers;
@ -33,9 +52,25 @@ public class ListenerInfo {
this.fallbackServer = fallbackServer;
this.forceDefault = forceDefault;
this.websocket = websocket;
this.forwardIp = forwardIp;
this.forcedHosts = forcedHosts;
this.texturePack = texturePack;
this.tabList = tabList;
this.serverIcon = serverIcon;
this.serverIconCache = new int[4096];
this.serverIconLoaded = false;
this.serverIconSet = false;
this.allowMOTD = allowMOTD;
this.allowQuery = allowQuery;
this.cacheConfig = cacheConfig;
this.rateLimitIP = rateLimitIP;
this.rateLimitLogin = rateLimitLogin;
this.rateLimitMOTD = rateLimitMOTD;
this.rateLimitQuery = rateLimitQuery;
}
public String getHostString() {
return this.hostString;
}
public InetSocketAddress getHost() {
@ -120,6 +155,9 @@ public class ListenerInfo {
if (this.getTabListSize() != other.getTabListSize()) {
return false;
}
if (this.isWebsocket() != other.isWebsocket()) {
return false;
}
final Object this$defaultServer = this.getDefaultServer();
final Object other$defaultServer = other.getDefaultServer();
Label_0165: {
@ -180,6 +218,15 @@ public class ListenerInfo {
} else if (this$tabList.equals(other$tabList)) {
return true;
}
final Object this$getServerIcon = this.getServerIcon();
final Object other$getServerIcon = other.getServerIcon();
if (this$getServerIcon == null) {
if (other$getServerIcon == null) {
return true;
}
} else if (this$getServerIcon.equals(other$getServerIcon)) {
return true;
}
return false;
}
@ -208,6 +255,8 @@ public class ListenerInfo {
result = result * 31 + (($texturePack == null) ? 0 : $texturePack.hashCode());
final Object $tabList = this.getTabList();
result = result * 31 + (($tabList == null) ? 0 : $tabList.hashCode());
final Object $serverIconCache = this.getTabList();
result = result * 31 + (($serverIconCache == null) ? 0 : $serverIconCache.hashCode());
return result;
}
@ -220,4 +269,76 @@ public class ListenerInfo {
public boolean isWebsocket() {
return websocket;
}
public boolean hasForwardedHeaders() {
return forwardIp;
}
public String getServerIcon() {
return serverIcon;
}
public int[] getServerIconCache() {
if(!serverIconLoaded) {
if(serverIcon != null) {
int[] img = ServerIcon.createServerIcon(new File(serverIcon));
if(img != null) {
System.arraycopy(img, 0, serverIconCache, 0, img.length);
serverIconSet = true;
}else {
serverIconSet = false;
}
}else {
serverIconSet = false;
}
serverIconLoaded = true;
}
return serverIconCache;
}
public boolean isIconSet() {
getServerIconCache();
return serverIconSet;
}
public boolean isForwardIp() {
return forwardIp;
}
public boolean isServerIconLoaded() {
return serverIconLoaded;
}
public boolean isServerIconSet() {
return serverIconSet;
}
public boolean isAllowMOTD() {
return allowMOTD;
}
public boolean isAllowQuery() {
return allowQuery;
}
public MOTDCacheConfiguration getCacheConfig() {
return cacheConfig;
}
public WebSocketRateLimiter getRateLimitIP() {
return rateLimitIP;
}
public WebSocketRateLimiter getRateLimitLogin() {
return rateLimitLogin;
}
public WebSocketRateLimiter getRateLimitMOTD() {
return rateLimitMOTD;
}
public WebSocketRateLimiter getRateLimitQuery() {
return rateLimitQuery;
}
}

View File

@ -0,0 +1,21 @@
package net.md_5.bungee.api.config;
public class MOTDCacheConfiguration {
public final int cacheTTL;
public final boolean cacheServerListAnimation;
public final boolean cacheServerListResults;
public final boolean cacheServerListTrending;
public final boolean cacheServerListPortfolios;
public MOTDCacheConfiguration(int cacheTTL, boolean cacheServerListAnimation, boolean cacheServerListResults,
boolean cacheServerListTrending, boolean cacheServerListPortfolios) {
this.cacheTTL = cacheTTL;
this.cacheServerListAnimation = cacheServerListAnimation;
this.cacheServerListResults = cacheServerListResults;
this.cacheServerListTrending = cacheServerListTrending;
this.cacheServerListPortfolios = cacheServerListPortfolios;
}
}

View File

@ -0,0 +1,15 @@
package net.md_5.bungee.api.event;
import net.md_5.bungee.api.MOTD;
public class WebsocketMOTDEvent extends WebsocketQueryEvent {
public WebsocketMOTDEvent(MOTD connection) {
super(connection);
}
public MOTD getMOTD() {
return (MOTD)connection;
}
}

View File

@ -0,0 +1,33 @@
package net.md_5.bungee.api.event;
import java.net.InetAddress;
import net.md_5.bungee.api.QueryConnection;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.plugin.Event;
public class WebsocketQueryEvent extends Event {
protected final QueryConnection connection;
public WebsocketQueryEvent(QueryConnection connection) {
this.connection = connection;
}
public InetAddress getRemoteAddress() {
return connection.getRemoteAddress();
}
public ListenerInfo getListener() {
return connection.getListener();
}
public String getAccept() {
return connection.getAccept();
}
public QueryConnection getQuery() {
return connection;
}
}

View File

@ -0,0 +1,118 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.plugin.Command;
public class CommandClearRatelimit extends Command {
public CommandClearRatelimit() {
super("eag-ratelimit", "bungeecord.command.eag.ratelimit", "e-ratelimit", "gratelimit");
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length >= 1 && ("clear".equalsIgnoreCase(p1[0]) || "reset".equalsIgnoreCase(p1[0]))) {
if(p1.length == 1 || (p1.length == 2 && "all".equalsIgnoreCase(p1[1]))) {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitIP() != null) l.getRateLimitIP().resetLimiters();
if(l.getRateLimitLogin() != null) l.getRateLimitLogin().resetLimiters();
if(l.getRateLimitMOTD() != null) l.getRateLimitMOTD().resetLimiters();
if(l.getRateLimitQuery() != null) l.getRateLimitQuery().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all ratelimits");
return;
}else if(p1.length == 2 || p1.length == 3) {
ListenerInfo ll = null;
if(p1.length == 3) {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getHostString().equalsIgnoreCase(p1[2])) {
ll = l;
break;
}
}
if(ll == null) {
p0.sendMessage(ChatColor.RED + "Listener does not exist: " + ChatColor.WHITE + p1[2]);
String accum = "";
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(accum.length() > 0) {
accum += ", ";
}
accum += l.getHostString();
}
p0.sendMessage(ChatColor.GREEN + "Listeners Available: " + ChatColor.WHITE + accum);
return;
}
}
if("all".equalsIgnoreCase(p1[1])) {
if(ll != null) {
if(ll.getRateLimitIP() != null) ll.getRateLimitIP().resetLimiters();
if(ll.getRateLimitLogin() != null) ll.getRateLimitLogin().resetLimiters();
if(ll.getRateLimitMOTD() != null) ll.getRateLimitMOTD().resetLimiters();
if(ll.getRateLimitQuery() != null) ll.getRateLimitQuery().resetLimiters();
p0.sendMessage(ChatColor.GREEN + "Reset all ratelimits on listener: " + ChatColor.WHITE + ll.getHostString());
}else {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitIP() != null) l.getRateLimitIP().resetLimiters();
if(l.getRateLimitLogin() != null) l.getRateLimitLogin().resetLimiters();
if(l.getRateLimitMOTD() != null) l.getRateLimitMOTD().resetLimiters();
if(l.getRateLimitQuery() != null) l.getRateLimitQuery().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all ratelimits");
}
return;
}else if("ip".equalsIgnoreCase(p1[1])) {
if(ll != null) {
if(ll.getRateLimitIP() != null) ll.getRateLimitIP().resetLimiters();
p0.sendMessage(ChatColor.GREEN + "Reset all IP ratelimits on listener: " + ChatColor.WHITE + ll.getHostString());
}else {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitIP() != null) l.getRateLimitIP().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all IP ratelimits.");
}
return;
}else if("login".equalsIgnoreCase(p1[1])) {
if(ll != null) {
if(ll.getRateLimitLogin() != null) ll.getRateLimitLogin().resetLimiters();
p0.sendMessage(ChatColor.GREEN + "Reset all login ratelimits on listener: " + ChatColor.WHITE + ll.getHostString());
}else {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitLogin() != null) l.getRateLimitLogin().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all login ratelimits.");
}
return;
}else if("motd".equalsIgnoreCase(p1[1])) {
if(ll != null) {
if(ll.getRateLimitMOTD() != null) ll.getRateLimitMOTD().resetLimiters();
p0.sendMessage(ChatColor.GREEN + "Reset all MOTD ratelimits on listener: " + ChatColor.WHITE + ll.getHostString());
}else {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitMOTD() != null) l.getRateLimitMOTD().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all MOTD ratelimits.");
}
return;
}else if("query".equalsIgnoreCase(p1[1])) {
if(ll != null) {
if(ll.getRateLimitMOTD() != null) ll.getRateLimitMOTD().resetLimiters();
p0.sendMessage(ChatColor.GREEN + "Reset all query ratelimits on listener: " + ChatColor.WHITE + ll.getHostString());
}else {
for(ListenerInfo l : BungeeCord.getInstance().config.getListeners()) {
if(l.getRateLimitMOTD() != null) l.getRateLimitMOTD().resetLimiters();
}
p0.sendMessage(ChatColor.GREEN + "Reset all query ratelimits.");
}
return;
}
}
}
p0.sendMessage(ChatColor.RED + "How to reset all rate limits: " + ChatColor.WHITE + "/eag-ratelimit reset");
p0.sendMessage(ChatColor.RED + "How to reset a specific rate limit: " + ChatColor.WHITE + "/eag-ratelimit reset <ip|login|motd|query>");
p0.sendMessage(ChatColor.RED + "How to reset a specific listener: " + ChatColor.WHITE + "/eag-ratelimit reset <all|ip|login|motd|query> <host>");
}
}

View File

@ -0,0 +1,33 @@
package net.md_5.bungee.command;
import java.nio.charset.StandardCharsets;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.QueryConnectionImpl;
import net.md_5.bungee.eaglercraft.SHA1Digest;
public class CommandConfirmCode extends Command {
public CommandConfirmCode() {
super("confirm-code", "bungeecord.command.eag.confirmcode", "confirmcode");
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length != 1) {
p0.sendMessage(ChatColor.RED + "How to use: " + ChatColor.WHITE + "/confirm-code <code>");
}else {
p0.sendMessage(ChatColor.YELLOW + "Server list 2FA code has been set to: " + ChatColor.GREEN + p1[0]);
p0.sendMessage(ChatColor.YELLOW + "You can now return to the server list site and continue");
byte[] bts = p1[0].getBytes(StandardCharsets.US_ASCII);
SHA1Digest dg = new SHA1Digest();
dg.update(bts, 0, bts.length);
byte[] f = new byte[20];
dg.doFinal(f, 0);
QueryConnectionImpl.confirmHash = SHA1Digest.hash2string(f);
}
}
}

View File

@ -0,0 +1,61 @@
package net.md_5.bungee.command;
import java.util.Collection;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalBan extends Command {
private final boolean replaceBukkit;
public CommandGlobalBan(boolean replaceBukkit) {
super(replaceBukkit ? "ban" : "eag-ban", "bungeecord.command.eag.ban", replaceBukkit ? new String[] { "kickban", "eag-ban", "e-ban", "gban" } : new String[] { "e-ban", "gban" });
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length >= 1) {
String p = p1[0].trim().toLowerCase();
if(p0.getName().equalsIgnoreCase(p)) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "You cannot ban yourself");
return;
}
String reason = "The ban hammer has spoken!";
if(p1.length >= 2) {
reason = "";
for(int i = 1; i < p1.length; ++i) {
if(reason.length() > 0) {
reason += " ";
}
reason += p1[i];
}
}
String wasTheKick = null;
Collection<ProxiedPlayer> playerz = BungeeCord.getInstance().getPlayers();
for(ProxiedPlayer pp : playerz) {
if(pp.getName().equalsIgnoreCase(p)) {
wasTheKick = pp.getName();
pp.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: " + reason);
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.WHITE + "Kicked: " + pp.getName());
}
}
if(BanList.ban(p, reason)) {
if(wasTheKick == null) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Warning! '" + ChatColor.WHITE + p + ChatColor.YELLOW + "' is not currently on this server");
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Username '" + ChatColor.WHITE + (wasTheKick == null ? p : wasTheKick) + ChatColor.GREEN + "' was added to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Username '" + ChatColor.WHITE + p + ChatColor.RED + "' is already banned");
}
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To ban a player, use: " + ChatColor.WHITE + "/" + (replaceBukkit?"":"eag-") + "ban <player> [reason]");
}
}
}

View File

@ -0,0 +1,148 @@
package net.md_5.bungee.command;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
import net.md_5.bungee.eaglercraft.BanList.IPBan;
public class CommandGlobalBanIP extends Command {
private final boolean replaceBukkit;
public CommandGlobalBanIP(boolean replaceBukkit) {
super(replaceBukkit ? "ban-ip" : "eag-ban-ip", "bungeecord.command.eag.banip", (replaceBukkit ? new String[] {"eag-ban-ip", "banip", "e-ban-ip", "gban-ip"} :
new String[] {"gban-ip", "e-ban-ip", "gbanip", "e-banip"}) );
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
String w = (String) p0.getAttachment().get("banIPWaitingToAdd");
if(w != null) {
List<ProxiedPlayer> lst = (List<ProxiedPlayer>)p0.getAttachment().get("banIPWaitingToKick");
if(p1.length != 1 || (!p1[0].equalsIgnoreCase("confirm") && !p1[0].equalsIgnoreCase("cancel"))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-ip" : "/eag-ban-ip") + " confirm" + ChatColor.RED + " to add IP " + ChatColor.WHITE + w +
ChatColor.RED + " and ban " + ChatColor.WHITE + lst.size() + ChatColor.RED + " players");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-ip" : "/eag-ban-ip") + " cancel" + ChatColor.RED + " to cancel this operation");
}else {
if(p1[0].equalsIgnoreCase("confirm")) {
try {
if(BanList.banIP(w)) {
for(ProxiedPlayer pp : lst) {
pp.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by IP");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + pp.getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added IP '" + ChatColor.WHITE + w + ChatColor.GREEN + "' to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "IP '" + ChatColor.WHITE + w + ChatColor.RED + "' is already on the ban list");
}
} catch (UnknownHostException e) {
e.printStackTrace();
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "ERROR: address '" + ChatColor.WHITE + w + ChatColor.RED + "' is suddenly invalid for some reason");
}
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Canceled ban");
}
p0.getAttachment().remove("banIPWaitingToAdd");
p0.getAttachment().remove("banIPWaitingToKick");
}
return;
}
if(p1.length != 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "How to use: " + ChatColor.WHITE + (replaceBukkit ? "/ban-ip" : "/eag-ban-ip") + " <addr|player>");
return;
}
boolean isPlayer = false;
IPBan p = null;
try {
p = BanList.constructIpBan(p1[0]);
}catch(Throwable t) {
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
if(pp.getName().equalsIgnoreCase(p1[0])) {
Object addr = pp.getAttachment().get("remoteAddr");
if(addr != null) {
String newAddr = ((InetAddress)addr).getHostAddress();
isPlayer = true;
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Player '" + ChatColor.WHITE + p1[0] + ChatColor.GREEN + "' has IP " + ChatColor.WHITE + newAddr);
p1[0] = newAddr;
try {
p = BanList.constructIpBan(p1[0]);
}catch(UnknownHostException ex) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Address '" + ChatColor.WHITE + p1[0] + "' is suddenly invalid: " + ChatColor.WHITE + p1[0]);
return;
}
}
break;
}
}
if(!isPlayer) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Player '" + ChatColor.WHITE + p1[0] + "' is not on this server");
return;
}
}
boolean blocked = false;
for(IPBan b : BanList.blockedBans) {
if(b.checkBan(p.getBaseAddress()) || p.checkBan(b.getBaseAddress())) {
blocked = true;
}
}
if(blocked) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Cannot ban '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "', it will ban local addresses that may break your game");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To force, add to the " + ChatColor.WHITE + "[IPs]" + ChatColor.RED + " section of " + ChatColor.WHITE + "bans.txt" + ChatColor.RED + " in your bungee directory");
return;
}
boolean isSenderGonnaGetKicked = false;
List<ProxiedPlayer> usersThatAreGonnaBeKicked = new ArrayList();
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
Object addr = pp.getAttachment().get("remoteAddr");
if(addr != null) {
InetAddress addrr = (InetAddress)addr;
if(p.checkBan(addrr)) {
usersThatAreGonnaBeKicked.add(pp);
if(pp.getName().equalsIgnoreCase(p0.getName())) {
isSenderGonnaGetKicked = true;
break;
}
}
}
}
if(isSenderGonnaGetKicked) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "banning address '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' will ban you off of your own server");
return;
}
if(usersThatAreGonnaBeKicked.size() > 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "WARNING: banning address '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is gonna ban " +
ChatColor.WHITE + usersThatAreGonnaBeKicked.size() + ChatColor.RED + " players off of your server");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-ip" : "/eag-ban-ip") + " confirm" + ChatColor.RED + " to continue, or type " +
ChatColor.WHITE + (replaceBukkit ? "/ban-ip" : "/eag-ban-ip") + " cancel" + ChatColor.RED + " to cancel");
p0.getAttachment().put("banIPWaitingToKick", usersThatAreGonnaBeKicked);
p0.getAttachment().put("banIPWaitingToAdd", p1[0]);
}else {
try {
if(BanList.banIP(p1[0])) {
if(usersThatAreGonnaBeKicked.size() > 0) {
usersThatAreGonnaBeKicked.get(0).disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by IP");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + usersThatAreGonnaBeKicked.get(0).getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added IP '" + ChatColor.WHITE + p1[0] + ChatColor.GREEN + "' to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "IP '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is already on the ban list");
}
} catch (UnknownHostException e) {
e.printStackTrace();
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "ERROR: address '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is suddenly invalid for some reason");
return;
}
}
}
}

View File

@ -0,0 +1,106 @@
package net.md_5.bungee.command;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalBanRegex extends Command {
private final boolean replaceBukkit;
public CommandGlobalBanRegex(boolean replaceBukkit) {
super(replaceBukkit ? "ban-regex" : "eag-ban-regex", "bungeecord.command.eag.banregex", replaceBukkit ? new String[] { "eag-ban-regex", "e-ban-regex",
"gban-regex", "eag-banregex", "e-banregex", "gbanregex", "banregex" } : new String[] { "e-ban-regex", "gban-regex",
"eag-banregex", "e-banregex", "gbanregex" });
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
String w = (String) p0.getAttachment().get("banRegexWaitingToAdd");
if(w != null) {
List<ProxiedPlayer> lst = (List<ProxiedPlayer>)p0.getAttachment().get("banRegexWaitingToKick");
if(p1.length != 1 || (!p1[0].equalsIgnoreCase("confirm") && !p1[0].equalsIgnoreCase("cancel"))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-regex" : "/eag-ban-regex") + " confirm" + ChatColor.RED + " to add regex " + ChatColor.WHITE + w +
ChatColor.RED + " and ban " + ChatColor.WHITE + lst.size() + ChatColor.RED + " players");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-regex" : "/eag-ban-regex") + " cancel" + ChatColor.RED + " to cancel this operation");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
}else {
if(p1[0].equalsIgnoreCase("confirm")) {
if(BanList.banRegex(w)) {
for(ProxiedPlayer pp : lst) {
pp.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by regex");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + pp.getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added regex '" + ChatColor.WHITE + w + ChatColor.GREEN + "' to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Regex '" + ChatColor.WHITE + w + ChatColor.RED + "' is already banned");
}
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Canceled ban");
}
p0.getAttachment().remove("banRegexWaitingToAdd");
p0.getAttachment().remove("banRegexWaitingToKick");
}
return;
}
if(p1.length != 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "How to use: " + ChatColor.WHITE + (replaceBukkit ? "/ban-regex" : "/eag-ban-regex") + " <pattern>");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
return;
}
Pattern p;
try {
p = Pattern.compile(p1[0]);
}catch(Throwable t) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Regex syntax error: " + t.getMessage());
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
return;
}
boolean isSenderGonnaGetKicked = false;
List<ProxiedPlayer> usersThatAreGonnaBeKicked = new ArrayList();
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
String n = pp.getName().toLowerCase();
if(p.matcher(n).matches()) {
usersThatAreGonnaBeKicked.add(pp);
if(n.equalsIgnoreCase(p0.getName())) {
isSenderGonnaGetKicked = true;
break;
}
}
}
if(isSenderGonnaGetKicked) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "banning regex '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is gonna ban your own username");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
return;
}
if(usersThatAreGonnaBeKicked.size() > 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "WARNING: banning regex '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is gonna ban " +
ChatColor.WHITE + usersThatAreGonnaBeKicked.size() + ChatColor.RED + " players off of your server");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-regex" : "/eag-ban-regex") + " confirm" + ChatColor.RED + " to continue, or type " +
ChatColor.WHITE + "/eag-ban-regex cancel" + ChatColor.RED + " to cancel");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
p0.getAttachment().put("banRegexWaitingToKick", usersThatAreGonnaBeKicked);
p0.getAttachment().put("banRegexWaitingToAdd", p1[0]);
}else {
if(BanList.banRegex(p1[0])) {
if(usersThatAreGonnaBeKicked.size() > 0) {
usersThatAreGonnaBeKicked.get(0).disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by regex");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + usersThatAreGonnaBeKicked.get(0).getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added regex '" + ChatColor.WHITE + p1[0] + ChatColor.GREEN + "' to the ban list");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Note: all usernames are converted to lowercase before being matched");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Regex '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is already banned");
}
}
}
}

View File

@ -0,0 +1,21 @@
package net.md_5.bungee.command;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalBanReload extends Command {
public CommandGlobalBanReload(boolean replaceBukkit) {
super(replaceBukkit ? "reloadban" : "eag-reloadban", "bungeecord.command.eag.reloadban", replaceBukkit ? new String[] { "eag-reloadban", "banreload", "eag-banreload", "e-reloadban",
"e-banreload", "gbanreload", "greloadban"} : new String[] { "eag-banreload", "e-reloadban", "e-banreload", "gbanreload", "greloadban"});
}
@Override
public void execute(CommandSender p0, String[] p1) {
BanList.maybeReloadBans(p0);
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.WHITE + "Ban list reloaded");
}
}

View File

@ -0,0 +1,125 @@
package net.md_5.bungee.command;
import java.util.ArrayList;
import java.util.List;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalBanWildcard extends Command {
private final boolean replaceBukkit;
public CommandGlobalBanWildcard(boolean replaceBukkit) {
super(replaceBukkit ? "ban-wildcard" : "eag-ban-wildcard", "bungeecord.command.eag.banwildcard", replaceBukkit ? new String[] { "eag-ban-wildcard", "e-ban-wildcard", "gban-wildcard",
"banwildcard", "eag-banwildcard", "banwildcard"} : new String[] { "e-ban-wildcard", "gban-wildcard", "eag-banwildcard"});
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
String w = (String) p0.getAttachment().get("banWildcardWaitingToAdd");
if(w != null) {
List<ProxiedPlayer> lst = (List<ProxiedPlayer>)p0.getAttachment().get("banWildcardWaitingToKick");
if(p1.length != 1 || (!p1[0].equalsIgnoreCase("confirm") && !p1[0].equalsIgnoreCase("cancel"))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-wildcard" : "/eag-ban-wildcard") + " confirm" + ChatColor.RED + " to add wildcard " + ChatColor.WHITE + w +
ChatColor.RED + " and ban " + ChatColor.WHITE + lst.size() + ChatColor.RED + " players");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-wildcard" : "/eag-ban-wildcard") + " cancel" + ChatColor.RED + " to cancel this operation");
}else {
if(p1[0].equalsIgnoreCase("confirm")) {
if(BanList.banWildcard(w)) {
for(ProxiedPlayer pp : lst) {
pp.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by wildcard");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + pp.getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added wildcard '" + ChatColor.WHITE + w + ChatColor.GREEN + "' to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Wildcard '" + ChatColor.WHITE + w + ChatColor.RED + "' is already banned");
}
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Canceled ban");
}
p0.getAttachment().remove("banWildcardWaitingToAdd");
p0.getAttachment().remove("banWildcardWaitingToKick");
}
return;
}
if(p1.length != 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "How to use: " + ChatColor.WHITE + (replaceBukkit ? "/ban-wildcard" : "/eag-ban-wildcard") + " <pattern>");
return;
}
p1[0] = p1[0].toLowerCase();
String s = p1[0];
boolean startStar = s.startsWith("*");
if(startStar) {
s = s.substring(1);
}
boolean endStar = s.endsWith("*");
if(endStar) {
s = s.substring(0, s.length() - 1);
}
if(!startStar && !endStar) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "'" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is not a wildcard, try '"
+ ChatColor.WHITE + "*" + p1[0] + ChatColor.RED + "' or '" + ChatColor.WHITE + p1[0] + "*" + ChatColor.RED + "' or '" + ChatColor.WHITE
+ "*" + p1[0] + "*" + ChatColor.RED + "' instead");
return;
}
boolean isSenderGonnaGetKicked = false;
List<ProxiedPlayer> usersThatAreGonnaBeKicked = new ArrayList();
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
String n = pp.getName().toLowerCase();
if(startStar && endStar) {
if(n.contains(s)) {
usersThatAreGonnaBeKicked.add(pp);
if(pp.getName().equalsIgnoreCase(p0.getName())) {
isSenderGonnaGetKicked = true;
break;
}
}
}else if(startStar) {
if(n.endsWith(s)) {
usersThatAreGonnaBeKicked.add(pp);
if(pp.getName().equalsIgnoreCase(p0.getName())) {
isSenderGonnaGetKicked = true;
break;
}
}
}else if(endStar) {
if(n.startsWith(s)) {
usersThatAreGonnaBeKicked.add(pp);
if(pp.getName().equalsIgnoreCase(p0.getName())) {
isSenderGonnaGetKicked = true;
break;
}
}
}
}
if(isSenderGonnaGetKicked) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "banning wildcard '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is gonna ban your own username");
return;
}
if(usersThatAreGonnaBeKicked.size() > 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "WARNING: banning wildcard '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is gonna ban " +
ChatColor.WHITE + usersThatAreGonnaBeKicked.size() + ChatColor.RED + " players off of your server");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Type " + ChatColor.WHITE + (replaceBukkit ? "/ban-wildcard" : "/eag-ban-wildcard") + " confirm" + ChatColor.RED + " to continue, or type " +
ChatColor.WHITE + (replaceBukkit ? "/ban-wildcard" : "/eag-ban-wildcard") + " cancel" + ChatColor.RED + " to cancel");
p0.getAttachment().put("banWildcardWaitingToKick", usersThatAreGonnaBeKicked);
p0.getAttachment().put("banWildcardWaitingToAdd", p1[0]);
}else {
if(BanList.banWildcard(p1[0])) {
if(usersThatAreGonnaBeKicked.size() > 0) {
usersThatAreGonnaBeKicked.get(0).disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: banned by wildcard");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Kicked: " + ChatColor.WHITE + usersThatAreGonnaBeKicked.get(0).getName());
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Added wildcard '" + ChatColor.WHITE + p1[0] + ChatColor.GREEN + "' to the ban list");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Wildcard '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is already banned");
}
}
}
}

View File

@ -0,0 +1,56 @@
package net.md_5.bungee.command;
import java.net.InetAddress;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
import net.md_5.bungee.eaglercraft.BanList.BanCheck;
import net.md_5.bungee.eaglercraft.BanList.BanState;
public class CommandGlobalCheckBan extends Command {
private final boolean replaceBukkit;
public CommandGlobalCheckBan(boolean replaceBukkit) {
super(replaceBukkit ? "banned" : "eag-bannned", "bungeecord.command.eag.banned", replaceBukkit ? new String[] { "eag-banned", "isbanned", "e-banned", "gbanned", "eag-isbanned", "e-isbanned", "gisbanned" } :
new String[] { "e-banned", "gbanned", "eag-isbanned", "e-isbanned", "gisbanned" });
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length != 1) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To check if a player or IP is banned, use: " + ChatColor.WHITE + (replaceBukkit ? "/banned" : "/eag-banned") + " <username|ip>");
}else {
BanCheck bc = BanList.checkBanned(p1[0]);
if(!bc.isBanned()) {
try {
InetAddress addr = InetAddress.getByName(p1[0]);
bc = BanList.checkIpBanned(addr);
if(bc.isBanned()) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "IP address '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is banned by: "
+ "'" + ChatColor.WHITE + bc.match + ChatColor.RED + "' " + ChatColor.YELLOW + "(" + bc.string + ")");
return;
}
}catch(Throwable t) {
// no
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Player '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' has not been banned");
}else {
if(bc.reason == BanState.USER_BANNED) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Player '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is banned by username, reason: "
+ ChatColor.YELLOW + "\"" + bc.string + "\"");
}else if(bc.reason == BanState.WILDCARD_BANNED) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Player '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is banned by wildcard: "
+ ChatColor.WHITE + "\"" + bc.match + "\"");
}else if(bc.reason == BanState.REGEX_BANNED) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Player '" + ChatColor.WHITE + p1[0] + ChatColor.RED + "' is banned by regex: "
+ ChatColor.WHITE + "\"" + bc.match + "\"");
}
}
}
}
}

View File

@ -0,0 +1,66 @@
package net.md_5.bungee.command;
import java.util.List;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalListBan extends Command {
private final boolean replaceBukkit;
public CommandGlobalListBan(boolean replaceBukkit) {
super(replaceBukkit ? "banlist" : "eag-banlist", "bungeecord.command.eag.banlist", replaceBukkit ? new String[] { "eag-banlist", "gbanlist", "e-banlist",
"gbanlist" } : new String[] { "gbanlist", "e-banlist" });
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length == 0 || (p1.length == 1 && (p1[0].equalsIgnoreCase("user") || p1[0].equalsIgnoreCase("username")
|| p1[0].equalsIgnoreCase("users") || p1[0].equalsIgnoreCase("usernames")))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Players banned by username: " + ChatColor.WHITE + BanList.listAllBans());
return;
}else if(p1.length == 1) {
if(p1[0].equalsIgnoreCase("regex") || p1[0].equalsIgnoreCase("regexes")) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Regex ban list: " + ChatColor.WHITE + BanList.listAllRegexBans());
return;
}else if(p1[0].equalsIgnoreCase("wildcard") || p1[0].equalsIgnoreCase("wildcards")) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Wildcard ban list: " + ChatColor.WHITE + BanList.listAllWildcardBans());
return;
}else if(p1[0].equalsIgnoreCase("ip") || p1[0].equalsIgnoreCase("ips")) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To list IP bans, use: " + ChatColor.WHITE + (replaceBukkit ? "/banlist" : "/eag-banlist") + " ip <addr|netmask> [v4|v6]");
return;
}
}else if(p1.length > 1 && p1.length <= 3 && (p1[0].equalsIgnoreCase("ip") || p1[0].equalsIgnoreCase("ips"))) {
int addrOrNetmask = 0;
if(p1[1].equalsIgnoreCase("addr") || p1[1].equalsIgnoreCase("addrs")) {
addrOrNetmask = 1;
}else if(p1[1].equalsIgnoreCase("netmask") || p1[1].equalsIgnoreCase("netmasks")) {
addrOrNetmask = 2;
}
if(addrOrNetmask > 0) {
boolean yes = false;
if(p1.length == 2 || (p1.length == 3 && (p1[2].equalsIgnoreCase("v4") || p1[2].equals("4")))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "IPv4 " + (addrOrNetmask == 2 ? "netmask" : "address") + " ban list: " + ChatColor.WHITE + BanList.listAllIPBans(false, addrOrNetmask == 2));
yes = true;
}
if(p1.length == 2 || (p1.length == 3 && (p1[2].equalsIgnoreCase("v6") || p1[2].equals("6")))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "IPv6 " + (addrOrNetmask == 2 ? "netmask" : "address") + " ban list: " + ChatColor.WHITE + BanList.listAllIPBans(true, addrOrNetmask == 2));
yes = true;
}
if(yes) {
return;
}
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To list IP bans, use: " + ChatColor.WHITE + (replaceBukkit ? "/banlist" : "/eag-banlist") + " ip <addr|netmask> [v4|v6]");
return;
}
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To list all user bans, use: " + ChatColor.WHITE + (replaceBukkit ? "/banlist" : "/eag-banlist"));
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To list ips, regexes, and wildcards, use: " + ChatColor.WHITE + (replaceBukkit ? "/banlist" : "/eag-banlist") + " <ip|regex|wildcard>");
return;
}
}

View File

@ -0,0 +1,56 @@
package net.md_5.bungee.command;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.eaglercraft.BanList;
public class CommandGlobalUnban extends Command {
private final boolean replaceBukkit;
public CommandGlobalUnban(boolean replaceBukkit) {
super(replaceBukkit ? "unban" : "eag-unban", "bungeecord.command.eag.unban", replaceBukkit ? new String[] {"eag-unban", "e-unban", "gunban"} :new String[] {"e-unban", "gunban"});
this.replaceBukkit = replaceBukkit;
}
@Override
public void execute(CommandSender p0, String[] p1) {
if(p1.length != 2 || (!p1[0].equalsIgnoreCase("user") && !p1[0].equalsIgnoreCase("username") && !p1[0].equalsIgnoreCase("player")
&& !p1[0].equalsIgnoreCase("wildcard") && !p1[0].equalsIgnoreCase("regex") && !p1[0].equalsIgnoreCase("ip"))) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To unban a player, use: " + ChatColor.WHITE + "/" + (replaceBukkit?"":"eag-") + "unban user <player>");
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "To unban an ip/wildcard/regex, use: " + ChatColor.WHITE + "/" + (replaceBukkit?"":"eag-") + "unban <ip|wildcard|regex> <value>");
return;
}
if(p1[0].equalsIgnoreCase("user") || p1[0].equalsIgnoreCase("username") || p1[0].equalsIgnoreCase("player")) {
if(BanList.unban(p1[1])) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "User '" + ChatColor.WHITE + p1[1] + ChatColor.GREEN + "' was unbanned");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "User '" + ChatColor.WHITE + p1[1] + ChatColor.RED + "' is not banned");
}
}else if(p1[0].equalsIgnoreCase("ip")) {
try {
if(BanList.unbanIP(p1[1])) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "IP '" + ChatColor.WHITE + p1[1] + ChatColor.GREEN + "' was unbanned");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "IP '" + ChatColor.WHITE + p1[1] + ChatColor.RED + "' is not banned");
}
}catch(Throwable t) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "IP address '" + ChatColor.WHITE + p1[1] + ChatColor.RED + "' is invalid: " + t.getMessage());
}
}else if(p1[0].equalsIgnoreCase("wildcard")) {
if(BanList.unbanWildcard(p1[1])) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Wildcard '" + ChatColor.WHITE + p1[1] + ChatColor.GREEN + "' was unbanned");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Wildcard '" + ChatColor.WHITE + p1[1] + ChatColor.RED + "' is not banned");
}
}else if(p1[0].equalsIgnoreCase("regex")) {
if(BanList.unbanRegex(p1[1])) {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.GREEN + "Regex '" + ChatColor.WHITE + p1[1] + ChatColor.GREEN + "' was unbanned");
}else {
p0.sendMessage(BanList.banChatMessagePrefix + ChatColor.RED + "Regex '" + ChatColor.WHITE + p1[1] + ChatColor.RED + "' is not banned");
}
}
}
}

View File

@ -6,6 +6,9 @@ package net.md_5.bungee.command;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.ProxyServer;
import java.net.InetAddress;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
@ -25,7 +28,12 @@ public class CommandIP extends Command {
if (user == null) {
sender.sendMessage(ChatColor.RED + "That user is not online");
} else {
sender.sendMessage(ChatColor.BLUE + "IP of " + args[0] + " is " + user.getAddress());
Object o = user.getAttachment().get("remoteAddr");
if(o != null) {
sender.sendMessage(ChatColor.BLUE + "IP of " + args[0] + " is " + (InetAddress)o);
}else {
sender.sendMessage(ChatColor.BLUE + "IP of " + args[0] + " is " + user.getAddress());
}
}
}
}

View File

@ -4,14 +4,16 @@
package net.md_5.bungee.command;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.Collection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.CommandSender;
public class ConsoleCommandSender implements CommandSender {
private static final ConsoleCommandSender instance;
private static final Map<String, Object> attachment = new WeakHashMap();
private ConsoleCommandSender() {
}
@ -65,4 +67,9 @@ public class ConsoleCommandSender implements CommandSender {
static {
instance = new ConsoleCommandSender();
}
@Override
public Map<String, Object> getAttachment() {
return attachment;
}
}

View File

@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
import net.md_5.bungee.api.ProxyServer;
import java.util.UUID;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.eaglercraft.EaglercraftBungee;
import gnu.trove.map.TMap;
import net.md_5.bungee.api.config.ListenerInfo;
import java.util.Collection;
@ -24,6 +25,8 @@ public class Configuration {
private AuthServiceInfo authInfo;
private boolean onlineMode;
private int playerLimit;
private String name;
private boolean showBanType;
public Configuration() {
this.timeout = 30000;
@ -38,9 +41,18 @@ public class Configuration {
this.listeners = adapter.getListeners();
this.timeout = adapter.getInt("timeout", this.timeout);
this.uuid = adapter.getString("stats", this.uuid);
if(this.uuid.equalsIgnoreCase("595698b3-9c36-4e86-b1ee-cb3027038f41")) {
this.uuid = UUID.randomUUID().toString();
System.err.println("Notice: this server has the stats UUID \"595698b3-9c36-4e86-b1ee-cb3027038f41\" which is a known duplicate");
System.err.println("It has been updated to \"" + this.uuid + "\". This is not an error");
adapter.getMap().put("stats", this.uuid);
adapter.forceSave();
}
this.authInfo = adapter.getAuthSettings();
this.onlineMode = false;
this.playerLimit = adapter.getInt("player_limit", this.playerLimit);
this.name = adapter.getString("server_name", EaglercraftBungee.name + " Server");
this.showBanType = adapter.getBoolean("display_ban_type_on_kick", false);
Preconditions.checkArgument(this.listeners != null && !this.listeners.isEmpty(), (Object) "No listeners defined.");
final Map<String, ServerInfo> newServers = adapter.getServers();
Preconditions.checkArgument(newServers != null && !newServers.isEmpty(), (Object) "No servers defined");
@ -88,4 +100,13 @@ public class Configuration {
public AuthServiceInfo getAuthInfo() {
return authInfo;
}
public String getServerName() {
return name;
}
public boolean shouldShowBanType() {
return this.showBanType;
}
}

View File

@ -8,10 +8,13 @@ import net.md_5.bungee.tab.ServerUnique;
import net.md_5.bungee.tab.GlobalPing;
import net.md_5.bungee.tab.Global;
import net.md_5.bungee.api.tab.TabListHandler;
import net.md_5.bungee.eaglercraft.WebSocketRateLimiter;
import net.md_5.bungee.api.config.TexturePackInfo;
import net.md_5.bungee.api.ChatColor;
import java.util.HashSet;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.MOTDCacheConfiguration;
import java.util.Collection;
import java.net.InetSocketAddress;
import java.util.Iterator;
@ -24,6 +27,7 @@ import java.io.FileWriter;
import java.util.LinkedHashMap;
import java.io.InputStream;
import java.util.Collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.io.IOException;
@ -67,21 +71,11 @@ public class YamlConfig implements ConfigurationAdapter {
final Map<String, Object> permissions = this.get("permissions", new HashMap<String, Object>());
if (permissions.isEmpty()) {
permissions.put("default", Arrays.asList("bungeecord.command.server", "bungeecord.command.list"));
permissions.put("admin", Arrays.asList("bungeecord.command.alert", "bungeecord.command.end", "bungeecord.command.ip", "bungeecord.command.reload"));
permissions.put("admin", Arrays.asList("bungeecord.command.alert", "bungeecord.command.end", "bungeecord.command.ip", "bungeecord.command.reload",
"bungeecord.command.eag.ban", "bungeecord.command.eag.banwildcard", "bungeecord.command.eag.banip", "bungeecord.command.eag.banregex",
"bungeecord.command.eag.reloadban", "bungeecord.command.eag.banned", "bungeecord.command.eag.banlist", "bungeecord.command.eag.unban", "bungeecord.command.eag.ratelimit"));
}
final Map<String, Object> groups = this.get("groups", new HashMap<String, Object>());
if (groups.isEmpty()) {
groups.put("lax1dude", Collections.singletonList("admin"));
}
/*
final Map<String, Object> auth = this.get("authservice", new HashMap<String, Object>());
if(auth.isEmpty()) {
auth.put("enabled", false);
auth.put("limbo", "lobby");
auth.put("authfile", "passwords.yml");
auth.put("timeout", 30);
}
*/
this.get("groups", new HashMap<String, Object>());
}
private <T> T get(final String path, final T def) {
@ -155,13 +149,25 @@ public class YamlConfig implements ConfigurationAdapter {
//forcedDef.put("pvp.md-5.net", "pvp");
final Collection<ListenerInfo> ret = new HashSet<ListenerInfo>();
for (final Map<String, Object> val : base) {
String motd = this.get("motd", "&6&lbungeecord eaglercraft server |>", val);
String motd = this.get("motd", null, val);
if(motd != null) {
val.remove("motd");
}
motd = this.get("motd1", motd, val);
if(motd == null) {
motd = this.get("motd1", "&6An Eaglercraft server", val);
}
motd = ChatColor.translateAlternateColorCodes('&', motd);
String motd2 = this.get("motd2", null, val);
if(motd2 != null && motd2.length() > 0) {
motd = motd + "\n" + ChatColor.translateAlternateColorCodes('&', motd2);
}
final int maxPlayers = this.get("max_players", 60, val);
final String defaultServer = this.get("default_server", "lobby", val);
final String fallbackServer = this.get("fallback_server", defaultServer, val);
final boolean forceDefault = this.get("force_default_server", true, val);
final boolean websocket = this.get("websocket", true, val);
final boolean forwardIp = this.get("forward_ip", false, val);
final String host = this.get("host", "0.0.0.0:25565", val);
final int tabListSize = this.get("tab_size", 60, val);
final InetSocketAddress address = Util.getAddr(host);
@ -170,16 +176,78 @@ public class YamlConfig implements ConfigurationAdapter {
final int textureSize = this.get("texture_size", 16, val);
final TexturePackInfo texture = (textureURL == null) ? null : new TexturePackInfo(textureURL, textureSize);
final String tabListName = this.get("tab_list", "GLOBAL_PING", val);
final String serverIcon = this.get("server_icon", "server-icon.png", val);
final boolean allowMOTD = this.get("allow_motd", true, val);
final boolean allowQuery = this.get("allow_query", true, val);
final MOTDCacheConfiguration cacheConfig = readCacheConfiguration(this.get("request_motd_cache", new HashMap<String, Object>(), val));
WebSocketRateLimiter ratelimitIP = null;
WebSocketRateLimiter ratelimitLogin = null;
WebSocketRateLimiter ratelimitMOTD = null;
WebSocketRateLimiter ratelimitQuery = null;
final Map<String, Object> rateLimits = this.get("ratelimit", new HashMap<String, Object>(), val);
final Map<String, Object> ratelimitIPConfig = this.get("ip", new HashMap<String, Object>(), rateLimits);
final Map<String, Object> ratelimitLoginConfig = this.get("login", new HashMap<String, Object>(), rateLimits);
final Map<String, Object> ratelimitMOTDConfig = this.get("motd", new HashMap<String, Object>(), rateLimits);
final Map<String, Object> ratelimitQueryConfig = this.get("query", new HashMap<String, Object>(), rateLimits);
if(this.get("enable", true, ratelimitIPConfig)) {
ratelimitIP = new WebSocketRateLimiter(
this.get("period", 90, ratelimitIPConfig),
this.get("limit", 60, ratelimitIPConfig),
this.get("limit_lockout", 80, ratelimitIPConfig),
this.get("lockout_duration", 1200, ratelimitIPConfig),
this.get("exceptions", new ArrayList<String>(), ratelimitIPConfig)
);
}
if(this.get("enable", true, ratelimitLoginConfig)) {
ratelimitLogin = new WebSocketRateLimiter(
this.get("period", 50, ratelimitLoginConfig),
this.get("limit", 5, ratelimitLoginConfig),
this.get("limit_lockout", 10, ratelimitLoginConfig),
this.get("lockout_duration", 300, ratelimitLoginConfig),
this.get("exceptions", new ArrayList<String>(), ratelimitLoginConfig)
);
}
if(this.get("enable", true, ratelimitMOTDConfig)) {
ratelimitMOTD = new WebSocketRateLimiter(
this.get("period", 30, ratelimitMOTDConfig),
this.get("limit", 5, ratelimitMOTDConfig),
this.get("limit_lockout", 15, ratelimitMOTDConfig),
this.get("lockout_duration", 1200, ratelimitMOTDConfig),
this.get("exceptions", new ArrayList<String>(), ratelimitMOTDConfig)
);
}
if(this.get("enable", true, ratelimitQueryConfig)) {
ratelimitQuery = new WebSocketRateLimiter(
this.get("period", 90, ratelimitQueryConfig),
this.get("limit", 60, ratelimitQueryConfig),
this.get("limit_lockout", 80, ratelimitQueryConfig),
this.get("lockout_duration", 1200, ratelimitQueryConfig),
this.get("exceptions", new ArrayList<String>(), ratelimitQueryConfig)
);
}
DefaultTabList value = DefaultTabList.valueOf(tabListName.toUpperCase());
if (value == null) {
value = DefaultTabList.GLOBAL_PING;
}
final ListenerInfo info = new ListenerInfo(address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, websocket, forced, texture, value.clazz);
ret.add(info);
ret.add(new ListenerInfo(host, address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, websocket, forwardIp,
forced, texture, value.clazz, serverIcon, cacheConfig, allowMOTD, allowQuery, ratelimitIP, ratelimitLogin, ratelimitMOTD, ratelimitQuery));
}
return ret;
}
private MOTDCacheConfiguration readCacheConfiguration(Map<String, Object> val) {
final int ttl = this.get("cache_ttl", 7200, val);
final boolean anim = this.get("online_server_list_animation", false, val);
final boolean results = this.get("online_server_list_results", true, val);
final boolean trending = this.get("online_server_list_trending", true, val);
final boolean portfolios = this.get("online_server_list_portfolios", false, val);
return new MOTDCacheConfiguration(ttl, anim, results, trending, portfolios);
}
@Override
public Collection<String> getGroups(final String player) {
final Collection<String> groups = this.get("groups." + player, (Collection<String>) null);
@ -209,4 +277,15 @@ public class YamlConfig implements ConfigurationAdapter {
//return new AuthServiceInfo(this.get("enabled", true, auth), this.get("limbo", "lobby", auth), new File(this.get("authfile", "passwords.yml", auth)), this.get("timeout", 30, auth));
return null;
}
@Override
public Map<String, Object> getMap() {
return config;
}
@Override
public void forceSave() {
this.save();
}
}

View File

@ -6,6 +6,7 @@ package net.md_5.bungee.connection;
import java.beans.ConstructorProperties;
import java.util.ArrayList;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import net.md_5.bungee.protocol.packet.PacketFFKick;
import net.md_5.bungee.api.config.ServerInfo;
@ -37,6 +38,10 @@ import net.md_5.bungee.protocol.Forge;
import net.md_5.bungee.netty.PacketDecoder;
import com.google.common.base.Preconditions;
import net.md_5.bungee.api.event.ProxyPingEvent;
import net.md_5.bungee.eaglercraft.BanList;
import net.md_5.bungee.eaglercraft.WebSocketProxy;
import net.md_5.bungee.eaglercraft.BanList.BanCheck;
import net.md_5.bungee.eaglercraft.BanList.BanState;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.protocol.packet.PacketFEPing;
import net.md_5.bungee.Util;
@ -112,23 +117,67 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
if (handshake.getProcolVersion() == 69) {
skipEncryption = true;
this.handshake.swapProtocol((byte) 61);
}else if(handshake.getProcolVersion() == 71) {
this.disconnect("this server does not support microsoft accounts");
return;
}else if(handshake.getProcolVersion() != 61) {
this.disconnect("minecraft 1.5.2 required for eaglercraft backdoor access");
return;
}
if (handshake.getUsername().length() < 3) {
String un = handshake.getUsername();
if (un.length() < 3) {
this.disconnect("Username must be at least 3 characters");
return;
}
if (handshake.getUsername().length() > 16) {
if (un.length() > 16) {
this.disconnect("Cannot have username longer than 16 characters");
return;
}
if(!un.equals(un.replaceAll("[^A-Za-z0-9\\-_]", "_").trim())) {
this.disconnect("Go fuck yourself");
return;
}
InetAddress sc = WebSocketProxy.localToRemote.get(this.ch.getHandle().remoteAddress());
if(sc == null) {
System.out.println("WARNING: player '" + un + "' doesn't have a websocket IP, remote address: " + this.ch.getHandle().remoteAddress().toString());
}else {
BanCheck bc = BanList.checkIpBanned(sc);
if(bc.isBanned()) {
System.err.println("Player '" + un + "' [" + sc.toString() + "] is banned by IP: " + bc.match + " (" + bc.string + ")");
this.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: " + bc.string);
return;
}else {
System.out.println("Player '" + un + "' [" + sc.toString() + "] has remote websocket IP: " + sc.getHostAddress());
}
}
BanCheck bc = BanList.checkBanned(un);
if(bc.isBanned()) {
switch(bc.reason) {
case USER_BANNED:
System.err.println("Player '" + un + "' is banned by username, because '" + bc.string + "'");
break;
case WILDCARD_BANNED:
System.err.println("Player '" + un + "' is banned by wildcard: " + bc.match);
break;
case REGEX_BANNED:
System.err.println("Player '" + un + "' is banned by regex: " + bc.match);
break;
default:
System.err.println("Player '" + un + "' is banned: " + bc.string);
}
if(bc.reason == BanState.USER_BANNED || ((BungeeCord)bungee).config.shouldShowBanType()) {
this.disconnect("" + ChatColor.RED + "You are banned.\n" + ChatColor.DARK_GRAY + "Reason: " + bc.string);
}else {
this.disconnect("" + ChatColor.RED + "You are banned.");
}
return;
}
final int limit = BungeeCord.getInstance().config.getPlayerLimit();
if (limit > 0 && this.bungee.getOnlineCount() > limit) {
this.disconnect(this.bungee.getTranslation("proxy_full"));
return;
}
if (!BungeeCord.getInstance().config.isOnlineMode() && this.bungee.getPlayer(handshake.getUsername()) != null) {
if (!BungeeCord.getInstance().config.isOnlineMode() && this.bungee.getPlayer(un) != null) {
this.disconnect(this.bungee.getTranslation("already_connected"));
return;
}
@ -189,6 +238,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
public void handle(final PacketCDClientStatus clientStatus) throws Exception {
Preconditions.checkState(this.thisState == State.LOGIN, (Object) "Not expecting LOGIN");
final UserConnection userCon = new UserConnection(this.bungee, this.ch, this.getName(), this);
InetAddress ins = WebSocketProxy.localToRemote.get(this.ch.getHandle().remoteAddress());
if(ins != null) {
userCon.getAttachment().put("remoteAddr", ins);
}
userCon.init();
this.bungee.getPluginManager().callEvent(new PostLoginEvent(userCon));
((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class)).setHandler(new UpstreamBridge(this.bungee, userCon));
@ -218,7 +271,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection {
@Override
public InetSocketAddress getVirtualHost() {
return (this.handshake == null) ? null : new InetSocketAddress(this.handshake.getHost(), this.handshake.getPort());
return (this.handshake == null) ? null : new InetSocketAddress(this.handshake.getHost(), this.handshake.getPort() & 0xFFFF);
}
@Override

View File

@ -0,0 +1,872 @@
package net.md_5.bungee.eaglercraft;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.eaglercraft.sun.net.util.IPAddressUtil;
public class BanList {
private static final Object banListMutex = new Object();
public static enum BanState {
NOT_BANNED, USER_BANNED, IP_BANNED, WILDCARD_BANNED, REGEX_BANNED;
}
public static class BanCheck {
public final BanState reason;
public final String match;
public final String string;
private BanCheck(BanState reason, String match, String string) {
this.reason = reason;
this.match = match;
this.string = string;
}
public boolean isBanned() {
return reason != BanState.NOT_BANNED;
}
}
private static class RegexBan {
public final String string;
public final Pattern compiled;
private RegexBan(String string, Pattern compiled) {
this.string = string;
this.compiled = compiled;
}
public String toString() {
return string;
}
public int hashCode() {
return string.hashCode();
}
}
public static interface IPBan {
boolean checkBan(InetAddress addr);
InetAddress getBaseAddress();
boolean hasNetMask();
}
private static class IPBan4 implements IPBan {
private final int addr;
private final InetAddress addrI;
private final int mask;
private final String string;
protected IPBan4(Inet4Address addr, String s, int mask) {
if(mask >= 32) {
this.mask = 0xFFFFFFFF;
}else {
this.mask = ~((1 << (32 - mask)) - 1);
}
this.string = s;
byte[] bits = addr.getAddress();
this.addr = this.mask & ((bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | (bits[3] & 0xFF));
this.addrI = addr;
}
@Override
public boolean checkBan(InetAddress addr4) {
if(addr4 instanceof Inet4Address) {
Inet4Address a = (Inet4Address)addr4;
byte[] bits = a.getAddress();
int addrBits = ((bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | (bits[3] & 0xFF));
return (mask & addrBits) == addr;
}else {
return false;
}
}
@Override
public InetAddress getBaseAddress() {
return addrI;
}
@Override
public String toString() {
return string;
}
@Override
public int hashCode() {
return string.hashCode();
}
@Override
public boolean equals(Object o) {
return o != null && o instanceof IPBan4 && ((IPBan4)o).addr == addr && ((IPBan4)o).mask == mask;
}
@Override
public boolean hasNetMask() {
return mask != 0xFFFFFFFF;
}
}
private static class IPBan6 implements IPBan {
private static final BigInteger mask128 = new BigInteger(1, new byte[] {
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF
});
private final BigInteger addr;
private final InetAddress addrI;
private final BigInteger mask;
private final String string;
protected IPBan6(Inet6Address addr, String s, int mask) {
this.mask = BigInteger.valueOf(1l).shiftLeft(128 - mask).subtract(BigInteger.valueOf(1l)).xor(mask128);
this.string = s.toLowerCase();
this.addr = new BigInteger(1, addr.getAddress()).and(this.mask);
this.addrI = addr;
}
@Override
public boolean checkBan(InetAddress addr6) {
if(addr6 instanceof Inet6Address) {
Inet6Address a = (Inet6Address)addr6;
BigInteger addrBits = new BigInteger(1, a.getAddress()).and(this.mask);
return addr.equals(addrBits);
}else {
return false;
}
}
@Override
public InetAddress getBaseAddress() {
return addrI;
}
@Override
public String toString() {
return string;
}
@Override
public int hashCode() {
return string.hashCode();
}
@Override
public boolean equals(Object o) {
return o != null && o instanceof IPBan6 && ((IPBan6)o).addr.equals(addr) && ((IPBan6)o).mask.equals(mask);
}
@Override
public boolean hasNetMask() {
return !mask.equals(mask128);
}
}
public static final File bansFile = new File("bans.txt");
public static final String banChatMessagePrefix = ChatColor.GOLD + "[BanList] ";
public static final Map<String,String> userBans = new HashMap();
public static final Set<IPBan> ipBans = new HashSet();
public static final Set<String> wildcardBans = new HashSet();
public static final Set<RegexBan> regexBans = new HashSet();
private static List<String> currentBanList = null;
public static final List<IPBan> blockedBans = new ArrayList();
static {
try {
blockedBans.add(constructIpBan("127.0.0.0/8"));
}catch(UnknownHostException e) {
System.err.println("Error: could not whitelist '127.0.0.0/8'");
e.printStackTrace();
}
try {
blockedBans.add(constructIpBan("10.0.0.0/8"));
}catch(UnknownHostException e) {
System.err.println("Error: could not whitelist '10.0.0.0/8'");
e.printStackTrace();
}
try {
blockedBans.add(constructIpBan("172.24.0.0/14"));
}catch(UnknownHostException e) {
System.err.println("Error: could not whitelist '172.24.0.0/14'");
e.printStackTrace();
}
try {
blockedBans.add(constructIpBan("192.168.0.0/16"));
}catch(UnknownHostException e) {
System.err.println("Error: could not whitelist '192.168.0.0/16'");
e.printStackTrace();
}
try {
blockedBans.add(constructIpBan("::1/128"));
}catch(UnknownHostException e) {
System.err.println("Error: could not whitelist '::1/128'");
e.printStackTrace();
}
}
public static boolean isBlockedBan(InetAddress addr) {
for(IPBan b : BanList.blockedBans) {
if(b.checkBan(addr)) {
return true;
}
}
return false;
}
private static long lastListTest = 0l;
private static long lastListLoad = 0l;
private static boolean fileIsBroken = false;
public static BanCheck checkIpBanned(InetAddress addr) {
synchronized(banListMutex) {
for(IPBan b : ipBans) {
if(b.checkBan(addr)) {
return new BanCheck(BanState.IP_BANNED, b.toString(), b.hasNetMask() ? "Banned by Netmask" : "Banned by IP");
}
}
}
return new BanCheck(BanState.NOT_BANNED, "none", "not banned");
}
public static BanCheck checkBanned(String player) {
synchronized(banListMutex) {
player = player.trim().toLowerCase();
String r = userBans.get(player);
if(r != null) {
if(r.length() <= 0) {
r = "The ban hammer has spoken";
}
return new BanCheck(BanState.USER_BANNED, player, r);
}
for(String ss : wildcardBans) {
String s = ss;
boolean startStar = s.startsWith("*");
if(startStar) {
s = s.substring(1);
}
boolean endStar = s.endsWith("*");
if(endStar) {
s = s.substring(0, s.length() - 1);
}
if(startStar && endStar) {
if(player.contains(s)) {
return new BanCheck(BanState.WILDCARD_BANNED, ss, "You've been banned via wildcard");
}
}else if(endStar) {
if(player.startsWith(s)) {
return new BanCheck(BanState.WILDCARD_BANNED, ss, "You've been banned via wildcard");
}
}else if(startStar) {
if(player.endsWith(s)) {
return new BanCheck(BanState.WILDCARD_BANNED, ss, "You've been banned via wildcard");
}
}else {
if(player.equals(s)) {
return new BanCheck(BanState.WILDCARD_BANNED, ss, "You've been banned via wildcard");
}
}
}
for(RegexBan p : regexBans) {
if(p.compiled.matcher(player).matches()) {
return new BanCheck(BanState.REGEX_BANNED, p.string, "You've been banned via regex");
}
}
}
return new BanCheck(BanState.NOT_BANNED, "none", "not banned");
}
private static void saveCurrentBanListLines() {
try {
PrintWriter pf = new PrintWriter(new FileWriter(bansFile));
for(String s : currentBanList) {
pf.println(s);
}
pf.close();
lastListLoad = lastListTest = System.currentTimeMillis();
}catch(Throwable t) {
System.err.println("ERROR: the ban list could not be saved to file '" + bansFile.getName() + "', please fix this or you will lose all your bans next time this server restarts");
t.printStackTrace();
}
}
private static boolean addEntryToFile(BanState b, String s) {
if(b == null || b == BanState.NOT_BANNED) {
return false;
}
String wantedHeader = b == BanState.USER_BANNED ? "[Usernames]" : (b == BanState.WILDCARD_BANNED ? "[Wildcards]" : (b == BanState.REGEX_BANNED ? "[Regex]" : (b == BanState.IP_BANNED ? "[IPs]" : "shit")));
int lastFullPart = -1;
boolean isFilePart = false;
boolean isPartStart = false;
for(int i = 0, l = currentBanList.size(); i < l; ++i) {
String ss = currentBanList.get(i).trim();
if(ss.length() <= 0) {
continue;
}
if(ss.startsWith("#")) {
continue;
}
if(ss.equalsIgnoreCase(wantedHeader)) {
isFilePart = true;
isPartStart = true;
lastFullPart = i;
}else if(ss.indexOf('[') != -1) {
if(isFilePart) {
break;
}
}else {
if(isFilePart) {
lastFullPart = i;
isPartStart = false;
}
}
}
if(lastFullPart != -1) {
if(isPartStart) {
lastFullPart += 1;
currentBanList.add(lastFullPart, "");
}
lastFullPart += 1;
currentBanList.add(lastFullPart, s);
lastFullPart += 1;
if(currentBanList.size() > lastFullPart && currentBanList.get(lastFullPart).trim().length() > 0) {
currentBanList.add(lastFullPart, "");
}
}else {
if(currentBanList.size() > 0 && currentBanList.get(currentBanList.size() - 1).trim().length() > 0) {
currentBanList.add("");
}
currentBanList.add(wantedHeader);
currentBanList.add("");
currentBanList.add(s);
currentBanList.add("");
}
saveCurrentBanListLines();
return true;
}
private static boolean removeEntryFromFile(BanState b, String s, boolean ignoreCase) {
if(b == null || b == BanState.NOT_BANNED) {
return false;
}
String wantedHeader = b == BanState.USER_BANNED ? "[Usernames]" : (b == BanState.WILDCARD_BANNED ? "[Wildcards]" : (b == BanState.REGEX_BANNED ? "[Regex]" : (b == BanState.IP_BANNED ? "[IPs]" : "shit")));
Iterator<String> lns = currentBanList.iterator();
boolean isFilePart = false;
boolean wasRemoved = false;
while(lns.hasNext()) {
String ss = lns.next().trim();
if(ss.length() <= 0) {
continue;
}
if(ss.startsWith("#")) {
continue;
}
if(ss.equalsIgnoreCase(wantedHeader)) {
isFilePart = true;
}else if(ss.indexOf('[') != -1) {
isFilePart = false;
}else {
if(b == BanState.USER_BANNED && ss.contains(":")) {
ss = ss.substring(0, ss.indexOf(':')).trim();
}
if(isFilePart && (ignoreCase ? ss.equalsIgnoreCase(s) : ss.equals(s))) {
lns.remove();
wasRemoved = true;
}
}
}
if(wasRemoved) {
saveCurrentBanListLines();
}
return wasRemoved;
}
public static boolean unban(String player) {
synchronized(banListMutex) {
String s = player.trim().toLowerCase();
if(userBans.remove(s) != null) {
removeEntryFromFile(BanState.USER_BANNED, player, true);
return true;
}else {
return false;
}
}
}
public static boolean ban(String player, String reason) {
synchronized(banListMutex) {
player = player.trim().toLowerCase();
if(userBans.put(player, reason) == null) {
addEntryToFile(BanState.USER_BANNED, player + (reason == null || reason.length() <= 0 ? "" : ": " + reason));
return true;
}else {
return false;
}
}
}
public static boolean banWildcard(String wc) throws PatternSyntaxException {
synchronized(banListMutex) {
wc = wc.trim().toLowerCase();
boolean b = wc.contains("*");
if(!b || (b && !wc.startsWith("*") && !wc.endsWith("*"))) {
throw new PatternSyntaxException("Wildcard can only begin and/or end with *", wc, 0);
}
if(wildcardBans.add(wc)) {
addEntryToFile(BanState.WILDCARD_BANNED, wc);
return true;
}else {
return false;
}
}
}
public static boolean unbanWildcard(String wc) {
synchronized(banListMutex) {
wc = wc.trim().toLowerCase();
if(wildcardBans.remove(wc)) {
removeEntryFromFile(BanState.WILDCARD_BANNED, wc, true);
return true;
}else {
return false;
}
}
}
public static boolean banRegex(String regex) throws PatternSyntaxException {
synchronized(banListMutex) {
regex = regex.trim();
Pattern p = Pattern.compile(regex);
if(regexBans.add(new RegexBan(regex, p))) {
addEntryToFile(BanState.REGEX_BANNED, regex);
return true;
}else {
return false;
}
}
}
public static boolean unbanRegex(String regex) {
synchronized(banListMutex) {
regex = regex.trim();
Iterator<RegexBan> banz = regexBans.iterator();
while(banz.hasNext()) {
if(banz.next().string.equals(regex)) {
banz.remove();
removeEntryFromFile(BanState.REGEX_BANNED, regex, false);
return true;
}
}
return false;
}
}
public static IPBan constructIpBan(String ip) throws UnknownHostException {
synchronized(banListMutex) {
ip = ip.trim();
String s = ip;
int subnet = -1;
int i = s.indexOf('/');
if(i != -1) {
String s2 = s.substring(i + 1);
s = s.substring(0, i);
try {
subnet = Integer.parseInt(s2);
}catch(Throwable t) {
throw new UnknownHostException("Invalid netmask: '" + s + "'");
}
}
if(!IPAddressUtil.isIPv4LiteralAddress(s) && !IPAddressUtil.isIPv6LiteralAddress(s)) {
throw new UnknownHostException("Invalid address: '" + s + "'");
}
InetAddress aa = InetAddress.getByName(s);
if(aa instanceof Inet4Address) {
if(subnet > 32 || subnet < -1) {
throw new UnknownHostException("IPv4 netmask '" + subnet + "' is invalid");
}
if(subnet == -1) {
subnet = 32;
}
return new IPBan4((Inet4Address)aa, ip, subnet);
}else if(aa instanceof Inet6Address) {
if(subnet > 128 || subnet < -1) {
throw new UnknownHostException("IPv6 netmask '" + subnet + "' is invalid");
}
if(subnet == -1) {
subnet = 128;
}
return new IPBan6((Inet6Address)aa, ip, subnet);
}else {
throw new UnknownHostException("Only ipv4 and ipv6 addresses allowed in Eaglercraft");
}
}
}
public static boolean banIP(String ip) throws UnknownHostException {
synchronized(banListMutex) {
ip = ip.trim();
IPBan b = constructIpBan(ip);
if(b != null) {
if(ipBans.add(b)) {
addEntryToFile(BanState.IP_BANNED, ip);
return true;
}
}
return false;
}
}
public static boolean unbanIP(String ip) throws UnknownHostException {
synchronized(banListMutex) {
ip = ip.trim();
IPBan b = constructIpBan(ip);
if(b != null) {
Iterator<IPBan> banz = ipBans.iterator();
while(banz.hasNext()) {
IPBan bb = banz.next();
if(bb.equals(b)) {
banz.remove();
removeEntryFromFile(BanState.IP_BANNED, bb.toString(), true);
return true;
}
}
}
return false;
}
}
private static final int MAX_CHAT_LENGTH = 118;
public static String listAllBans() {
synchronized(banListMutex) {
String ret = "";
for(String s : userBans.keySet()) {
if(ret.length() > 0) {
ret += ", ";
}
ret += s;
}
return ret.length() > 0 ? ret : "(none)";
}
}
public static String listAllWildcardBans() {
synchronized(banListMutex) {
String ret = "";
for(String s : wildcardBans) {
if(ret.length() > 0) {
ret += ", ";
}
ret += s;
}
return ret.length() > 0 ? ret : "(none)";
}
}
public static String listAllRegexBans() {
synchronized(banListMutex) {
String ret = "";
for(RegexBan s : regexBans) {
if(ret.length() > 0) {
ret += " | ";
}
ret += s.string;
}
return ret.length() > 0 ? ret : "(none)";
}
}
public static String listAllIPBans(boolean v6, boolean netmask) {
synchronized(banListMutex) {
String ret = "";
for(IPBan b : ipBans) {
if(v6) {
if(b instanceof IPBan6) {
IPBan6 b2 = (IPBan6)b;
if(netmask == b2.hasNetMask()) {
if(ret.length() > 0) {
ret += ", ";
}
ret += b2.string;
}
}
}else {
if(b instanceof IPBan4) {
IPBan4 b2 = (IPBan4)b;
if(netmask == b2.hasNetMask()) {
if(ret.length() > 0) {
ret += ", ";
}
ret += b2.string;
}
}
}
}
if(ret.length() <= 0) {
ret = "(none)";
}
return ret;
}
}
public static void maybeReloadBans(CommandSender cs) {
synchronized(banListMutex) {
long st = System.currentTimeMillis();
if(cs == null && st - lastListTest < 1000l) {
return;
}
lastListTest = st;
boolean ex = bansFile.exists();
if(!fileIsBroken && !ex) {
try {
PrintWriter p = new PrintWriter(new FileWriter(bansFile));
p.println();
p.println("#");
p.println("# This file allows you to configure bans for eaglercraftbungee");
p.println("# When it is saved, eaglercraft should reload it automatically");
p.println("# (check the console though to be safe)");
p.println("#");
p.println("# For a [Usernames] ban, just add the player's name. Use a colon ':' to put in a ban reason");
p.println("# For a [IPs] ban, just add the player's IP, or a subnet like 69.69.0.0/16 to ban all IPs beginning with 69.69.*");
p.println("# For a [Wildcards] ban, type a string and prefix and/or suffix it with * to define the wildcard");
p.println("# For a [Regex] ban, type a valid regular expression in the java.util.regex format");
p.println("#");
p.println("# All bans are case-insensitive, USERNAMES ARE CONVERTED TO LOWERCASE BEFORE BEING MATCHED VIA REGEX");
p.println("# Java regex syntax: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html");
p.println("#");
p.println();
p.println("# set this to to true to use \"/ban\" to ban on bungee instead of \"/eag-ban\"");
p.println("# (most likely needs a restart to take effect)");
p.println("replace-bukkit=false");
p.println();
p.println();
p.println("[Usernames]");
p.println();
p.println("# ban_test1: The ban hammer has spoken!");
p.println("# ban_test2: custom ban message here");
p.println("# ban_test3");
p.println();
p.println("# (remove the '#' before each line to enable)");
p.println();
p.println("[IPs]");
p.println();
p.println("# WARNING: if you're using nginx, banning any player's IP is gonna ban ALL PLAYERS on your server");
p.println("# For this reason, the ban IP command doesn't ban 127.0.0.1 or any other 'private' range IPs");
p.println();
p.println("# 101.202.69.11");
p.println("# 123.21.43.0/24");
p.println("# 2601:1062:69:418:BEEF::10");
p.println("# 2601:6090:420::/48");
p.println();
p.println();
p.println("[Wildcards]");
p.println();
p.println("# *fuck*");
p.println("# shi*");
p.println();
p.println();
p.println("[Regex]");
p.println();
p.println("# you.+are.(a|the).+bitch");
p.println();
p.println();
p.println("# end of file");
p.println();
p.close();
System.out.println("Wrote a new bans.txt to: " + bansFile.getAbsolutePath());
lastListLoad = 0l;
}catch(Throwable t) {
fileIsBroken = true;
if(cs != null) {
cs.sendMessage(banChatMessagePrefix + ChatColor.RED + "Could not create blank 'bans.txt' list file");
cs.sendMessage(banChatMessagePrefix + ChatColor.RED + "(Reason: " + t.toString() + ")");
}
System.err.println("Could not create blank 'bans.txt' list file");
System.err.println("(Reason: " + t.toString() + ")");
t.printStackTrace();
}
return;
}
if(fileIsBroken && ex) {
fileIsBroken = false;
lastListLoad = 0l;
}
if(fileIsBroken) {
return;
}
long lastEdit = bansFile.lastModified();
if(cs != null || lastEdit - lastListLoad > 400l) {
try {
BufferedReader r = new BufferedReader(new FileReader(bansFile));
currentBanList = new LinkedList();
String s;
while((s = r.readLine()) != null) {
currentBanList.add(s);
}
r.close();
lastListLoad = lastEdit;
System.out.println("Server bans.txt changed, it will be reloaded automatically");
if(cs == null) {
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
if(pp.hasPermission("bungeecord.command.eag.reloadban")) {
pp.sendMessage(BanList.banChatMessagePrefix + ChatColor.WHITE + "Your Eaglercraftbungee bans.txt just got modified, it will be reloaded asap");
pp.sendMessage(BanList.banChatMessagePrefix + ChatColor.YELLOW + "Stop your server and check your config immediately if you don't know how this happened!!");
}
}
}
parseListFrom();
System.out.println("Reload complete");
}catch(Throwable t) {
if(cs != null) {
cs.sendMessage(banChatMessagePrefix + ChatColor.RED + "Could not reload 'bans.txt' list file");
cs.sendMessage(banChatMessagePrefix + ChatColor.RED + "(Reason: " + t.toString() + ")");
}
System.err.println("Could not reload 'bans.txt' list file");
System.err.println("(Reason: " + t.toString() + ")");
}
}
}
}
private static void parseListFrom() {
userBans.clear();
ipBans.clear();
wildcardBans.clear();
regexBans.clear();
int filePart = 0;
boolean replaceBukkit = false;
for(String s : currentBanList) {
s = s.trim();
if(s.length() <= 0) {
continue;
}
if(s.startsWith("#")) {
continue;
}
if(s.equals("[Usernames]")) {
filePart = 1;
}else if(s.equals("[Wildcards]")) {
filePart = 2;
}else if(s.equals("[Regex]")) {
filePart = 3;
}else if(s.equals("[IPs]")) {
filePart = 4;
}else if(s.equals("replace-bukkit=true")) {
replaceBukkit = true;
}else if(s.equals("replace-bukkit=false")) {
continue;
}else {
if(filePart == 1) {
int i = s.indexOf(':');
if(i == -1) {
userBans.put(s.toLowerCase(), "");
}else {
userBans.put(s.substring(0, i).trim().toLowerCase(), s.substring(i + 1).trim());
}
}else if(filePart == 2) {
boolean ws = s.startsWith("*");
boolean we = s.endsWith("*");
if(!ws && !we) {
if(s.contains("*")) {
System.err.println("Error: wildcard '" + s + "' contains a '*' not at the start/end of the string");
}else {
System.err.println("Error: wildcard '" + s + "' does not contain a '*' wildcard character");
}
}else {
int total = (ws ? 1 : 0) + (we ? 1 : 0);
int t2 = 0;
for(char c : s.toCharArray()) {
if(c == '*') ++t2;
}
if(total != t2) {
System.err.println("Error: wildcard '" + s + "' contains a '*' not at the start/end of the string");
}
}
wildcardBans.add(s.toLowerCase());
}else if(filePart == 3) {
Pattern p = null;
try {
p = Pattern.compile(s);
}catch(Throwable t) {
System.err.println("Error: the regex " + s.toLowerCase() + " is invalid");
System.err.println("Reason: " + t.getClass().getSimpleName() + ": " + t.getLocalizedMessage());
}
if(p != null) {
regexBans.add(new RegexBan(s, p));
}
}else if(filePart == 4) {
String ss = s;
int subnet = -1;
int i = s.indexOf('/');
if(i != -1) {
String s2 = s.substring(i + 1);
s = s.substring(0, i);
try {
subnet = Integer.parseInt(s2);
}catch(Throwable t) {
System.err.println("Error: the subnet '"+ s2 +"' for IP ban address " + s + " was invalid");
subnet = -2;
}
}
if(subnet >= -1) {
try {
InetAddress aa = InetAddress.getByName(s);
if(aa instanceof Inet4Address) {
if(subnet == -1) {
subnet = 32;
}
ipBans.add(new IPBan4((Inet4Address)aa, ss, subnet));
}else if(aa instanceof Inet6Address) {
if(subnet == -1) {
subnet = 128;
}
ipBans.add(new IPBan6((Inet6Address)aa, ss, subnet));
}else {
throw new UnknownHostException("Only ipv4 and ipv6 addresses allowed in Eaglercraft");
}
}catch(Throwable t) {
System.err.println("Error: the IP ban address " + s + " could not be parsed");
t.printStackTrace();
}
}
}
}
}
BungeeCord.getInstance().reconfigureBanCommands(replaceBukkit);
}
}

View File

@ -0,0 +1,10 @@
package net.md_5.bungee.eaglercraft;
public class EaglercraftBungee {
public static final String brand = "Eagtek";
public static final String name = "EaglercraftBungee";
public static final String version = "0.2.0";
public static final boolean cracked = true;
}

View File

@ -0,0 +1,124 @@
package net.md_5.bungee.eaglercraft;
/**
* base implementation of MD4 family style digest as outlined in
* "Handbook of Applied Cryptography", pages 344 - 347.
*/
public abstract class GeneralDigest {
private byte[] xBuf;
private int xBufOff;
private long byteCount;
/**
* Standard constructor
*/
protected GeneralDigest()
{
xBuf = new byte[4];
xBufOff = 0;
}
/**
* Copy constructor. We are using copy constructors in place
* of the Object.clone() interface as this interface is not
* supported by J2ME.
*/
protected GeneralDigest(GeneralDigest t)
{
xBuf = new byte[t.xBuf.length];
System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
xBufOff = t.xBufOff;
byteCount = t.byteCount;
}
public void update(
byte in)
{
xBuf[xBufOff++] = in;
if (xBufOff == xBuf.length)
{
processWord(xBuf, 0);
xBufOff = 0;
}
byteCount++;
}
public void update(
byte[] in,
int inOff,
int len)
{
//
// fill the current word
//
while ((xBufOff != 0) && (len > 0))
{
update(in[inOff]);
inOff++;
len--;
}
//
// process whole words.
//
while (len > xBuf.length)
{
processWord(in, inOff);
inOff += xBuf.length;
len -= xBuf.length;
byteCount += xBuf.length;
}
//
// load in the remainder.
//
while (len > 0)
{
update(in[inOff]);
inOff++;
len--;
}
}
public void finish()
{
long bitLength = (byteCount << 3);
//
// add the pad bytes.
//
update((byte)128);
while (xBufOff != 0)
{
update((byte)0);
}
processLength(bitLength);
processBlock();
}
public void reset()
{
byteCount = 0;
xBufOff = 0;
for ( int i = 0; i < xBuf.length; i++ ) {
xBuf[i] = 0;
}
}
protected abstract void processWord(byte[] in, int inOff);
protected abstract void processLength(long bitLength);
protected abstract void processBlock();
}

View File

@ -0,0 +1,202 @@
package net.md_5.bungee.eaglercraft;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.java_websocket.WebSocket;
import org.json.JSONArray;
import org.json.JSONObject;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.MOTD;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.MOTDCacheConfiguration;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class MOTDConnectionImpl extends QueryConnectionImpl implements MOTD {
private String line1;
private String line2;
private List<String> players;
private int[] bitmap;
private int onlinePlayers;
private int maxPlayers;
private boolean hasIcon;
private boolean iconDirty;
private String subType;
public MOTDConnectionImpl(ListenerInfo listener, InetAddress addr, WebSocket socket, String arg1) {
super(listener, addr, socket, "motd");
String[] lns = listener.getMotd().split("\n");
if(lns.length >= 1) {
line1 = lns[0];
}
if(lns.length >= 2) {
line2 = lns[1];
}
maxPlayers = listener.getMaxPlayers();
onlinePlayers = BungeeCord.getInstance().getOnlineCount();
players = new ArrayList();
for(ProxiedPlayer pp : BungeeCord.getInstance().getPlayers()) {
players.add(pp.getDisplayName());
if(players.size() >= 9) {
players.add("" + ChatColor.GRAY + ChatColor.ITALIC + "(" + (onlinePlayers - players.size()) + " more)");
break;
}
}
bitmap = new int[4096];
setReturnType("motd");
int i = arg1.indexOf('.');
if(i > 0) {
subType = arg1.substring(i + 1);
if(subType.length() == 0) {
subType = "motd";
}
}else {
subType = "motd";
}
if(!subType.startsWith("noicon") && !subType.startsWith("cache.noicon")) {
iconDirty = hasIcon = listener.isIconSet();
if(hasIcon) {
System.arraycopy(listener.getServerIconCache(), 0, bitmap, 0, 4096);
}
}
}
@Override
public String getLine1() {
return line1;
}
@Override
public String getLine2() {
return line2;
}
@Override
public List<String> getPlayerList() {
return players;
}
@Override
public int[] getBitmap() {
return bitmap;
}
@Override
public int getOnlinePlayers() {
return onlinePlayers;
}
@Override
public int getMaxPlayers() {
return maxPlayers;
}
@Override
public String getSubType() {
return subType;
}
@Override
public void setLine1(String p) {
line1 = p;
}
@Override
public void setLine2(String p) {
line2 = p;
}
@Override
public void setPlayerList(List<String> p) {
players = p;
}
@Override
public void setPlayerList(String... p) {
players = Arrays.asList(p);
}
@Override
public void setBitmap(int[] p) {
iconDirty = hasIcon = true;
bitmap = p;
}
@Override
public void setOnlinePlayers(int i) {
onlinePlayers = i;
}
@Override
public void setMaxPlayers(int i) {
maxPlayers = i;
}
@Override
public void sendToUser() {
if(!isClosed()) {
JSONObject obj = new JSONObject();
if(subType.startsWith("cache.anim")) {
obj.put("unsupported", true);
writeResponse(obj);
close();
return;
}else if(subType.startsWith("cache")) {
JSONArray cacheControl = new JSONArray();
MOTDCacheConfiguration cc = listener.getCacheConfig();
if(cc.cacheServerListAnimation) {
cacheControl.put("animation");
}
if(cc.cacheServerListResults) {
cacheControl.put("results");
}
if(cc.cacheServerListTrending) {
cacheControl.put("trending");
}
if(cc.cacheServerListPortfolios) {
cacheControl.put("portfolio");
}
obj.put("cache", cacheControl);
obj.put("ttl", cc.cacheTTL);
}else {
MOTDCacheConfiguration cc = listener.getCacheConfig();
obj.put("cache", cc.cacheServerListAnimation || cc.cacheServerListResults ||
cc.cacheServerListTrending || cc.cacheServerListPortfolios);
}
boolean noIcon = subType.startsWith("noicon") || subType.startsWith("cache.noicon");
JSONArray motd = new JSONArray();
if(line1 != null && line1.length() > 0) motd.put(line1);
if(line2 != null && line2.length() > 0) motd.put(line2);
obj.put("motd", motd);
obj.put("icon", hasIcon && !noIcon);
obj.put("online", onlinePlayers);
obj.put("max", maxPlayers);
JSONArray playerz = new JSONArray();
for(String s : players) {
playerz.put(s);
}
obj.put("players", playerz);
writeResponse(obj);
if(hasIcon && !noIcon && iconDirty && bitmap != null) {
byte[] iconPixels = new byte[16384];
for(int i = 0; i < 4096; ++i) {
iconPixels[i * 4] = (byte)((bitmap[i] >> 16) & 0xFF);
iconPixels[i * 4 + 1] = (byte)((bitmap[i] >> 8) & 0xFF);
iconPixels[i * 4 + 2] = (byte)(bitmap[i] & 0xFF);
iconPixels[i * 4 + 3] = (byte)((bitmap[i] >> 24) & 0xFF);
}
writeResponseBinary(iconPixels);
iconDirty = false;
}
if(subType.startsWith("cache")) {
close();
}
}
}
}

View File

@ -16,7 +16,7 @@ public class PluginEaglerSkins extends Plugin implements Listener {
private final HashMap<String,byte[]> skinCollection = new HashMap();
private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, 128*64*4, 128*128*4, 1 };
private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, 128*64*4, 128*128*4, 1, 64*64*4, 128*128*4 };
private static final int VALID_DEFAULT_SKINS = 33;
@ -41,27 +41,31 @@ public class PluginEaglerSkins extends Plugin implements Listener {
if(event.getSender() instanceof UserConnection && event.getData().length > 0) {
String user = ((UserConnection)event.getSender()).getName();
byte[] msg = event.getData();
if("EAG|MySkin".equals(event.getTag())) {
int t = (int)msg[0] & 0xFF;
if(t >= 0 && t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
if(msg.length == 2) {
if(((int)msg[1] & 0xFF) >= VALID_DEFAULT_SKINS) {
msg[1] = 0;
try {
if("EAG|MySkin".equals(event.getTag())) {
int t = (int)msg[0] & 0xFF;
if(t >= 0 && t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
if(msg.length == 2) {
if(((int)msg[1] & 0xFF) >= VALID_DEFAULT_SKINS) {
msg[1] = 0;
}
}
skinCollection.put(user, msg);
}
}else if("EAG|FetchSkin".equals(event.getTag())) {
if(msg.length > 2) {
String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
byte[] data;
if((data = skinCollection.get(fetch)) != null) {
byte[] conc = new byte[data.length + 2];
conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
System.arraycopy(data, 0, conc, 2, data.length);
((UserConnection)event.getSender()).sendData("EAG|UserSkin", conc);
}
}
skinCollection.put(user, msg);
}
}else if("EAG|FetchSkin".equals(event.getTag())) {
if(msg.length > 2) {
String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
byte[] data;
if((data = skinCollection.get(fetch)) != null) {
byte[] conc = new byte[data.length + 2];
conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
System.arraycopy(data, 0, conc, 2, data.length);
((UserConnection)event.getSender()).sendData("EAG|UserSkin", conc);
}
}
}catch(Throwable t) {
// hacker
}
}
}

View File

@ -0,0 +1,121 @@
package net.md_5.bungee.eaglercraft;
import java.net.InetAddress;
import java.util.LinkedList;
import java.util.List;
import org.java_websocket.WebSocket;
import net.md_5.bungee.api.QueryConnection;
import net.md_5.bungee.api.config.ListenerInfo;
public class QueryConnectionImpl implements QueryConnection {
protected ListenerInfo listener;
protected InetAddress addr;
protected WebSocket socket;
protected String accept;
protected String responseType;
protected List<String> packetBuffer = new LinkedList();
protected long creationTime;
protected boolean keepAlive = false;
public static String confirmHash = null;
public QueryConnectionImpl(ListenerInfo listener, InetAddress addr, WebSocket socket, String accept) {
this.listener = listener;
this.addr = addr;
this.socket = socket;
this.accept = accept.toLowerCase();
this.responseType = "unknown";
this.creationTime = System.currentTimeMillis();
}
public void postMessage(String m) {
synchronized(packetBuffer) {
packetBuffer.add(m);
}
}
@Override
public InetAddress getRemoteAddress() {
return addr;
}
@Override
public ListenerInfo getListener() {
return listener;
}
@Override
public String getAccept() {
return accept;
}
@Override
public int availableRequests() {
synchronized(packetBuffer) {
return packetBuffer.size();
}
}
@Override
public String readRequestString() {
synchronized(packetBuffer) {
if(packetBuffer.size() > 0) {
return packetBuffer.remove(0);
}else {
return null;
}
}
}
@Override
public long getConnectionTimestamp() {
return creationTime;
}
@Override
public void writeResponseRaw(String msg) {
socket.send(msg);
}
@Override
public void writeResponseBinary(byte[] blob) {
socket.send(blob);
}
@Override
public void keepAlive(boolean yes) {
keepAlive = yes;
}
@Override
public boolean shouldKeepAlive() {
return keepAlive;
}
@Override
public boolean isClosed() {
return socket.isClosing() || socket.isClosed();
}
@Override
public void close() {
socket.close();
}
@Override
public void setReturnType(String type) {
if(!"unknown".equals(responseType) && !type.equalsIgnoreCase(responseType)) {
throw new IllegalStateException("Tried to change query return type to '" + type + "' when it was already set to '" + responseType + "'");
}
responseType = type;
}
@Override
public String getReturnType() {
return responseType;
}
}

View File

@ -0,0 +1,270 @@
package net.md_5.bungee.eaglercraft;
/**
* implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
*
* It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
* is the "endienness" of the word processing!
*/
public class SHA1Digest
extends GeneralDigest
{
private static final int DIGEST_LENGTH = 20;
private int H1, H2, H3, H4, H5;
private int[] X = new int[80];
private int xOff;
/**
* Standard constructor
*/
public SHA1Digest()
{
reset();
}
/**
* Copy constructor. This will copy the state of the provided
* message digest.
*/
public SHA1Digest(SHA1Digest t)
{
super(t);
H1 = t.H1;
H2 = t.H2;
H3 = t.H3;
H4 = t.H4;
H5 = t.H5;
System.arraycopy(t.X, 0, X, 0, t.X.length);
xOff = t.xOff;
}
public String getAlgorithmName()
{
return "SHA-1";
}
public int getDigestSize()
{
return DIGEST_LENGTH;
}
protected void processWord(
byte[] in,
int inOff)
{
X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
| ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff));
if (xOff == 16)
{
processBlock();
}
}
private void unpackWord(
int word,
byte[] out,
int outOff)
{
out[outOff] = (byte)(word >>> 24);
out[outOff + 1] = (byte)(word >>> 16);
out[outOff + 2] = (byte)(word >>> 8);
out[outOff + 3] = (byte)word;
}
protected void processLength(
long bitLength)
{
if (xOff > 14)
{
processBlock();
}
X[14] = (int)(bitLength >>> 32);
X[15] = (int)(bitLength & 0xffffffff);
}
public int doFinal(
byte[] out,
int outOff)
{
finish();
unpackWord(H1, out, outOff);
unpackWord(H2, out, outOff + 4);
unpackWord(H3, out, outOff + 8);
unpackWord(H4, out, outOff + 12);
unpackWord(H5, out, outOff + 16);
reset();
return DIGEST_LENGTH;
}
/**
* reset the chaining variables
*/
public void reset()
{
super.reset();
H1 = 0x67452301;
H2 = 0xefcdab89;
H3 = 0x98badcfe;
H4 = 0x10325476;
H5 = 0xc3d2e1f0;
xOff = 0;
for (int i = 0; i != X.length; i++)
{
X[i] = 0;
}
}
//
// Additive constants
//
private static final int Y1 = 0x5a827999;
private static final int Y2 = 0x6ed9eba1;
private static final int Y3 = 0x8f1bbcdc;
private static final int Y4 = 0xca62c1d6;
private int f(
int u,
int v,
int w)
{
return ((u & v) | ((~u) & w));
}
private int h(
int u,
int v,
int w)
{
return (u ^ v ^ w);
}
private int g(
int u,
int v,
int w)
{
return ((u & v) | (u & w) | (v & w));
}
private int rotateLeft(
int x,
int n)
{
return (x << n) | (x >>> (32 - n));
}
protected void processBlock()
{
//
// expand 16 word block into 80 word block.
//
for (int i = 16; i <= 79; i++)
{
X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
}
//
// set up working variables.
//
int A = H1;
int B = H2;
int C = H3;
int D = H4;
int E = H5;
//
// round 1
//
for (int j = 0; j <= 19; j++)
{
int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
E = D;
D = C;
C = rotateLeft(B, 30);
B = A;
A = t;
}
//
// round 2
//
for (int j = 20; j <= 39; j++)
{
int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
E = D;
D = C;
C = rotateLeft(B, 30);
B = A;
A = t;
}
//
// round 3
//
for (int j = 40; j <= 59; j++)
{
int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
E = D;
D = C;
C = rotateLeft(B, 30);
B = A;
A = t;
}
//
// round 4
//
for (int j = 60; j <= 79; j++)
{
int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
E = D;
D = C;
C = rotateLeft(B, 30);
B = A;
A = t;
}
H1 += A;
H2 += B;
H3 += C;
H4 += D;
H5 += E;
//
// reset the offset and clean out the word buffer.
//
xOff = 0;
for (int i = 0; i != X.length; i++)
{
X[i] = 0;
}
}
private static final String hex = "0123456789abcdef";
public static String hash2string(byte[] b) {
char[] ret = new char[b.length * 2];
for(int i = 0; i < b.length; ++i) {
int bb = (int)b[i] & 0xFF;
ret[i * 2] = hex.charAt((bb >> 4) & 0xF);
ret[i * 2 + 1] = hex.charAt(bb & 0xF);
}
return new String(ret);
}
}

View File

@ -1,35 +1,86 @@
package net.md_5.bungee.eaglercraft;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.MOTD;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.event.WebsocketMOTDEvent;
import net.md_5.bungee.api.event.WebsocketQueryEvent;
import net.md_5.bungee.eaglercraft.WebSocketRateLimiter.RateLimit;
public class WebSocketListener extends WebSocketServer {
public static final String queryResponseBlocked = "{\"type\":\"blocked\"}";
public static final String queryResponseLockout = "{\"type\":\"locked\"}";
public static final String ipBlockedString = "BLOCKED";
public static final String ipLockedString = "LOCKED";
public static class PendingSocket {
public long openTime;
public InetAddress realAddress;
public boolean bypassBan;
protected PendingSocket(long openTime, InetAddress realAddress, boolean bypassBan) {
this.openTime = openTime;
this.realAddress = realAddress;
this.bypassBan = bypassBan;
}
}
private InetSocketAddress bungeeProxy;
private ProxyServer bungeeCord;
private ListenerInfo info;
private final WebSocketRateLimiter ratelimitIP;
private final WebSocketRateLimiter ratelimitLogin;
private final WebSocketRateLimiter ratelimitMOTD;
private final WebSocketRateLimiter ratelimitQuery;
public WebSocketListener(ListenerInfo info, InetSocketAddress sock, ProxyServer bungeeCord) {
super(info.getHost());
this.setTcpNoDelay(true);
this.setConnectionLostTimeout(5);
this.setConnectionLostTimeout(20);
this.start();
this.info = info;
this.bungeeProxy = sock;
this.bungeeCord = bungeeCord;
this.ratelimitIP = info.getRateLimitIP();
this.ratelimitLogin = info.getRateLimitLogin();
this.ratelimitMOTD = info.getRateLimitMOTD();
this.ratelimitQuery = info.getRateLimitQuery();
if(this.ratelimitIP != null) {
this.ratelimitIP.resetLimiters();
}
if(this.ratelimitLogin != null) {
this.ratelimitLogin.resetLimiters();
}
if(this.ratelimitMOTD != null) {
this.ratelimitMOTD.resetLimiters();
}
if(this.ratelimitQuery != null) {
this.ratelimitQuery.resetLimiters();
}
}
@Override
public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) {
if(arg0.getAttachment() != null) {
((WebSocketProxy)arg0.getAttachment()).killConnection();
Object o = arg0.getAttachment();
if(o != null) {
if(o instanceof WebSocketProxy) {
((WebSocketProxy)arg0.getAttachment()).killConnection();
}
}
System.out.println("websocket closed - " + arg0.getRemoteSocketAddress());
}
@Override
@ -39,28 +90,204 @@ public class WebSocketListener extends WebSocketServer {
@Override
public void onMessage(WebSocket arg0, String arg1) {
}
@Override
public void onMessage(WebSocket arg0, ByteBuffer arg1) {
if(arg0.getAttachment() != null) {
((WebSocketProxy)arg0.getAttachment()).sendPacket(arg1);
}
}
@Override
public void onOpen(WebSocket arg0, ClientHandshake arg1) {
System.out.println("websocket opened - " + arg0.getRemoteSocketAddress());
WebSocketProxy proxyObj = new WebSocketProxy(arg0, bungeeProxy);
arg0.setAttachment(proxyObj);
if(!proxyObj.connect()) {
Object o = arg0.getAttachment();
if(o != null) {
if(o instanceof PendingSocket) {
InetAddress realAddr = ((PendingSocket)o).realAddress;
arg1 = arg1.trim().toLowerCase();
QueryConnectionImpl con;
if(arg1.startsWith("accept:")) {
arg1 = arg1.substring(7).trim();
WebsocketQueryEvent evt;
if(arg1.startsWith("motd")) {
if(info.isAllowMOTD()) {
if(ratelimitMOTD != null && !BanList.isBlockedBan(realAddr)) {
RateLimit l = ratelimitMOTD.rateLimit(realAddr);
if(l.blocked()) {
if(l == RateLimit.LIMIT) {
arg0.send(queryResponseBlocked);
}else if(l == RateLimit.NOW_LOCKED_OUT) {
arg0.send(queryResponseLockout);
}
arg0.close();
return;
}
}
con = new MOTDConnectionImpl(info, realAddr, arg0, arg1);
evt = new WebsocketMOTDEvent((MOTD)con);
}else {
arg0.send(queryResponseBlocked);
arg0.close();
return;
}
}else {
if(QueryConnectionImpl.confirmHash != null && arg1.equalsIgnoreCase(QueryConnectionImpl.confirmHash)) {
QueryConnectionImpl.confirmHash = null;
arg0.send("OK");
arg0.close();
return;
}else if(info.isAllowQuery()) {
if(ratelimitQuery != null && !BanList.isBlockedBan(realAddr)) {
RateLimit l = ratelimitQuery.rateLimit(realAddr);
if(l.blocked()) {
if(l == RateLimit.LIMIT) {
arg0.send(queryResponseBlocked);
}else if(l == RateLimit.NOW_LOCKED_OUT) {
arg0.send(queryResponseLockout);
}
arg0.close();
return;
}
}
con = new QueryConnectionImpl(info, realAddr, arg0, arg1);
evt = new WebsocketQueryEvent(con);
}else {
arg0.send(queryResponseBlocked);
arg0.close();
return;
}
}
BungeeCord.getInstance().getPluginManager().callEvent(evt);
if(!con.isClosed() && (con instanceof MOTDConnectionImpl)) {
((MOTDConnectionImpl)con).sendToUser();
}
if(!con.shouldKeepAlive() && !con.isClosed()) {
con.close();
}else {
if(!arg0.isClosed()) {
arg0.setAttachment(con);
}
}
}else {
arg0.close();
}
return;
}else if(o instanceof QueryConnectionImpl) {
((QueryConnectionImpl)o).postMessage(arg1);
}
}else {
arg0.close();
}
}
@Override
public void onStart() {
public void onMessage(WebSocket arg0, ByteBuffer arg1) {
Object o = arg0.getAttachment();
if(o == null || (o instanceof PendingSocket)) {
InetAddress realAddr;
if(o == null) {
realAddr = arg0.getRemoteSocketAddress().getAddress();
}else {
realAddr = ((PendingSocket)o).realAddress;
}
if(ratelimitLogin != null && !BanList.isBlockedBan(realAddr)) {
RateLimit l = ratelimitLogin.rateLimit(realAddr);
if(l.blocked()) {
if(l == RateLimit.LIMIT) {
arg0.send(createRawKickPacket("BLOCKED"));
}else if(l == RateLimit.NOW_LOCKED_OUT) {
arg0.send(createRawKickPacket("LOCKED"));
}
arg0.close();
return;
}
}
WebSocketProxy proxyObj = new WebSocketProxy(arg0, realAddr, bungeeProxy);
arg0.setAttachment(proxyObj);
if(!proxyObj.connect()) {
System.err.println("loopback to '" + bungeeProxy.toString() + "' failed - " + realAddr);
arg0.close();
return;
}
o = proxyObj;
}
if(o != null) {
if(o instanceof WebSocketProxy) {
((WebSocketProxy)o).sendPacket(arg1);
}else {
arg0.close();
}
}
}
@Override
public void onOpen(WebSocket arg0, ClientHandshake arg1) {
InetAddress addr;
if(info.hasForwardedHeaders()) {
String s = arg1.getFieldValue("X-Real-IP");
if(s != null) {
try {
addr = InetAddress.getByName(s);
}catch(UnknownHostException e) {
System.out.println("invalid 'X-Real-IP' header - " + e.toString());
arg0.close();
return;
}
}else {
addr = arg0.getRemoteSocketAddress().getAddress();
}
}else {
addr = arg0.getRemoteSocketAddress().getAddress();
}
boolean bypassBan = BanList.isBlockedBan(addr);
if(!bypassBan && ratelimitIP != null) {
RateLimit l = ratelimitIP.rateLimit(addr);
if(l.blocked()) {
if(l == RateLimit.LIMIT) {
arg0.send(ipBlockedString);
}else if(l == RateLimit.NOW_LOCKED_OUT) {
arg0.send(ipLockedString);
}
arg0.close();
return;
}
}
arg0.setAttachment(new PendingSocket(System.currentTimeMillis(), addr, bypassBan));
}
@Override
public void onStart() {
}
public void closeInactiveSockets() {
for(WebSocket w : this.getConnections()) {
Object o = w.getAttachment();
if(o == null) {
w.close();
}else if(o instanceof PendingSocket) {
if(System.currentTimeMillis() - ((PendingSocket)o).openTime > 1500l) {
w.close();
}
}
}
}
@Override
public void stop() throws IOException, InterruptedException {
for(WebSocket w : this.getConnections()) {
Object o = w.getAttachment();
if(o != null && o instanceof WebSocketProxy) {
((WebSocketProxy)o).killConnection();
}
}
super.stop();
}
private byte[] createRawKickPacket(String str) {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bao);
try {
dout.write(255);
dout.writeShort(str.length());
dout.writeChars(str);
return bao.toByteArray();
}catch(IOException e) {
return new byte[] { (byte)255, 0, 0 };
}
}
public ListenerInfo getInfo() {
return info;
}
}

View File

@ -1,7 +1,9 @@
package net.md_5.bungee.eaglercraft;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import org.java_websocket.WebSocket;
@ -16,6 +18,8 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
/**
* Not the ideal solution but what are we supposed to do
@ -25,20 +29,22 @@ public class WebSocketProxy extends SimpleChannelInboundHandler<ByteBuf> {
private WebSocket client;
private InetSocketAddress tcpListener;
private InetSocketAddress localAddress;
private InetAddress realRemoteAddr;
private NioSocketChannel tcpChannel;
private static final EventLoopGroup group = new NioEventLoopGroup(4);
public static final HashMap<InetSocketAddress,InetAddress> localToRemote = new HashMap();
public WebSocketProxy(WebSocket w, InetSocketAddress addr) {
public WebSocketProxy(WebSocket w, InetAddress remoteAddr, InetSocketAddress addr) {
client = w;
realRemoteAddr = remoteAddr;
tcpListener = addr;
tcpChannel = null;
}
public void killConnection() {
if(client.isOpen()) {
client.close();
}
localToRemote.remove(localAddress);
if(tcpChannel != null && tcpChannel.isOpen()) {
try {
tcpChannel.disconnect().sync();
@ -59,9 +65,16 @@ public class WebSocketProxy extends SimpleChannelInboundHandler<ByteBuf> {
clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(WebSocketProxy.this);
socketChannel.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> paramF) throws Exception {
localToRemote.remove(localAddress);
}
});
}
});
tcpChannel = (NioSocketChannel) clientBootstrap.connect().sync().channel();
localToRemote.put(localAddress = tcpChannel.localAddress(), realRemoteAddr);
return true;
}
}catch(Throwable t) {
@ -89,4 +102,8 @@ public class WebSocketProxy extends SimpleChannelInboundHandler<ByteBuf> {
}
}
public void finalize() {
localToRemote.remove(localAddress);
}
}

View File

@ -0,0 +1,171 @@
package net.md_5.bungee.eaglercraft;
import java.net.InetAddress;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class WebSocketRateLimiter {
public static enum RateLimit {
NONE, LIMIT, LOCKED_OUT, NOW_LOCKED_OUT;
public boolean blocked() {
return this != NONE;
}
}
public final int period;
public final int limit;
public final int lockoutLimit;
public final int lockoutTime;
public final Collection<String> exceptions;
protected final Map<String, RateLimiter> ratelimiters = new HashMap();
public WebSocketRateLimiter(int period, int limit, int lockoutLimit, int lockoutTime, Collection<String> exceptions) {
this.period = period;
this.limit = limit;
this.lockoutLimit = lockoutLimit;
this.lockoutTime = lockoutTime;
this.exceptions = exceptions;
}
protected static class RateLimiter {
protected final WebSocketRateLimiter limiterConfig;
protected RateLimiter(WebSocketRateLimiter limiterConfig) {
this.limiterConfig = limiterConfig;
this.cooldownTimestamp = System.currentTimeMillis();
}
protected int requestCounter = 0;
protected long lockoutTimestamp = 0l;
protected long cooldownTimestamp;
private boolean checkLockout(long currentTimeMillis) {
if(lockoutTimestamp > 0l) {
if(currentTimeMillis - lockoutTimestamp < (long)(limiterConfig.lockoutTime * 1000l)) {
return true;
}else {
lockoutTimestamp = 0l;
requestCounter = 0;
cooldownTimestamp = currentTimeMillis;
}
}
return false;
}
private boolean checkCooldown(long currentTimeMillis) {
long cooldownIncrement = limiterConfig.period * 1000 / limiterConfig.limit;
while(currentTimeMillis - cooldownTimestamp > cooldownIncrement && requestCounter > 0) {
--requestCounter;
cooldownTimestamp += cooldownIncrement;
}
if(requestCounter == 0) {
cooldownTimestamp = currentTimeMillis;
return false;
}else {
return requestCounter >= limiterConfig.limit;
}
}
protected RateLimit increment() {
long t = System.currentTimeMillis();
if(checkLockout(t)) {
return RateLimit.LOCKED_OUT;
}
++requestCounter;
boolean blockByCooldown = checkCooldown(t);
if(requestCounter >= limiterConfig.lockoutLimit) {
requestCounter = 0;
cooldownTimestamp = t;
lockoutTimestamp = t;
return RateLimit.NOW_LOCKED_OUT;
}
if(blockByCooldown) {
return RateLimit.LIMIT;
}else {
return RateLimit.NONE;
}
}
protected RateLimit checkLimited() {
long t = System.currentTimeMillis();
if(checkLockout(t)) {
return RateLimit.LOCKED_OUT;
}else if(checkCooldown(t)) {
return RateLimit.LIMIT;
}else {
return RateLimit.NONE;
}
}
protected boolean checkClear() {
long t = System.currentTimeMillis();
if(checkLockout(t) || checkCooldown(t)) {
return false;
}else if(requestCounter > 0) {
return false;
}else {
return true;
}
}
}
public void resetLimiters() {
synchronized(ratelimiters) {
ratelimiters.clear();
}
}
public void deleteClearLimiters() {
synchronized(ratelimiters) {
Iterator<RateLimiter> itr = ratelimiters.values().iterator();
while(itr.hasNext()) {
if(itr.next().checkClear()) {
itr.remove();
}
}
}
}
public RateLimit checkLimit(InetAddress identifier) {
return checkLimit(identifier.getHostAddress());
}
public RateLimit rateLimit(InetAddress identifier) {
return rateLimit(identifier.getHostAddress());
}
public RateLimit checkLimit(String identifier) {
if(exceptions.contains(identifier)) {
return RateLimit.NONE;
}
synchronized(ratelimiters) {
RateLimiter l = ratelimiters.get(identifier);
if(l == null) {
return RateLimit.NONE;
}else {
return l.checkLimited();
}
}
}
public RateLimit rateLimit(String identifier) {
if(exceptions.contains(identifier)) {
return RateLimit.NONE;
}
synchronized(ratelimiters) {
RateLimiter l = ratelimiters.get(identifier);
if(l == null) {
l = new RateLimiter(this);
ratelimiters.put(identifier, l);
}
return l.increment();
}
}
}

View File

@ -0,0 +1,321 @@
package net.md_5.bungee.eaglercraft.sun.net.util;
import java.net.URL;
import java.util.Arrays;
public class IPAddressUtil {
private static final int INADDR4SZ = 4;
private static final int INADDR16SZ = 16;
private static final int INT16SZ = 2;
private static final long L_IPV6_DELIMS = 0L;
private static final long H_IPV6_DELIMS = 671088640L;
private static final long L_GEN_DELIMS = -8935000888854970368L;
private static final long H_GEN_DELIMS = 671088641L;
private static final long L_AUTH_DELIMS = 288230376151711744L;
private static final long H_AUTH_DELIMS = 671088641L;
private static final long L_COLON = 288230376151711744L;
private static final long H_COLON = 0L;
private static final long L_SLASH = 140737488355328L;
private static final long H_SLASH = 0L;
private static final long L_BACKSLASH = 0L;
private static final long H_BACKSLASH = 268435456L;
private static final long L_NON_PRINTABLE = 4294967295L;
private static final long H_NON_PRINTABLE = -9223372036854775808L;
private static final long L_EXCLUDE = -8935000884560003073L;
private static final long H_EXCLUDE = -9223372035915251711L;
public static byte[] textToNumericFormatV4(String paramString) {
byte[] arrayOfByte = new byte[4];
long l = 0L;
byte b1 = 0;
boolean bool = true;
int i = paramString.length();
if (i == 0 || i > 15)
return null;
for (byte b2 = 0; b2 < i; b2++) {
char c = paramString.charAt(b2);
if (c == '.') {
if (bool || l < 0L || l > 255L || b1 == 3)
return null;
arrayOfByte[b1++] = (byte) (int) (l & 0xFFL);
l = 0L;
bool = true;
} else {
int j = Character.digit(c, 10);
if (j < 0)
return null;
l *= 10L;
l += j;
bool = false;
}
}
if (bool || l < 0L || l >= 1L << (4 - b1) * 8)
return null;
switch (b1) {
case 0 :
arrayOfByte[0] = (byte) (int) (l >> 24L & 0xFFL);
case 1 :
arrayOfByte[1] = (byte) (int) (l >> 16L & 0xFFL);
case 2 :
arrayOfByte[2] = (byte) (int) (l >> 8L & 0xFFL);
case 3 :
arrayOfByte[3] = (byte) (int) (l >> 0L & 0xFFL);
break;
}
return arrayOfByte;
}
public static byte[] textToNumericFormatV6(String paramString) {
if (paramString.length() < 2)
return null;
char[] arrayOfChar = paramString.toCharArray();
byte[] arrayOfByte1 = new byte[16];
int j = arrayOfChar.length;
int k = paramString.indexOf("%");
if (k == j - 1)
return null;
if (k != -1)
j = k;
byte b = -1;
byte b1 = 0, b2 = 0;
if (arrayOfChar[b1] == ':' && arrayOfChar[++b1] != ':')
return null;
byte b3 = b1;
boolean bool = false;
int i = 0;
while (b1 < j) {
char c = arrayOfChar[b1++];
int m = Character.digit(c, 16);
if (m != -1) {
i <<= 4;
i |= m;
if (i > 65535)
return null;
bool = true;
continue;
}
if (c == ':') {
b3 = b1;
if (!bool) {
if (b != -1)
return null;
b = b2;
continue;
}
if (b1 == j)
return null;
if (b2 + 2 > 16)
return null;
arrayOfByte1[b2++] = (byte) (i >> 8 & 0xFF);
arrayOfByte1[b2++] = (byte) (i & 0xFF);
bool = false;
i = 0;
continue;
}
if (c == '.' && b2 + 4 <= 16) {
String str = paramString.substring(b3, j);
byte b4 = 0;
int n = 0;
while ((n = str.indexOf('.', n)) != -1) {
b4++;
n++;
}
if (b4 != 3)
return null;
byte[] arrayOfByte = textToNumericFormatV4(str);
if (arrayOfByte == null)
return null;
for (byte b5 = 0; b5 < 4; b5++)
arrayOfByte1[b2++] = arrayOfByte[b5];
bool = false;
break;
}
return null;
}
if (bool) {
if (b2 + 2 > 16)
return null;
arrayOfByte1[b2++] = (byte) (i >> 8 & 0xFF);
arrayOfByte1[b2++] = (byte) (i & 0xFF);
}
if (b != -1) {
int m = b2 - b;
if (b2 == 16)
return null;
for (b1 = 1; b1 <= m; b1++) {
arrayOfByte1[16 - b1] = arrayOfByte1[b + m - b1];
arrayOfByte1[b + m - b1] = 0;
}
b2 = 16;
}
if (b2 != 16)
return null;
byte[] arrayOfByte2 = convertFromIPv4MappedAddress(arrayOfByte1);
if (arrayOfByte2 != null)
return arrayOfByte2;
return arrayOfByte1;
}
public static boolean isIPv4LiteralAddress(String paramString) {
return (textToNumericFormatV4(paramString) != null);
}
public static boolean isIPv6LiteralAddress(String paramString) {
return (textToNumericFormatV6(paramString) != null);
}
public static byte[] convertFromIPv4MappedAddress(byte[] paramArrayOfbyte) {
if (isIPv4MappedAddress(paramArrayOfbyte)) {
byte[] arrayOfByte = new byte[4];
System.arraycopy(paramArrayOfbyte, 12, arrayOfByte, 0, 4);
return arrayOfByte;
}
return null;
}
private static boolean isIPv4MappedAddress(byte[] paramArrayOfbyte) {
if (paramArrayOfbyte.length < 16)
return false;
if (paramArrayOfbyte[0] == 0 && paramArrayOfbyte[1] == 0 && paramArrayOfbyte[2] == 0 && paramArrayOfbyte[3] == 0
&& paramArrayOfbyte[4] == 0 && paramArrayOfbyte[5] == 0 && paramArrayOfbyte[6] == 0
&& paramArrayOfbyte[7] == 0 && paramArrayOfbyte[8] == 0 && paramArrayOfbyte[9] == 0
&& paramArrayOfbyte[10] == -1 && paramArrayOfbyte[11] == -1)
return true;
return false;
}
public static boolean match(char paramChar, long paramLong1, long paramLong2) {
if (paramChar < '@')
return ((1L << paramChar & paramLong1) != 0L);
return false;
}
public static int scan(String paramString, long paramLong1, long paramLong2) {
byte b = -1;
int i;
if (paramString == null || (i = paramString.length()) == 0)
return -1;
boolean bool = false;
while (++b < i && !(bool = match(paramString.charAt(b), paramLong1, paramLong2)));
if (bool)
return b;
return -1;
}
public static int scan(String paramString, long paramLong1, long paramLong2, char[] paramArrayOfchar) {
byte b = -1;
int i;
if (paramString == null || (i = paramString.length()) == 0)
return -1;
boolean bool = false;
char c2 = paramArrayOfchar[0];
char c1;
while (++b < i && !(bool = match(c1 = paramString.charAt(b), paramLong1, paramLong2))) {
if (c1 >= c2 && Arrays.binarySearch(paramArrayOfchar, c1) > -1) {
bool = true;
break;
}
}
if (bool)
return b;
return -1;
}
private static String describeChar(char paramChar) {
if (paramChar < ' ' || paramChar == '') {
if (paramChar == '\n')
return "LF";
if (paramChar == '\r')
return "CR";
return "control char (code=" + paramChar + ")";
}
if (paramChar == '\\')
return "'\\'";
return "'" + paramChar + "'";
}
private static String checkUserInfo(String paramString) {
int i = scan(paramString, -9223231260711714817L, -9223372035915251711L);
if (i >= 0)
return "Illegal character found in user-info: " + describeChar(paramString.charAt(i));
return null;
}
private static String checkHost(String paramString) {
if (paramString.startsWith("[") && paramString.endsWith("]")) {
paramString = paramString.substring(1, paramString.length() - 1);
if (isIPv6LiteralAddress(paramString)) {
int j = paramString.indexOf('%');
if (j >= 0) {
j = scan(paramString = paramString.substring(j), 4294967295L, -9223372036183687168L);
if (j >= 0)
return "Illegal character found in IPv6 scoped address: " + describeChar(paramString.charAt(j));
}
return null;
}
return "Unrecognized IPv6 address format";
}
int i = scan(paramString, -8935000884560003073L, -9223372035915251711L);
if (i >= 0)
return "Illegal character found in host: " + describeChar(paramString.charAt(i));
return null;
}
private static String checkAuth(String paramString) {
int i = scan(paramString, -9223231260711714817L, -9223372036586340352L);
if (i >= 0)
return "Illegal character found in authority: " + describeChar(paramString.charAt(i));
return null;
}
public static String checkAuthority(URL paramURL) {
if (paramURL == null)
return null;
String str1;
String str2;
if ((str1 = checkUserInfo(str2 = paramURL.getUserInfo())) != null)
return str1;
String str3;
if ((str1 = checkHost(str3 = paramURL.getHost())) != null)
return str1;
if (str3 == null && str2 == null)
return checkAuth(paramURL.getAuthority());
return null;
}
public static String checkExternalForm(URL paramURL) {
if (paramURL == null)
return null;
String str;
int i = scan(str = paramURL.getUserInfo(), 140741783322623L, Long.MIN_VALUE);
if (i >= 0)
return "Illegal character found in authority: " + describeChar(str.charAt(i));
if ((str = checkHostString(paramURL.getHost())) != null)
return str;
return null;
}
public static String checkHostString(String paramString) {
if (paramString == null)
return null;
return null;
}
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_231"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>PackageCompiler</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

Binary file not shown.

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/bin" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

Binary file not shown.

12
epkcompiler/readme.txt Normal file
View File

@ -0,0 +1,12 @@
TO QUICKLY MAKE RESOURCE PACK:
1. make your changes to the files in '/lwjgl-rundir/resources'
2. double click 'run.bat' on windows, or run './run_unix.sh' in terminal on mac
3. copy 'assets.epk from '/javascript' to your web directory
To manually use the CompilePackage.jar on a custom directory, run the jar file like this:
java -jar CompilePackage.jar <source directory> <output file>
To recompile the assets.epk file found in /javascript, run:
java -jar CompilePackage.jar "../lwjgl-rundir/resources" "../javascript/assets.epk"

2
epkcompiler/run.bat Normal file
View File

@ -0,0 +1,2 @@
@echo off
java -jar CompilePackage.jar "../lwjgl-rundir/resources" "../javascript/assets.epk"

2
epkcompiler/run_unix.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/sh
java -jar CompilePackage.jar "../lwjgl-rundir/resources" "../javascript/assets.epk"

View File

@ -18,6 +18,10 @@ public class CompilePackage {
private static ArrayList<File> files = new ArrayList();
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
if(args.length != 2) {
System.out.print("Usage: java -jar CompilePackage.jar <input directory> <output file>");
return;
}
File root = new File(args[0]);
listDirectory(root);
ByteArrayOutputStream osb = new ByteArrayOutputStream();
@ -47,7 +51,7 @@ public class CompilePackage {
os.writeUTF(" end");
os.flush();
os.close();
FileOutputStream out = new FileOutputStream(new File("out.epk"));
FileOutputStream out = new FileOutputStream(new File(args[1]));
out.write(osb.toByteArray());
out.close();
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>eagler</title>
<title>ayuncraft</title>
<script type="text/javascript" src="jsbn/jsbn.js"></script>
<script type="text/javascript" src="jsbn/jsbn2.js"></script>
@ -12,48 +13,30 @@
<script type="text/javascript" src="asn1-parser.js"></script>
<script type="text/javascript" src="classes.js"></script>
<!--script src="https://unpkg.com/@peculiar/x509"></script-->
<script type="text/javascript" src="music.js"></script>
<script type="text/javascript" src="classes.js?t=updateme0"></script>
<script type="text/javascript">
window.addEventListener("load", function(){ window.minecraftOpts = [
//window.eag_self_proxy=true;//set to true to set the default proxy to the current url
//window.eag_proxy_list="";//set to a string of comma-separated proxy ip:port combinations for a custom proxy list
var name="PixelCraft",motd="A public 1.5.2 server",ip="pixelcraft.me";
window.addEventListener("load", function(){
document.requestPointerLock=document.requestPointerLock||function(){};
document.exitPointerLock=document.exitPointerLock||function(){};
window.minecraftOpts = [
"game_frame","assets.epk",
"CgAACQAHc2VydmVycwoAAAACCAACaXAAJHdzczovL2cuZWFncy51cy9lYWdsZXJjcmFmdC9jcmVhdGl2ZQgABG5hbWUAFGVhZ2xlcmNyYWZ0IGNyZWF0aXZlAQALaGlkZUFkZHJlc3MACAAKZm9yY2VkTU9URAAhdGhpcyBpcyBtZWFudCB0byBiZSBhIGRlbW8gc2VydmVyAAgAAmlwACR3c3M6Ly9nLmVhZ3MudXMvZWFnbGVyY3JhZnQvc3Vydml2YWwIAARuYW1lABRlYWdsZXJjcmFmdCBzdXJ2aXZhbAEAC2hpZGVBZGRyZXNzAAgACmZvcmNlZE1PVEQAI3NlZSBnaXRodWIgZm9yIHByaXZhdGUgc2VydmVyIGd1aWRlAAA="
]; main(); });
//modified from https://gist.github.com/GlauberF/d8278ce3aa592389e6e3d4e758e6a0c2
function simulateKey (key, type) {
var keyCode = key.charCodeAt(0);
var evtName = (typeof(type) === "string") ? "key" + type : "keydown";
var event = document.createEvent("HTMLEvents");
event.initEvent(evtName, true, false);
event.keyCode = event.which = keyCode;
event.key = key;
event.shiftKey = false;
event.ctrlKey = false;
event.metaKey = false;
document.dispatchEvent(event);
}
if(window.navigator.clipboard&&window.isSecureContext){
window.addEventListener("keydown",function(e){
if((e.ctrlKey||e.metaKey)&&e.keyCode==86&&!e.altKey){
window.navigator.clipboard.readText().then(clipdata=>{
if(clipdata==null||clipdata=="")return;
simulateKey("\u0011","up");
simulateKey("\u0011","press");
simulateKey("\b","down");
simulateKey("\b","up");
simulateKey("\b","press");
var clipchars=clipdata.split("");
for(var clipchar of clipchars){
simulateKey(clipchar,"down");
simulateKey(clipchar,"up");
simulateKey(clipchar,"press");
}
});
}
});
btoa(atob("CgAACQAHc2VydmVycwoAAAABCAAKZm9yY2VkTU9URABtb3RkaGVyZQEAC2hpZGVBZGRyZXNzAQgAAmlwAGlwaGVyZQgABG5hbWUAbmFtZWhlcmUAAA==").replace("motdhere",String.fromCharCode(motd.length)+motd).replace("namehere",String.fromCharCode(name.length)+name).replace("iphere",String.fromCharCode(ip.length)+ip))
];
(function(){
var q = window.location.search;
if(typeof q === 'string' && q.startsWith("?")) {
q = new URLSearchParams(q);
var s = q.get("server");
if(s) window.minecraftOpts.push(s);
}
})();
main();
});
</script>
</head>
<body style="margin:0px;width:100vw;height:100vh;" id="game_frame">

118
javascript/music.js Normal file
View File

@ -0,0 +1,118 @@
var aud=new Audio();
var songs=["PkIeYKbzyZY","lv5A5EDvi-g","EyicJOlYOm4","1weATSoaRbA","qSdiecyj6-M","Ugb7GUtiyZ0","1ZFMy48q63w","10RNhMuWR2g","QkVvPD7Xk5U","RUEWIG8zoa0","V6N_rL4fh6I","n02zTn2d3rY","iBZS6ad3Tlk","Mnb2RhXL-nM","lidx_2d4YOA","ETQJZHYlc3g","kRpRoTaNni0","ACy5tHoNUoA","yLFX_7SH2tY","io-vPXE9JXY","oP6wOte3wZU","6LwLyIv3yvA","MrD05HVGVIQ","HBYS5mBHie4","5HxGK3DTUBQ","_9qUu8IeabE","r76yldhXSrw","OqJi_n3AcV4","WFFF-jMyFaQ","D8CwzhM7O6I","FD56t_0B9ig","5OcsWd949w4","jrnNzNT11aU","VLbMXG8lvjI","4aNDoqt9kEQ","_ZMfQ0Aj7h8","ZCJo8CDyqlQ","A1-fM0s1Yt0","zsLT3JqfTn0","zsGM_sGEako","YZlclPLX1Hw","uT1evbCloAw","HYOth1zARhg","loeGmoYr3s4","0qhoqXTUQlY","FtdPlfZNqVY","uIk_jGypR24","mdAb2xALVm0","5hpBvX0sUuo","RiVZCDq--m4","2k5dqgNT37g","j4Jyev7iTlE","9Ty-qFZZPZk","6EDS01Ipaow","720HcvEvEC8","YbdcrJZBtu8","nZ15jw3NOO8","Ub7y69hg4do","hFal0LKZwnM","g-QdgLe_D5M","CAmHrCvZ8tA","Mr-wV17WFZU","EdFyQOngYJs","3RyqONKuRzk","jBPqr_IsWvY","LcyCREQL7w8","dAalyaoVGfE","RM9O1HO4FLE","tUx4SfdoyUI","qFjaDnnPbA4","NrlhbIzjO04","eDBAdAzCqr4","UqVW7-q7fTA","3I-WJ6UgmOA","m8wcDiahBjg","NmzrLZajTLU","EPT3dIWBbDA","tf4dBTlz25g","FuMtDXkuxVw","PkmKM_OXNZM","KbC46oJmLh4","mRJSIYmHuNI","GmLsIivtcIM","rDBbaGCCIhk","Ig5v4jhLLWI","XZcG2esvW7I","_qpgIOzaI0E","TTJBevUIp0s","V4oiuY02dTo","agIayif-oi0","plm3DVsX7Jg","HA0Mk5BXX44","2RLq_paK3-g","h2EgfSvOuPc","HbtwR1REaFk","-tUJJXWXdXk","h-b8Xs7sNI0","xt2DGLoEmW0","eyp-YuzhTN4","xrawoRF4lN0","6xVHpgJbuc8","qsy-14oAXGc","fYSUV33ZPfw","qnSHJlRJ2cM","Ytt1_ErIV34","05TnpE0x4wI","-jcOtAuGZC4","XbuqB3uB6DI","x-42Zkcw4Cs","kXjA7eRZchc","_zceCigOTwo","Qg83cniiYEY","F7gwcgmoREg","aZFe4K1HmPE","e1Ve4Xa9ftQ","p-dVxnR-vLw","PD1a3mfmY8M","-cJFVNZC4h8","Jfs7Lo8CC0Q","zz3F5j8qWNw","CQLvggJFxuM","wf93JAZR3gU","XLQbs59Pn7E","phrpiLpaiLs","Md2xOKFTvSU","_Ci0Kgdpgsw","iBjZshhpipg","j15tAxxc38Y","LwKbsK6E-DI","9J8cD8-LHy4","7ZQlWCsHG7k","UBIsi3xWa64","GWYkh1IX4PE","YYjDFXJ6Wdo","5YDiUcc3emA","s0G4qOrDOgM","9zibDnOOj3w","rQMd3b1BF50","xeM40-FkRLI","wVOFnTrSOOA","CbziO8vuBR8","msUarvc4Sx8","GB9kBLre96M","UMwmB0ZK3yE","SLFMiEAjSoA","K5F-RLzLH6Q","ziAK1OLeeEE","--I54YPKsLU","33zGN7vENog","pTv51QwN57E","zD8TxUBkjGA","A09BhpgfGKQ","cvBQq1yJH-A","YZrIQardsz8","CUHYQ-FN3P8","GLGjqtgCKY8","bLagC2wX3Ak","fW128GHFJIE","e15qP676Zhg","B5L0AMO2HA8","oFFFzMkGNrk","1RQQLwnaw80","byUipqLQ_Hc","WtF6Z13HD_w","pkkIqT9LpDY","gMGEyl5TRa4","oxoqm05c7yA","yTP8tK2OzFQ"];
var insturl="https://invidious.zapashcanon.fr";
var loading=false;
var usealt=0;
function shuffle(array) {
for (let i = 0; i < array.length; i++) {
let j = Math.floor(Math.random() * (array.length-i)) + i;
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function fixfard(url){
if(!url)return insturl;
return url.endsWith("/")?url.slice(0,url.length-1):url;
}
var updinsturl=async ()=>{
try{
var json=await (await fetch("https://api.invidious.io/instances.json?sort_by=health")).json();
var out=shuffle(json).map(entry => {
const healthKnown = !!entry[1].monitor
return {
name: entry[0],
details: entry[1],
health: +(healthKnown ? entry[1].monitor.dailyRatios[0].ratio : 95),
healthKnown
}
}).filter(entry => {
return entry.details.type === "https" && entry.health > 0
}).sort((a, b) => {
return b.health - a.health
});
insturl=fixfard(out.find(e=>e.details.cors).details.uri);
}catch(e){aud.onerror();}
};
var updint=setInterval(updinsturl,3600000);
updinsturl();
aud.onended=function(e){
loading=true;
window.startmusic();
};
aud.oncanplay=function(e){
aud.play();
};
aud.onplay=function(e){
aud.playing=true;
loading=false;
};
aud.onerror=function(e){
if(usealt==2){
aud=null;
return;
}
if(usealt==0){
usealt=1;
}else if(usealt==1){
loading=true;
usealt=2;
}
window.stopmusic();
//todo: make attempt 2 more times with diff urls and if those fail then stop trying
clearInterval(updint);
};
window.startmusic=function(v){
if(v!=null&&v==0)return;
loading=true;
var url="";
if(usealt==0){
songs=shuffle(songs);
url=insturl+"/latest_version?id="+songs[0]+"&itag=251";
}else if(usealt==1){
url="https://nightride.fm/stream/chillsynth.m4a";
}else if(usealt==2){
return;
}
if(v!=null)aud.volume=v;
aud.src=url;
aud.currentTime=0;
};
window.stopmusic=function(){
if(usealt==2)return;
aud.pause();
loading=false;
};
window.volmusic=function(v){
if(usealt==2)return;
if(v==0){
window.startmusic();
}else{
if(aud.playing){
aud.volume=v;
}else{
window.startmusic(v);
}
}
};
window.playingmusic=function(){
return usealt==2||aud.playing||loading;
};
navigator.mediaSession.setActionHandler('play', function() {});
navigator.mediaSession.setActionHandler('pause', function() {});
navigator.mediaSession.setActionHandler('seekbackward', function() {});
navigator.mediaSession.setActionHandler('seekforward', function() {});
navigator.mediaSession.setActionHandler('previoustrack', function() {});
navigator.mediaSession.setActionHandler('nexttrack', function() {});

BIN
javascript/testvideo.mp4 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

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