539 Commits

Author SHA1 Message Date
md_5
edc5b4dc91 Close #656 - fix find filter. 2013-10-11 10:24:55 +11:00
md_5
220a95aece We cannot throttle like this if we want 1.7 compat, lets disable it until we work on a more compatible one. 2013-10-10 07:25:20 +11:00
md_5
4685099808 Close #564 adding a blank arg is a silly idea 2013-10-09 22:37:27 +11:00
md-5
6c14f40108 Reduce the time we wait for legacy pings. 2013-10-08 09:06:28 +11:00
md_5
b041d84063 Null check plugin input for servers 2013-10-07 16:55:29 +11:00
md_5
a9d3d9461f Mojang nerfed tab lists :( 2013-10-06 08:42:52 +11:00
md_5
3fc7064997 Add missing setters for handshake. 2013-10-05 09:50:20 +10:00
md_5
80001aa1f0 UDP + Java + IPV6 != Friends 2013-09-30 17:58:02 +10:00
marvin
a0d94282f6 Add PlayerHandshakeEvent which allows changing of versions and online mode status amongst other things. 2013-09-30 09:22:49 +10:00
md_5
33e11f4c44 Allow for iterables to be CSV-ified 2013-09-29 18:49:20 +10:00
md_5
b541e7aa76 Custom glist formatting 2013-09-29 18:45:11 +10:00
zaiyers
dd06937a3b changes to tab completion
* PacketCBTabComplete: options for completion should be seperated by
NUL
 * PluginManager: append an empty argument to arguments if command ends
with a whitespace (this will match all suggestions)
 * PlayerCommand: suggest only matching players instead of all players
2013-09-29 09:37:39 +10:00
md_5
891dc87b16 Allow unrecognised command line args 2013-09-28 21:00:38 +10:00
md_5
8e77cb35ff Use JDK map for throttle 2013-09-28 18:32:39 +10:00
md_5
59b32a8621 Remove access from PendingConnection interface 2013-09-28 17:37:30 +10:00
md_5
02324206e3 Clean up packets a tad 2013-09-28 17:03:33 +10:00
md_5
73ce828e6e [#637] - Fix resource bundle resolution 2013-09-26 09:24:30 +10:00
md_5
79d04bec2e [#582] Widen synchronized block for packet queue. 2013-09-26 09:20:52 +10:00
md_5
cbcd874d47 Close #626 - command line argument for version. Also refactors into a bootstrap which warns users when not using Java 7! 2013-09-25 17:21:03 +10:00
md_5
09f123ce9a guery -> query 2013-09-24 17:50:44 +10:00
md_5
0a5f8556fe Add config saving 2013-09-24 12:14:47 +10:00
md_5
103a509f26 Fix access of yaml config 2013-09-24 12:11:04 +10:00
md_5
32a5271dc3 Implement basic udp query to close #185 2013-09-24 10:09:55 +10:00
md_5
14389eb370 Use correct main class 2013-09-23 10:30:41 +10:00
md_5
a8b6a6b4aa Finish basic Yaml configuration API, complete with unit tests. Needs a lot of work with regards to how sections are handled, open to massive improvements from anyone that has more know-how. 2013-09-23 10:28:30 +10:00
md_5
8133304cce Use = for properties 2013-09-22 17:37:06 +10:00
md_5
3e8c21a485 Add specific exception for bad packets. 2013-09-21 16:57:17 +10:00
Matty Southall
f12dcc72d9 Fix compile error when compiling on OS X 2013-09-21 10:55:39 +10:00
md_5
a7a32509c7 find * -type f -print0 | xargs -0 sed -i 's/1.6.2/1.6.4/g' 2013-09-20 19:51:57 +10:00
md_5
703a393888 Procol -> Protocol. Fix typo, thanks @libraryaddict 2013-09-20 15:41:30 +10:00
md_5
3c961cd5d9 1.6.4 - MOJANG 2013-09-20 08:23:06 +10:00
md_5
12ee68a315 Update to 1.6.3 2013-09-19 17:41:01 +10:00
md_5
db5510cc4e Only interrupt tab completion if we have things to complete! 2013-09-17 10:28:51 +10:00
md_5
5ed5c71aea Move AbstractReconnectManager to the API and rename to AbstractReconnectHandler. 2013-09-16 08:21:53 +10:00
md_5
38a8469ab4 Cap command completion to one argument 2013-09-15 15:14:47 +10:00
md_5
9538dcf4d4 Properly tab complete 2013-09-15 14:04:51 +10:00
md_5
33f654ce6f *unused imports 2013-09-15 07:44:13 +10:00
md_5
c108e4e1ce Server command completion 2013-09-15 07:43:50 +10:00
md_5
e998faeec1 Add tab completion for find command. Also change api a bit. 2013-09-15 07:37:20 +10:00
md_5
d67acd7bc9 Add functionality to replicate #336 2013-09-15 07:29:22 +10:00
md_5
702f434db1 Add API to support #468 - force setting of reconnect server 2013-09-15 07:12:58 +10:00
md_5
47b5631562 Not part of the contract 2013-09-15 06:54:58 +10:00
Robin Lambertz
80e23d6646 Allow removal of listeners / commands by plugin 2013-09-15 06:52:46 +10:00
md_5
1dca12cffb Use boolean not binary and 2013-09-15 06:48:06 +10:00
md_5
29c897c9cf Add Tab Completion loosely based on @TheUnnamedDude's work. 2013-09-15 06:46:10 +10:00
md_5
042f47cbb9 Wrapped buffers are not thread safe. 2013-09-10 21:33:44 +10:00
md_5
422e97f495 Don't let pingbuf be released 2013-09-10 21:26:59 +10:00
md_5
08789d8f9f Write down a supported message type (ByteBuf) when using the ping handler. 2013-09-10 20:56:40 +10:00
md_5
96444ae304 Fix a message consisting only of a space causing the player to be kicked. 2013-09-10 16:23:05 +10:00
md_5
af58db8a67 Simpler, unit tested throttle to close #613 2013-09-10 12:02:29 +10:00
md_5
49cffebd9b Dynamic build dates - see #526 2013-09-10 11:37:48 +10:00
md_5
ffdb917f2c Use translation - closes #578 2013-09-09 14:58:56 +10:00
md_5
9c9657e36d Update links 2013-09-09 14:41:58 +10:00
md_5
1342baed47 Use fluid bytes instead of enum + format. 2013-09-09 14:36:48 +10:00
Dabo Ross
e3a7490bcd Fix formatting error - not sure how that happened 2013-09-09 14:27:23 +10:00
Dabo Ross
3e8693793c Add multiple listeners to EventPriorityTest 2013-09-09 14:27:23 +10:00
Dabo Ross
bb47aba682 Add UnregisteringListenerTest 2013-09-09 14:27:23 +10:00
Dabo Ross
d0e5ee4e09 Don't try to bake handlers when there are no more handlers. Remove them instead! 2013-09-09 14:27:23 +10:00
Dabo Ross
07e330b005 Create test for event priorities 2013-09-09 14:27:23 +10:00
Dabo Ross
024288e587 Added a Map<Class<?>, EventHandlerMethod[]> and implemented using it. I believe this should have a positive performance effect. 2013-09-09 14:27:23 +10:00
Dabo Ross
53a6bb1dee Added EventHandlerMethod wrapper for Listener and Method 2013-09-09 14:27:23 +10:00
Dabo Ross
0f06b2c4e0 Implement usage of EventPriority in EventBus 2013-09-09 14:27:23 +10:00
Dabo Ross
d3c1acce83 Add EventPriority method to EventHandler 2013-09-09 14:27:23 +10:00
Dabo Ross
eaea090d37 Add EventPriority 2013-09-09 14:27:22 +10:00
md_5
7384e797fc Bump date 2013-09-08 11:49:27 +10:00
md_5
d4d93ddbb9 Bump to Netty 4.0.9 2013-09-08 08:45:37 +10:00
md_5
ccdf2a89d8 Close #518 - use csv method for perms command 2013-09-07 12:22:43 +10:00
md_5
89edb00c05 Properly cancel tasks! 2013-09-05 19:52:41 +10:00
md_5
00a0277a13 Just call our own logger, screw jdk logger parenting 2013-09-03 11:36:00 +10:00
md_5
68f11e46f7 Depend updates. 2013-08-27 12:30:00 +10:00
Ammar Askar
c352e854ee Catch exceptions when disabling plugins 2013-08-25 10:27:25 +10:00
md_5
d8c92cd311 Add ConnectOther channel for moving other players from a plugin 2013-08-25 10:23:17 +10:00
md_5
99f361ca77 Instead of storing packets about to be passed on as a byte array, store them as a Netty buffer, which is likely to be pooled, direct and manually memory managed leading to increased performance and less GC strain. In order to ensure no resources are leaked, we free them at the end of each handle cycle if they have not been passed to a channel for writing. In initial profiles this now causes encryption to be one of the most intensive parts of BungeeCord, however in depth profiling snapshots may provide further routes for optimization. 2013-08-20 19:29:43 +10:00
md_5
738ed99d54 Code format. 2013-08-20 19:28:09 +10:00
md_5
ad0da59267 Really need to automatically do this. Add a few weeks to expire time 2013-08-20 18:50:52 +10:00
md_5
1dcc8d6a4b Close #572 - kick event message 2013-08-20 11:18:51 +10:00
md_5
0840a77153 Dem dates :( 2013-08-15 07:44:33 +10:00
md_5
61a93a54a9 ammar2 missed a spot 2013-08-14 22:14:32 +10:00
md_5
da0281508e Oi! Get back inside of that if statement. NOW! 2013-08-13 18:53:16 +10:00
Ammar Askar
51e92de2dd Only save to reconnectHandler if we have a listener that isn't forcing to the default server 2013-08-13 18:50:19 +10:00
md_5
f948acd634 Don't loop registering of listeners 2013-08-12 20:31:51 +10:00
md_5
773ce089c1 Fix http client 2013-08-10 07:30:41 +10:00
md_5
a07eba7965 Netty 4.0.7.Final - fixes memory leak 2013-08-09 19:50:48 +10:00
md_5
b68b6a76c7 Recover from broken yaml 2013-08-09 17:23:16 +10:00
md_5
332033bb02 Disable resource leak detector for ~15% cpu reduction 2013-08-09 16:58:14 +10:00
md_5
172b8bc75b Update to Netty 4.0.6-Final 2013-08-09 16:56:09 +10:00
md_5
db5a147491 Revert changes to SeverConnectedEvent 2013-08-06 11:14:54 +10:00
md_5
f083e27649 More translations! 2013-08-05 17:29:47 +10:00
md_5
b64a7be19b Bump date to the 9th 2013-08-04 21:34:56 +10:00
md_5
c4d60a8fa9 Hold player for ServerSwitchEvent - see #539 2013-08-04 21:28:10 +10:00
md_5
f07cfe0cf7 Make the ServerConnectedEvent async to allow stalling it. Closes #538 by @BjoernAkAManf. 2013-08-04 20:58:17 +10:00
md_5
4463b0c1b2 Use Java 7 API to make classloader thread safe. Closes #516 2013-08-04 20:23:31 +10:00
mrapple
ee8f33c196 Add State to ServerKickEvent 2013-08-04 18:57:13 +10:00
md_5
14ac2dd308 Allow setting whether to bind to the local address. 2013-08-04 18:56:48 +10:00
md_5
fb94612315 Fix throttle to 1) Work, 2) Not throttle outbound connections 2013-08-02 19:31:46 +10:00
md_5
4c96880580 Lets just silence java.util.NoSuchElementException: decrypt - PEOPLE DON'T UNDERSTAND ITS NOT AN ERROR. 2013-08-02 19:11:16 +10:00
md_5
4c4cdd51a1 Downgrade to Netty CR9 2013-08-02 07:32:42 +10:00
md_5
1f38152530 [URGENT] Add connection throttle. 2013-08-01 13:37:32 +10:00
md_5
911f08d52c Disable packet grouping in an attempt to increase reliability. 2013-07-31 20:18:54 +10:00
md_5
8f961c9d4e Put colours in default motd to try and force quoting in the dumped yaml 2013-07-27 12:12:12 +10:00
md_5
8a5d8a57f7 Don't infinite loop on tasks with no period 2013-07-24 17:38:46 +10:00
md_5
c54553d0f9 How kind of @lazertester to test the new scheduler! 2013-07-24 17:32:08 +10:00
md_5
600a1b4ff5 Update expire date 2013-07-24 17:02:37 +10:00
md_5
09e592295f Update to Netty 4.0.4-Final 2013-07-24 15:58:02 +10:00
md_5
fa0ee02beb Update Netty - if you guys could verify the leak has been fixed, that would be great, #523 2013-07-22 19:40:14 +10:00
md_5
b23b54d9e4 Bump Netty minor version 2013-07-19 19:31:46 +10:00
md_5
b3e8feb4cb Update POMs to 1.6.2 2013-07-18 20:13:07 +10:00
md_5
d0d1562155 Hi, I'm Mojang and I make hundreds of millions of dollars a year. I still like to think I am an Indy company, so I randomly remove existing game features and don't provide replacements.
Removes Texture Pack setting
2013-07-18 20:10:45 +10:00
md_5
f510ab2a0b Update to netty 4 final, exciting! 2013-07-17 16:47:49 +10:00
md_5
fb1cab499d Always use eventloop since we cannot be sure about plugins, thanks @MonsieurApple for the report. 2013-07-12 09:29:53 +10:00
md_5
58ca63e2b1 Use a defensive copy for shorter lock time 2013-07-11 11:14:12 +10:00
md_5
499337c98e Optimized yaml reconnect locations! Ding dong sqlite is dead.. 2013-07-11 11:12:43 +10:00
md_5
526137be7b Remove our packet queuing as it may be contributing to high CPU usage and/or memory leaks. 2013-07-11 10:14:51 +10:00
md_5
47839cb11c writeStringUTF8WithoutLengthHeaderBecause @Dinnerbone StuffedUpTheMCBrandPacket 2013-07-10 23:42:50 +10:00
md_5
55a6cc56ef Recycle messagelist when channel goes inactive (reverted from commit daa58ffe58) 2013-07-10 23:41:37 +10:00
md_5
8c2bea5be2 Fix possible race condition with regards to abandoning servers 2013-07-10 13:02:25 +10:00
md_5
daa58ffe58 Recycle messagelist when channel goes inactive 2013-07-10 09:18:58 +10:00
md_5
0189ad9c17 Add disabled commands 2013-07-09 14:55:27 +10:00
md_5
9adcb05d45 Fix 1.6.2 support 2013-07-08 22:37:59 +10:00
md_5
10e81041b2 Update to 1.6.2 2013-07-08 21:29:09 +10:00
md_5
0c56945ffd Implement upcoming Minecraft API to get the server brand - thanks @Grum for the hint. 2013-07-08 21:29:09 +10:00
md_5
0a36cbd5bc Fix compilation -> add silly catch block 2013-07-08 08:41:11 +10:00
md_5
61b4777177 Use more threads for IO to eliminate resource starvation possibly leading to high CPU usage. This brings the count back in line with what we had pre 1.6 / late 1.5 2013-07-08 08:35:12 +10:00
md_5
7d1904584b Back to Java cipher, they are both the same speed 2013-07-08 08:33:25 +10:00
md_5
475571986c Make sure packets are written before closing 2013-07-07 13:08:25 +10:00
md_5
55c2bcd634 Undo recent SQLite changes - might need to seek *another* DB engine - whats H2 like for concurrency? 2013-07-06 08:30:38 +10:00
md_5
db4abfe486 Expand streams a little bit 2013-07-05 19:17:25 +10:00
md_5
9424bdedca Implement basic MC stream 2013-07-05 19:06:46 +10:00
md_5
52b3c6b77c Dont need to force use of eventloop anymore 2013-07-05 09:32:20 +10:00
md_5
be29799f5a [Beta] Implement own HTTP client for online mode checks, instead of asynchttpclient 2013-07-05 09:29:28 +10:00
md_5
c0d581d41f Rework SQLite again to use thread local connections - closes #492 2013-07-05 08:23:29 +10:00
md_5
6b50c7c599 Move HTTP client stuffs into bungee-proxy 2013-07-04 21:59:38 +10:00
hyperring
b4101874cc Fixed forced_hosts MOTD
Noticed a tiny bug in creating a ServerPing response. The response was still using the old listener.getMotd() when it should be using the new motd variable (to take advantage of the new forced_hosts MOTD methods).
2013-07-04 21:39:33 +10:00
md_5
66de4c95ef Implement BouncyCastle as the cipher engine. 2013-07-04 21:13:10 +10:00
md_5
927a295add Add SSL support 2013-07-04 11:48:09 +10:00
md_5
2cbea83c02 HTTP is working, still need to do HTTPS though 2013-07-04 11:32:36 +10:00
md_5
87884ad084 Downgrade maven compiler - new one is still derp 2013-07-04 11:12:25 +10:00
md_5
94cc2412e7 Flush pending messages when manipulating pipeline - fixes forge support 2013-07-04 11:11:57 +10:00
md_5
924b90e325 Add statr of work on HTTP client. 2013-07-04 10:52:54 +10:00
md_5
3f476a30b4 Get depend name right :p 2013-07-04 10:31:00 +10:00
md_5
f579b31bca Add framework for HTTP api 2013-07-04 10:29:37 +10:00
md_5
cac35116c3 Import cleanup 2013-07-04 10:03:41 +10:00
md_5
bd42fb23a0 Update to Netty CR9 2013-07-04 09:58:29 +10:00
md_5
ffbebaff69 Remove old @Subscribe event handling 2013-07-04 09:43:32 +10:00
md_5
b741722e5d Close #489 - disable resource leak detector for performance reasons 2013-07-04 09:22:27 +10:00
md_5
07288c722c Update maven compiler version 2013-07-02 21:04:10 +10:00
md_5
85e82a2e34 Update POMs to 1.6.1 2013-07-02 20:59:04 +10:00
md_5
3aef35ccbb Warn about non existant fallback 2013-07-02 19:43:48 +10:00
md_5
d1760dad93 Custom outdated messages, tick! 2013-07-02 19:26:21 +10:00
md_5
d3d11cf283 Update to netty CR8 2013-07-02 15:31:20 +10:00
md_5
d3bada58d4 Close #469 - chat event setMessage 2013-07-02 10:45:37 +10:00
md-5
23517a9a97 Merge pull request #476 from vemacs/patch-1
Supposedly fix walk speeds
2013-07-01 14:10:43 -07:00
vemacs
fdc87e88f5 Supposedly fix walk speeds 2013-07-01 15:34:17 -04:00
md_5
12941ffe62 Close #471 - sync sqlite operations to guard against deadlocks 2013-07-01 21:25:39 +10:00
md_5
06e732d8c7 Close #474 - 1.5 ping to 1.6 bungee 2013-07-01 21:20:18 +10:00
md_5
5c4ea3c7a0 Solve long standing issue of creating too many TCP packets. This fix works very effectively. 2013-07-01 17:38:50 +10:00
md_5
632fa8bd94 Partially support forced_hosts MOTD without SRV records - gonna think how best to put this in the config, for now its server: motd:, might remove listener motd later on 2013-07-01 14:05:57 +10:00
md_5
8732904bfd Add stream helper to PacketFA 2013-07-01 13:45:36 +10:00
md_5
788b96dc0a knohacks - thanks @ammaraskar 2013-07-01 13:37:03 +10:00
md_5
1296783d9b Update to Minecraft 1.6.1 2013-07-01 13:19:18 +10:00
md_5
a9603a6372 Bump Javassist version 2013-06-29 15:04:13 +10:00
md_5
b15ed87ad5 Netty CR7 m8 2013-06-29 15:02:38 +10:00
md_5
3e816f628b Update to Netty CR6 2013-06-27 16:22:06 +10:00
md_5
7bfc4bf819 Remove outbound boss for now 2013-06-27 10:16:23 +10:00
David Marby
f8d15f4c88 Fix bad packet ID with bows 2013-06-27 10:14:34 +10:00
md_5
a73b06eee3 Close #462 - shutdown gracefully 2013-06-26 20:48:13 +10:00
md_5
2069679140 Silence JLine errors 2013-06-25 11:29:47 +10:00
md_5
9a173968f1 Update to Netty CR3 but include workaround for (bug?) present in it. Feedback is welcome, #448 is related. 2013-06-23 10:40:27 +10:00
AgentK
13f1fa7443 Reject clients on other protocol versions. 2013-06-21 16:36:37 +10:00
md_5
0f7da279ef Close #450 - errors from our backport 2013-06-19 13:30:43 +10:00
md_5
a6ba661a32 Back to CR1 we go. Deal with the issues. 2013-06-19 07:36:40 +10:00
md_5
22133bc8d2 Close #445 - error when clients use forge 2013-06-18 21:10:16 +10:00
md_5
f9c9517958 Why can no one ever provide helpful information to attempt to diagnose a bug, it is ridiculous that you can expect my help when you don't even provide a version number.
I am seriously just tired of this and need a break.
2013-06-18 20:52:18 +10:00
md_5
7a79bd0816 Update to Netty CR5, boasts very nice performance and should hopefully fix many of the issues we have seen. 2013-06-18 17:14:34 +10:00
md_5
6a60376033 If #438 does not go away, then BungeeCord users are derps, since this class has no been reverted to the exact same state before the so called issue inducing commit 2013-06-17 19:10:38 +10:00
md_5
4ce0eee232 #438 please just go away. 2013-06-17 17:25:20 +10:00
md_5
72f3a79759 Do what we can about Jline not being installed 2013-06-17 17:05:02 +10:00
md_5
dbb6aebf58 #3 windows fix 2013-06-17 16:29:21 +10:00
md_5
54040ec48d Windows fix #2 2013-06-17 16:17:50 +10:00
md_5
8c4ddf458c Fix #1 for windows. 2013-06-17 16:13:27 +10:00
md_5
07fb6490f8 Close issue #440 - players remaining after logout 2013-06-17 14:19:16 +10:00
Robin Lambertz
d9eb8c66b8 Change order of boolean so the latch is decremented all the time 2013-06-17 14:16:54 +10:00
md_5
7fab3ba372 Try twice to init jline 2013-06-16 21:27:15 +10:00
md_5
92c3ef1989 Fix custom tab API to allow using as soon as constructed 2013-06-16 15:40:31 +10:00
md_5
fbf2d8969e Exception caught should rely on channel activity state, not OUR close flag 2013-06-16 11:30:03 +10:00
md_5
1881507712 Move scoreboard stuff to the sscore package in preparation for refactor 2013-06-16 09:10:25 +10:00
md_5
fd2a72477f Move tab list stuff to the 'tab' package 2013-06-16 09:08:48 +10:00
md_5
d4cbac1bdf Add tab list getter to api 2013-06-16 07:56:38 +10:00
md_5
fa0671ab2a Finish up TabApi impl. 2013-06-16 07:55:15 +10:00
md_5
184154a8b3 Close issue #437 2013-06-16 07:26:29 +10:00
md_5
cbec4e836a Harsher reload warning 2013-06-15 21:12:15 +10:00
md_5
3ce7982778 Clean up pipeline flow. 2013-06-15 21:08:49 +10:00
md_5
b55944e2fb Dont spam the console with too many exceptions 2013-06-14 07:31:58 +10:00
md_5
12cba14657 Tweak our channel promise to be a bit more hellpful on errors 2013-06-13 20:53:35 +10:00
md_5
78e67283cc Roblabla feels listeners should be at the top 2013-06-11 20:23:48 +10:00
md_5
f0f1e71c93 Implement super sexy console to close #315 2013-06-11 18:55:15 +10:00
md_5
3c1a5aabfd Add translation + fix spelling for mojang servers down 2013-06-11 10:29:19 +10:00
md_5
f0d4e8c24a I feel like the time for change is here 2013-06-10 14:55:57 +10:00
md_5
ba8bd7faf0 Try to cut off packet race conditions when moving servers. 2013-06-10 08:54:52 +10:00
md_5
787692070e Set a row limit to stop at, we should shrink this after a while. Meh api is good enough for me 2013-06-08 15:48:26 +10:00
md_5
523e991018 Doesnt allow ALL possible variations of a string, but its good enough for now 2013-06-08 15:34:30 +10:00
md_5
7733fbfb28 Make tab list work! 2013-06-08 14:43:03 +10:00
md_5
44ac36941f Use 1 based index 2013-06-08 14:10:15 +10:00
md_5
0235c4a01e Make sure to init the tab list 2013-06-08 14:08:48 +10:00
md_5
b4220e9229 Refactor all the tab APIs 2013-06-08 14:06:09 +10:00
md_5
9b9addfccd Add interfaces for custom TabAPI, just need to add the hooks now, and of course a pretty example. As always, not tested yet. 2013-06-08 13:51:23 +10:00
md_5
b75a2b5060 [Breaking] Close #423 by making tab list per listener. 2013-06-08 13:13:17 +10:00
md_5
b5aecd5dcc Stab at fixing forge and wecui support when combined. F**** I hate mods. 2013-06-08 12:35:50 +10:00
md_5
4d51d16512 Fix mods like wecui not working after switching servers.
#364
2013-06-08 09:45:45 +10:00
md_5
05a9342854 Ramp up warning in preparation for breaking commit 2013-06-06 20:23:50 +10:00
md_5
483fede234 Work around windows bugs 2013-06-06 18:13:56 +10:00
md_5
ce8f1b44b6 Musical versions 2013-06-05 20:30:34 +10:00
md_5
b1e3f6a75b And people think dependancy loading is easy. Close #381 2013-06-05 18:24:33 +10:00
DerFlash
33d315b719 Tone down PingHandler too 2013-06-04 07:42:13 +10:00
md_5
d11e130d61 Close #365 - prettier error when mc.net is down 2013-06-03 19:54:41 +10:00
md_5
45a93c8cfc Close #417: whois -> find 2013-06-03 19:49:35 +10:00
md_5
fd411edddb Tone down logging for surprisingly large reduction in CPU usage - Closes #401 2013-06-03 19:48:21 +10:00
md_5
ac5e8dbaff Fix the bad packets! Naughty naughty packets! 2013-06-03 19:35:38 +10:00
md_5
340d82812a Reorder checks to prevent malformed packets throwing errors 2013-06-02 22:19:49 +10:00
md_5
eaf99cf4a6 Yo dawg. Lets start populating the seen row 2013-06-02 17:11:44 +10:00
md_5
4baae5a230 Add space to whois 2013-06-02 14:39:51 +10:00
md_5
aa1a871967 Actually use our threadLocal. Do'h 2013-06-02 14:33:47 +10:00
md_5
18f5ed3102 Close #410 - forge crashes 2013-06-02 10:30:44 +10:00
md_5
d1dd7379b1 Use cleaner equals check and actually set member field 2013-06-02 10:23:21 +10:00
md_5
0b0d09427d Proper case sensitivity + dont reverse lookup forced hosts 2013-06-02 09:23:05 +10:00
md_5
dce0f6b408 Missed some getters 2013-06-01 18:01:04 +10:00
md_5
c5307c4451 Dont use getters in team packet and add null check to team name 2013-06-01 18:00:17 +10:00
md_5
4f2b98188e Don't allow stupid users to connect bungee to themselves 2013-06-01 17:55:51 +10:00
md_5
d5eb37c7a6 Add debug to tryFailure 2013-06-01 17:46:11 +10:00
md_5
2a421cdd8d Close #306 use SQLite for reconnect locations 2013-06-01 17:29:14 +10:00
md_5
757f8f0cb9 Fix comparisons of objects in case insensitive hashmap 2013-06-01 16:07:17 +10:00
md_5
388d2620db Fix forge support with new protocol - closes #407 2013-06-01 12:55:02 +10:00
md_5
3ba52cb98b Might need a better way to do this...... oh well, add all the netbeans code style files 2013-06-01 11:12:03 +10:00
md_5
e652214071 Close issue #406 - tab list 2013-06-01 11:10:56 +10:00
md_5
0821404f92 Add netbeans config file 2013-06-01 11:09:46 +10:00
md-5
11b90b91b7 Update ServerConnection.java 2013-05-31 20:45:00 +10:00
md-5
aa3989db19 damn web editor 2013-05-31 19:26:15 +11:00
md-5
76c914db14 Update InitialHandler.java 2013-05-31 18:22:19 +10:00
md_5
639e5f3c1d Add 'unsafe' api for things like packet sending that may be implementation specific or break at any time 2013-05-31 17:02:45 +10:00
md_5
9fd69068ae [TESTING] Merge protocol api into master. This should provide slightly better performance and allow more flexibility for plugin developers. 2013-05-31 16:54:19 +10:00
md_5
9c35cad824 Will do final tests tomorrow, but all seems to work. Yay for efficiency and options for plugin developers! 2013-05-30 19:36:43 +10:00
md_5
d82b29e15a Finish up protocol API - we now compile again. Extensive testing is required, but that is for another day. 2013-05-30 19:11:05 +10:00
md_5
9b0c827c37 Now just to implement the necessary constructors and constants 2013-05-30 18:29:59 +10:00
md_5
125d3f07f7 Fix up failing test 2013-05-30 18:15:10 +10:00
md_5
2f45f0d578 Rework protocol system 2013-05-30 18:09:46 +10:00
md_5
ad4c143ce4 Finish and create passing unit tests for the integrity of all packet classes. 2013-05-30 17:34:56 +10:00
md_5
835e4e332c Start work on more efficient, publically accessable packet API 2013-05-30 16:38:53 +10:00
md_5
0578f94522 Rework shutdown sequence to close #391 2013-05-30 16:23:02 +10:00
md_5
0cd4c9030c Close #396 - broken API spec for "ALL" server 2013-05-29 12:03:41 +10:00
md_5
0d666168f0 Close #398 by printing debug so we can identify the issue if it arises again 2013-05-29 12:02:06 +10:00
md_5
cfb823f077 Close #395 - work around trove quirks 2013-05-29 12:00:57 +10:00
md_5
36a5e89ff9 I told you so 2013-05-27 19:28:50 +10:00
md_5
bb4e8e29a5 Update Netty version and remove our workaround - if this breaks, @mibby keeps the pieces. 2013-05-27 18:22:59 +10:00
md_5
8e34e038d6 Remove chat event firing when we get a message from server to client, as Mojang has decided to completely break this in the next major Minecraft release. 2013-05-26 21:24:32 +10:00
md_5
d1950389cc Just leave field as map... 2013-05-26 12:26:26 +10:00
md_5
9d841bb91a Store config in a case insensitive map 2013-05-26 12:25:46 +10:00
zSwayz
828cebcc4b Sexified
Pls add D:
2013-05-26 09:28:12 +10:00
md_5
12fec2fcdd Add some not null checks to API methods 2013-05-25 17:26:54 +10:00
md_5
8b6b134662 Maybe one day we will want to set this null - it can start null, so it can become null 2013-05-25 17:24:37 +10:00
md_5
538beb33a6 Remove now redundant field from InitialHandler 2013-05-25 17:22:43 +10:00
md_5
97338cbfad Its impossible unless you have a creative server and no mobs and no nothing, but we must allow 0 as an entity ID 2013-05-25 17:18:03 +10:00
md_5
3e28decef2 Remove getServer from the api - long depreceated 2013-05-25 17:09:29 +10:00
md_5
f93b647df3 Move protocol version declaration 2013-05-25 17:03:00 +10:00
md_5
775ffdc998 Optimize online count and broadcast methods 2013-05-25 17:01:39 +10:00
md_5
80c22027de Slightly more optimized getChannels 2013-05-25 16:52:41 +10:00
md_5
122987dd83 No space for lost connection translation 2013-05-25 16:50:39 +10:00
md_5
ac4bab2425 More case insensitive tests and read write lock for connections 2013-05-25 16:50:04 +10:00
md_5
a51ffb1f4c Use our own promise to work around @netty pipeline issues 2013-05-25 11:55:54 +10:00
md_5
77e0dcc7f8 Dont throw exceptions on missing translations 2013-05-25 11:54:17 +10:00
md_5
ddb93fd988 That was an easy test - just had time to write 2013-05-24 14:45:33 +10:00
md_5
7eac22d362 Make perms case insensitive - need to write unit test still 2013-05-24 14:44:40 +10:00
md_5
185dc97ca6 *chatcolor import 2013-05-24 14:41:15 +10:00
md_5
e0d19cf305 Show current server in server command 2013-05-24 14:37:40 +10:00
md_5
0e9002091b Add whois command 2013-05-24 14:35:27 +10:00
md_5
9fdcded97f Close #376 - case insensitive servers and maps 2013-05-24 14:31:31 +10:00
md_5
32fdc83841 Close #383 - swallow exceptions once and for all 2013-05-24 14:16:43 +10:00
md_5
1bf126d4f8 Close #384 - reset locations.yml on error 2013-05-24 14:12:50 +10:00
md_5
56533c6259 Close issue #374 - take a lock when checking channel state / writing 2013-05-23 13:49:58 +10:00
md-5
4cb46c6e5c Merge pull request #372 from roblabla/patch-2
Add global PlayerCount if target is "ALL"
2013-05-22 05:01:48 -07:00
md_5
6decf860c9 Update warning 2013-05-22 21:01:52 +10:00
md_5
29f22f9be9 Just swallow the error because thats what we did before. 2013-05-22 18:27:53 +10:00
md_5
98860ffd02 SLightly more atomic locations.yml saving to guard against ctrl+c'ing users 2013-05-22 17:07:46 +10:00
md_5
2c225a05e7 Add atomic close tracking. Closes #370. 2013-05-22 09:24:55 +10:00
Robin Lambertz
c1dfd0fb7b Add global PlayerCount if target is "ALL"
This allows bukkit servers to get the global bungeecord player count.
2013-05-21 22:14:00 +02:00
md_5
9be44d51a6 Update to netty CR3 2013-05-21 11:30:05 +10:00
md_5
2a2c2717d5 Connect via bound address - closes #337.
Blame JacobiCarter if this breaks
2013-05-19 18:14:59 +10:00
md_5
3f994a1c4c Downgrade to @netty CR1 2013-05-19 18:02:01 +10:00
md_5
9a0da50e6c Fix formatting 2013-05-16 16:49:14 +10:00
md_5
67fdc830c2 Protected access please 2013-05-16 16:47:21 +10:00
md_5
64e8a79551 Close #348 - translation key 2013-05-16 06:40:01 +10:00
md_5
afc387ce0d Set local address to listener address, closes #337 (reverse-merged from commit 57793e93f0) 2013-05-16 06:39:29 +10:00
md_5
8a70af5293 Clean up code style surrounding bootstrap creation 2013-05-15 19:08:14 +10:00
md_5
57793e93f0 Set local address to listener address, closes #337 2013-05-15 19:05:38 +10:00
md_5
a48ef137bd Make connect event implement cancellable, closes #338 2013-05-15 19:04:22 +10:00
md_5
ff32d29e09 Gracefully shutdown event loop, closes #346 2013-05-15 19:02:10 +10:00
md_5
9f3359f8fa Thanks Lex! Closes #319 2013-05-15 18:59:13 +10:00
Jacobi Carter
539fccb873 The client handles the server sending the same score multiple times to overwrite the previous entry. 2013-05-14 18:52:12 +10:00
md_5
b25c81daf3 Update to latest netty, fix event bus bug, comment and rework PacketDecoder to new netty for better performance 2013-05-14 18:32:30 +10:00
md_5
21a354fa75 Add home grown event bus 2013-05-14 11:38:39 +10:00
mickare
aefe3333a9 Add per plugin loggers 2013-05-14 11:19:01 +10:00
md_5
0afefa8f61 Allow nested event dispatch. Yet another thing which I should one day try and PR to Guava 2013-05-13 18:39:45 +10:00
md_5
834ac24b38 Add EventBus test, which fails, now to fix! 2013-05-13 18:36:12 +10:00
md_5
c465eca03b Just escape utf chars 2013-05-12 22:01:42 +10:00
md_5
beb0bf9836 Fu*** offline mode users 2013-05-12 16:09:21 +10:00
md_5
688c42219c Actually translate message 2013-05-12 15:55:51 +10:00
md_5
1ea53f01aa Add a series of new translations 2013-05-12 13:40:43 +10:00
md_5
202dab5c98 Add texture pack API 2013-05-12 09:28:36 +10:00
md_5
49ea7f908f Add server switch event 2013-05-12 09:15:17 +10:00
Harry
9d3bddedb6 Return if command should not be executed to avoid exceptions and unnecessary messages to the player. 2013-05-06 07:22:56 +10:00
md_5
332bdaaec0 Refactor forge support - closes #318 2013-05-05 08:31:44 +10:00
md_5
904a1bfaa3 *register channels. This fixes plugins being broke 2013-05-04 10:20:53 +10:00
md_5
5eb7a6eba7 Fix forge support - closes #312 2013-05-04 09:40:10 +10:00
md_5
8e262cf428 Close issue #311 - exception feedback on server connector 2013-05-04 09:28:28 +10:00
md_5
125df5c22d Add SQLite driver for future use 2013-05-03 21:25:47 +10:00
md_5
7b631092f5 Add experimental Forge support. This may cause issues when using Vanilla clients etc, so caution is advised. Please visit GitHub to report any issues you encounter. Thanks @LexManos for providing the basis for this implementation. 2013-05-03 21:21:55 +10:00
md_5
d3c1339cc9 Make sure we write out custom login packets 2013-05-03 20:36:55 +10:00
md_5
679bf2fca9 Synchronize on pending packet queue, add forge/no forge constructor argument to login packet, and don't send channel registers twice 2013-05-03 20:29:36 +10:00
md_5
7436621481 Refactor encryption to be two step like vanilla. Thanks @LexManos for pointing this out. 2013-05-03 19:35:00 +10:00
md_5
6236cff658 Refactor encrypt util class in preparation for forge support. 2013-05-03 19:10:54 +10:00
md_5
6b504d9160 Use faster collections for the various tab lists. 2013-05-03 18:20:10 +10:00
md_5
d1124ca70b Cleanup imports 2013-05-03 14:39:25 +10:00
md_5
779582d441 Use multimap in scheduler 2013-05-03 14:33:04 +10:00
md_5
b91564f77a Fix eclipse gitignore, I think - don't use eclipse 2013-05-03 14:24:35 +10:00
Zach Bruggeman
30b2e5008b Add ResourceBundle localization 2013-05-03 14:22:12 +10:00
md_5
140830efe0 Close #300 - cleaner disconnects when server is full 2013-05-03 14:16:48 +10:00
md_5
5f8e76c61c Revert "ConcurrentHashMap is junk - lets stick to standard unless issues arise."
This reverts commit 5d1a2c59a7 and closes #304
2013-05-03 14:15:23 +10:00
md_5
b7511abfda Update to 1.5.2, closes #302 2013-05-02 07:32:45 +10:00
md_5
09d04c34cb Increase thread pool timeout to try and reduce churn 2013-04-30 11:32:29 +10:00
md_5
3132d2c7cf Increment intent counter 2013-04-29 18:53:16 +10:00
md_5
3682e8ba3a Catch throwable not exception for enabling plugins 2013-04-28 17:45:25 +10:00
md_5
82d5954f2f Revert "Load plugins in alphabetical-ish order."
This reverts commit 384228b751.
2013-04-28 17:44:23 +10:00
Steve Anton
384228b751 Load plugins in alphabetical-ish order. 2013-04-28 17:35:27 +10:00
md_5
50f8bd2eb0 Finish encapsulating all userconnection fields 2013-04-28 11:36:36 +10:00
md_5
ff32764f9a Encapsulate ping fields 2013-04-28 11:19:19 +10:00
md_5
a1f928b210 Don't expose the channel 2013-04-28 10:45:20 +10:00
md_5
5bf616dc4d Forgot that mutex 2013-04-28 10:41:03 +10:00
md_5
0d7759f50b Eeek, name should be constant! 2013-04-28 10:39:41 +10:00
md_5
824bdc5491 Refactor permissions to be lock free, and clean up duplicate references 2013-04-28 10:37:18 +10:00
md_5
ebff48ff86 Remove remnants of forge in initial handler 2013-04-28 10:27:13 +10:00
md_5
6efba44e5a Cleanup userconnection constructor 2013-04-28 10:26:26 +10:00
md_5
9f8ad518e8 Don't use trove sets 2013-04-28 10:21:15 +10:00
md_5
885a96c0c6 Update lombok/asynchttp/guava versions 2013-04-28 10:12:37 +10:00
md_5
5d0ff24f70 Update async http 2013-04-28 10:11:11 +10:00
md_5
ca5db43f70 Don't spew error about long usernames, just disconnect 2013-04-28 10:07:23 +10:00
md_5
49a22f188f Alert when we cannot bind 2013-04-28 09:42:38 +10:00
md_5
ce7c095243 Make ReusableChannelPromise less hacky 2013-04-28 08:53:14 +10:00
md_5
cbb08ec58b Duh, of course connect isn't called, because we are already connected! 2013-04-27 22:52:02 +10:00
md_5
349949d154 @normanmaurer, @trustin in relation to netty/1317 can we consider this a motion to allow channel.write(Object,null), I think it is a very good idea and cannot see it breaking any existing functionality at all. 2013-04-27 22:24:57 +10:00
md_5
92e7faa346 Stab at closing #285, /send current issues 2013-04-27 18:34:43 +10:00
md_5
6b21fdaaea Refactor packet writes into their own channel handler class. 2013-04-27 18:29:12 +10:00
md_5
fa9dd7e27f Synchronize yaml save to close #286, crash on end 2013-04-27 18:17:40 +10:00
md_5
f44cf6c8e9 Move some bootstrapping to the connected method, #267 2013-04-27 12:27:40 +10:00
md_5
6bf9df31f5 Fix async/login event 2013-04-27 12:25:03 +10:00
md_5
c08764990d Bigger logs, with rotation! 2013-04-26 20:23:16 +10:00
md_5
a82e6f3eea Use new servers 2013-04-26 17:48:32 +10:00
md_5
26cee397e6 Only alow config reloads to ADD servers. 2013-04-26 17:31:44 +10:00
md_5
dc6835c21b Add reason when default server is not defined 2013-04-26 17:23:04 +10:00
md_5
be30c8b89a Rename tab list classes 2013-04-26 17:20:03 +10:00
md_5
70e10c382e Properly interface ServerInfo class. 2013-04-26 17:13:00 +10:00
md_5
93ea108acb Complete issue #190 - unthread the login event for maximum efficiency. 2013-04-26 17:00:09 +10:00
md_5
a63739277b Remove depreceated register methods. 2013-04-26 16:49:37 +10:00
md-5
112d543c2a bump date 2013-04-26 11:50:20 +10:00
Robin Lambertz
7338e20e98 Change jarfile property in Plugin to file 2013-04-26 07:35:08 +10:00
Robin Lambertz
18a5534499 Add jarfile property to Plugin 2013-04-26 07:34:56 +10:00
md_5
e540626a28 Rewrite only arrows and rods. Closes #270 2013-04-20 09:46:23 +10:00
md_5
5e2bcc2907 Use custom AnnotatedHandlerFinder and pretend all events are thread safe 2013-04-15 09:15:20 +10:00
md_5
a38b3ce9f2 Try removing connections via string key and direct map access. Closes issue #267 2013-04-14 18:51:33 +10:00
md_5
c615b2362f Revert "Case shouldn't really matter for groups and permissions"
This reverts commit a67d4a1697.
2013-04-14 11:57:50 +10:00
md_5
5620c4679d Fix issue #262 and put all scoreboard bugs to bed 2013-04-14 09:33:36 +10:00
md_5
a9ad4889f7 Revert "Bungee join / part messages"
This reverts commit 7108bd4deb.
2013-04-13 18:28:11 +10:00
md_5
7108bd4deb Bungee join / part messages 2013-04-13 18:17:08 +10:00
md_5
ac1119bef8 Move pending connects check 2013-04-13 11:51:34 +10:00
md_5
dac259933b Add pending connects for bad plugin message based connects 2013-04-13 09:49:08 +10:00
md_5
a57ae83d62 Return from method when we can't connect 2013-04-13 09:46:21 +10:00
md_5
a00c91c03a Fix users showing as disconnected on global ping list 2013-04-13 09:37:56 +10:00
md_5
a67d4a1697 Case shouldn't really matter for groups and permissions 2013-04-12 19:41:20 +10:00
md_5
b87fff2614 Fix users being disconnected without the event q_q 2013-04-12 12:43:17 +10:00
md_5
0c144c38db Fix issue #251 - hidden servers in list command 2013-04-12 12:40:36 +10:00
md_5
5592f81e97 Proper equals on servers 2013-04-12 08:22:17 +10:00
md_5
5d1a2c59a7 ConcurrentHashMap is junk - lets stick to standard unless issues arise. 2013-04-11 20:32:49 +10:00
md_5
88c99f071e Reduce ram usage by ~65kb / player. See #229 2013-04-11 20:30:07 +10:00
md_5
19c3c23b86 Reformat all code 2013-04-11 20:26:55 +10:00
Björn Teichmann
5dfe83cf6d add fallback_server so we can still have a different default server on first join 2013-04-11 20:23:30 +10:00
Steve Anton
fecaf76acf Initialize depends set to an empty set to prevent a NPE when no depends given. 2013-04-11 11:21:35 +10:00
Steve Anton
c8c1028bd9 Implement support for plugin hard dependencies. 2013-04-11 09:10:40 +10:00
md-5
51be33dbd7 Merge pull request #261 from roblabla/patch-2
Fix LoginEvent not being called.
2013-04-10 14:47:29 -07:00
Robin Lambertz
8cac038a07 Fix LoginEvent not being called.
If the server is in offline mode, the LoginEvent should be called.
2013-04-10 14:47:57 +02:00
md-5
edceaf072c Merge pull request #259 from roblabla/patch-2
Fix Crash with Teams. For real this time.
2013-04-08 17:26:10 -07:00
Robin Lambertz
f935f93d98 Fix two small typos. 2013-04-09 01:18:00 +01:00
Robin Lambertz
e5c457df04 Add new Team instances to the list of teams. 2013-04-09 02:10:41 +02:00
md-5
d4f60e65c3 Merge pull request #258 from roblabla/patch-2
Fix the crash with teams not being cleared
2013-04-08 16:25:05 -07:00
Robin Lambertz
548b2f2c60 Fix the crash with teams not being cleared
You forgot to actually add the team to the list of teams...
2013-04-09 01:23:08 +02:00
md-5
3733ecf628 Merge pull request #250 from weaondara/master
check the player's server before connecting
2013-04-04 14:06:40 -07:00
weaondara
6e9cdb2e20 send message to player if target is current server 2013-04-04 18:44:46 +03:00
weaondara
d900a5eae7 setDisplayName bug fix
first remove
then change and add again
2013-04-02 12:18:43 +03:00
weaondara
68712ab854 check the player's server before really connecting
otherwise the player will be kicked with the message "Logged in from another location" if the target server is the current server
2013-04-02 02:13:29 +03:00
md-5
d067662967 Merge pull request #245 from weaondara/master
add permission to check in PermissionCheckEvent
2013-03-31 19:04:14 -07:00
weaondara
88a52bc4e9 set displayName in function setDisplayName 2013-03-31 16:25:53 +03:00
weaondara
d684f5de69 added permission in constructor 2013-03-31 12:36:21 +03:00
weaondara
a316d6ccdc Update PermissionCheckEvent.java 2013-03-31 12:30:46 +03:00
md_5
5de8ac89e5 Remove any scores before updating - see #238 2013-03-29 08:08:13 +11:00
md_5
8707995503 Nullcheck getServer on failed reconnect handler to account for failings on first connect 2013-03-28 22:24:56 +11:00
md_5
caea1e3fa5 Set server as obsolete when kicked. 2013-03-28 19:53:04 +11:00
md_5
4096012d8e Bump to netty release 2013-03-27 17:39:42 +11:00
md_5
acbf6d3137 Add current server check to failed listener too 2013-03-26 18:12:28 +11:00
md_5
3a3fb27d9a Fixx issue #228 and #188 - CSV classes and ALL target for player list 2013-03-26 17:53:36 +11:00
md-5
e506957d38 Fix current server check - #216 2013-03-26 11:50:36 +11:00
md_5
8003dc50c4 Fix #227 - don't colour first name on list 2013-03-25 19:25:06 +11:00
md_5
75bc2738b9 Check length before checking if command. 2013-03-24 16:32:54 +11:00
md_5
cf4846baa9 Add issue #221 - permission check event 2013-03-24 16:29:45 +11:00
md_5
120a4dc401 Remove HTTP request which snuck in. 2013-03-24 16:25:53 +11:00
md_5
6881597692 Fix issue #156 - actually register packet for reading 2013-03-24 11:53:07 +11:00
md_5
0ffb557557 Try my artistic vision on the list command. 2013-03-24 11:44:30 +11:00
md_5
5f7ecf9d3b Fix issue #213 - servers crashing clients. 2013-03-24 11:39:14 +11:00
md_5
e07f1e603a Lowercase forced server checks - #223 2013-03-24 11:02:24 +11:00
md_5
430b5ff392 Bump expirary date back to 26/4/2013 2013-03-24 09:00:32 +11:00
md_5
81fe547a7c Server admins see stack trace and die. See #225 2013-03-24 08:41:25 +11:00
md_5
04fb1df3e1 Don't null out scores after objectives. 2013-03-23 20:58:21 +11:00
md_5
73aaf58009 Try and make the client not crash when switching teams. @lazertester 2013-03-23 20:49:47 +11:00
md_5
fd062503e1 Skeleton team object. TODO: Make @mbax come and show me how to rewrite entire API. Also interface 2013-03-23 20:41:35 +11:00
md_5
c97f113497 Add team packet. 2013-03-23 20:32:37 +11:00
md_5
14fcb90395 Fire server kick for logins too 2013-03-23 19:38:00 +11:00
md_5
39009d8c96 Check players have a server before sending 2013-03-23 13:45:22 +11:00
md_5
13f394b9a7 Send the players real IP for use in Spigot servers. 2013-03-23 11:24:37 +11:00
md_5
9838a09a8c Add slightly modified version of #220 - ChatColor.getByChar 2013-03-21 21:29:26 +11:00
md_5
ffddcf939f Rewrite cancel method as it is posing some issues 2013-03-21 20:16:41 +11:00
md_5
3d8143c36e Use Bungee thread pool for additional logging 2013-03-21 16:28:30 +11:00
md_5
5e31b158e9 Work around JDK stupidity with regards to thread count 2013-03-21 16:25:05 +11:00
md_5
a59e0f0b6b Async close http client as it appears bugged 2013-03-21 13:54:40 +11:00
md_5
517655f54e How did that debug stay there? 2013-03-21 13:45:56 +11:00
md_5
55ec76beee Allow users to connect 2013-03-21 13:37:38 +11:00
md_5
a564d4c7f1 Fix issue #219 - make the scheduler work 2013-03-21 13:35:35 +11:00
md_5
86b864ce21 Fix small javadoc warning 2013-03-20 20:36:33 +11:00
md_5
6813b82b84 Fix issue #216 and #219 by moving current server check to the connect method. 2013-03-20 20:25:42 +11:00
md_5
27d454524f Use asynchttpclient instead 2013-03-20 19:10:59 +11:00
md_5
8827feacfb Implement high performance HTTP api for plugins with jetty. 2013-03-20 18:52:26 +11:00
md_5
692610cd7e Add asynchronous event API from issue #200 2013-03-19 20:09:15 +11:00
md_5
1edd27963f Add issue #215 - scheduler API 2013-03-19 19:45:34 +11:00
md_5
730c05aaad Actually print time it took 2013-03-19 17:23:07 +11:00
md_5
2bae6cafc2 Try and prevent inefficient plugins by nagging when events take longer than 0.25ms to process. Someone let me know if this spams and I need to increase the max time. 2013-03-19 17:21:54 +11:00
md_5
5a15d5387c Use as many threads as the system can handle. 2013-03-19 16:07:39 +11:00
md_5
3fed94fbf2 Stop trying to be Forge for now. 2013-03-19 12:07:59 +11:00
md_5
1dd661f619 Use a byte array in the ping handler for simplicity 2013-03-19 12:07:13 +11:00
md_5
e364cff44e Fix loading config. 2013-03-19 12:00:57 +11:00
md_5
dfa47f740d Add feature #208 - Bungee texture packs. 2013-03-19 11:54:13 +11:00
md_5
87fcef0658 Implement PR #212 - sendMessages() for CommandSenders 2013-03-19 11:43:37 +11:00
md_5
49f2f5f28b Fix issue #211 - ServerInfo.ping 2013-03-19 11:40:56 +11:00
md_5
a12debf6d0 Revert "Add info on registered channels to /bungee to enable users to help identify cause of random timeouts & resource leaks"
This reverts commit b3c34815b0.
2013-03-18 17:36:57 +11:00
md_5
5d3cb452fe Fix issue #206 by updating netty. Big shoutout to Trustin and the Netty project. 2013-03-18 17:36:41 +11:00
md_5
b3c34815b0 Add info on registered channels to /bungee to enable users to help identify cause of random timeouts & resource leaks 2013-03-17 09:03:20 +11:00
md_5
40768c1711 Update Netty to 4.0.0-Beta3 2013-03-17 09:01:12 +11:00
md_5
b16da7d048 Be sure to null serverSentScoreboard each connect. 2013-03-16 22:35:13 +11:00
md_5
e681c8906d Add server kick event 2013-03-16 21:32:11 +11:00
md_5
ce40391717 Untested attempt at sending users to default server when their server goes down. 2013-03-16 21:17:41 +11:00
md_5
2e51ec4fba *add else statement to prevent duplicate exception logging 2013-03-16 21:09:16 +11:00
md_5
54098c8989 Attempt to track, and remove scoreboards at reconnect 2013-03-16 21:06:28 +11:00
md_5
156ea30c32 Add scoreboard packets + API classes. Still unimplemented. 2013-03-16 20:48:51 +11:00
md_5
34f4bae923 Fix score add definition 2013-03-16 20:37:36 +11:00
md_5
6bb089074e Clear scoreboards on reconnect. 2013-03-16 20:13:01 +11:00
md_5
70c73211a0 Fix remapping of entities (fishing floats) 2013-03-16 13:07:51 +11:00
md_5
c059345802 Add send command, closes issue #197 2013-03-16 12:14:15 +11:00
md_5
f5b4e1242d Add #205 more methods in Plugin for getting resources / data folders. 2013-03-16 11:53:25 +11:00
md_5
5365e5fb92 Bump the other pom versions to 1.5 too. 2013-03-15 21:21:58 +11:00
md_5
dc2ef1eac7 Bump api to 1.5 2013-03-15 21:19:10 +11:00
md_5
113dada511 Depreceate old register command / listener methods. 2013-03-15 21:08:50 +11:00
md_5
8ea5205fef Reuse single packet instance to save overhead 2013-03-15 21:03:45 +11:00
md_5
05d76c3f67 Pretty up login fail message. Fixes #201 2013-03-15 21:01:35 +11:00
md_5
d6e29b3f29 Fix issue #203 - errors in Util.exception when no trace present. 2013-03-15 20:38:40 +11:00
md_5
bd479ba083 Remove outdated $() logger getter. 2013-03-14 21:33:22 +11:00
md_5
704fe11b05 Make forced hosts take higher priority than force default. Closes #184 2013-03-14 21:18:59 +11:00
md_5
4811e7be4f Implement PostLoginEvent, closes #191 2013-03-14 21:11:16 +11:00
md_5
ac426f0c3f Use global netty version variable. 2013-03-14 20:35:58 +11:00
md_5
0f30024040 Now that we don't deploy the proxy we don't need the shaded identifier 2013-03-14 20:28:24 +11:00
md_5
5bfab582df Fix #156 - Bukkit trying to get client settings. 2013-03-14 20:22:26 +11:00
md_5
ec1de0f636 Add global slot limit. Fixes feature request #40 2013-03-14 20:14:01 +11:00
md_5
9bf6a58ba2 Update snakeyaml and guava versions. 2013-03-14 19:51:36 +11:00
md_5
9483c0228b Make protocol only depend on netty-buffer 2013-03-14 19:50:44 +11:00
md_5
09bb7a93d2 Update MySQL version 2013-03-14 19:50:17 +11:00
md_5
8935e77118 Use the Netty byte array encoder now that it is fixed. 2013-03-14 19:49:31 +11:00
md_5
b71d253de2 Clean up cipher codec for maximum speed and minimal memory copy. 2013-03-14 19:39:03 +11:00
md_5
d54f2462a8 Less error for IOExceptions, more debug for exceptions in the exception handler. 2013-03-14 19:22:54 +11:00
md_5
c1ff4ffb89 Update to 1.5 & don't deploy proxy to maven, only APIs 2013-03-14 17:50:33 +11:00
md_5
58f1ab208b Reenable encryption + online mode. 2013-03-14 17:46:57 +11:00
md_5
d5f25b07e5 *remove wrapper class 2013-03-14 17:25:24 +11:00
md_5
30b381853c Change packet handling from ByteBufs to byte arrays to work around netty bug. Connection now appears to be stable - just need to add an optimized encryption algorithm back. 2013-03-14 17:24:32 +11:00
md_5
b0820208e6 @normanm @trustin This hack appears to fix all my issues with writing ByteBufs directly to channels. new @lazertester.party(). Others, please note this still isn't even a beta quality build. Due to memory laziness this build will only accept one connection. 2013-03-13 20:11:41 +11:00
md_5
bc0a076e4b Don't sync, its an optimization - right? 2013-03-13 18:08:43 +11:00
md_5
1763dd3078 Remove unneeded channel option. Still trying to fix all these disconnect errors though. 2013-03-13 18:07:07 +11:00
md_5
373ec187fb Fix /server command to only show server name 2013-03-12 18:07:25 +11:00
md_5
ac2c96c2ea This test WITHOUT encryption reveals something is majorly wrong with our packet decoding causing random and frequent disconnects. 2013-03-12 17:53:18 +11:00
md_5
5688099605 Also make sure we get the restricted value per server 2013-03-12 17:14:50 +11:00
md_5
1d2afae98e Fix canAccess check 2013-03-12 17:13:50 +11:00
md_5
4805087e38 Case insensitive sort 2013-03-12 17:11:06 +11:00
md_5
e2f134ec08 Actually alphabetize players - thanks @Grooohm for the good spot! 2013-03-12 16:56:09 +11:00
md_5
92c1450909 Fix issue #129 - make chat event fire for commands, and add isCommand method. 2013-03-12 15:15:25 +11:00
md_5
fea3642550 Add #183 - restricted servers 2013-03-12 12:13:23 +11:00
md_5
f02d17c979 Fix issue #55 - show alerts in console 2013-03-12 12:03:21 +11:00
md_5
3dac86a94c Add getConsole() to the API 2013-03-12 12:01:47 +11:00
md_5
758e196479 Rewrite list command for per server breakdown, and alphabetizing. 2013-03-12 11:58:04 +11:00
md_5
5dd3384b31 Add GetServer channel, see #145 2013-03-12 11:43:37 +11:00
md_5
59efec128d Add ProxiedPlayer.chat, see #146 2013-03-12 11:38:11 +11:00
md_5
3b90737273 Update CipherCodec to try and fix issues. 2013-03-12 11:21:39 +11:00
md_5
f9f664f9b6 Try using out.writerIndex instead of readerIndex 2013-03-11 20:27:19 +11:00
md_5
9edcda7ace Downgrade NIO to 1.4.7 2013-03-11 18:28:10 +11:00
md_5
cd1420d9cd Fix entity rewrites on falling blocks. 2013-03-11 14:31:51 +11:00
md_5
a3e1493ce1 Merge NIO into master. I would not recommend this on a production server at all. Its 1.5 anyway. 2013-03-11 13:30:29 +11:00
md_5
9fb814003b Handle kicks when trying to login to server. Now we have to be about done. 2013-03-11 10:15:14 +11:00
md_5
76319371f7 Small code / api cleanup. Need to fix kicking in general, especially in ServerConnector before release. 2013-03-11 10:06:14 +11:00
md_5
2e33ab1460 Remove outdated javadoc 2013-03-11 09:52:53 +11:00
md_5
cfd10f5714 Handle when user gets kicked midway through login to other server 2013-03-11 09:47:42 +11:00
md_5
6ae5feee60 Error handling when cannot connect to server. 2013-03-11 09:39:37 +11:00
md_5
0b7b87d9c3 Wait 100ms before closing socket to give server time to process. 2013-03-11 09:30:49 +11:00
md_5
fa5804ec86 OMG WTF BBQ IT WORKS. LETS IRON OUT BUGS AND GET OUR RELEASE TARGET, ONLY 12 HOURS LEFT. 2013-03-11 09:18:39 +11:00
md_5
6e18403cd9 Ensure all resources are closed all the time. 2013-03-11 09:11:36 +11:00
md_5
f67ad024f5 Make builds expire. 2013-03-10 20:01:30 +11:00
md_5
a0989a8932 Update for 1.5. This build only supports 1.5, not any other versions. 2013-03-10 12:41:13 +11:00
md_5
3be83cb5a4 Disconnect when exception caught 2013-03-09 17:59:44 +11:00
md_5
0ce02251d4 Start work on a little spit and polish, with cleaner exceptions. 2013-03-09 16:47:13 +11:00
md_5
b4d104d258 *actually compile (wire up the broadcast method) 2013-03-09 14:31:39 +11:00
md_5
0c69814db7 Make sendMessage work again 2013-03-09 14:29:54 +11:00
md_5
f0766ebcfb Bridge packets both ways. 2013-03-09 14:27:24 +11:00
md_5
f0a19e0f45 Small cleanup of packet classes 2013-03-09 14:23:40 +11:00
md_5
6525502836 We can login now. Kindof. *wipes sweat off brow. 2013-03-09 14:19:12 +11:00
md_5
504f703fbb This is so tiring 2013-03-09 12:35:32 +11:00
md_5
4fb85721a9 Nearly ready to get a working connection, however few hacks due to own shortcomings and netty shortcomings. 2013-03-09 12:08:26 +11:00
md_5
e12bc1d92e Closer to connecting, trying to figure out this encryption bug also present in first connect on Spigot 2013-03-09 10:47:12 +11:00
md_5
bcaafc206f Advancing further in the login process. 2013-03-09 10:10:36 +11:00
md_5
8a96555cc7 We can now get pings! 2013-03-09 09:54:19 +11:00
md_5
45c848a4fd Cleanup channel initialization - now its time to get this show working. 2013-03-09 09:45:10 +11:00
md_5
9e0ae0a70d Thread login auth properly. 2013-03-08 18:26:59 +11:00
md_5
9ad9003974 Tigthen access + javadocs on a few netty related classes. 2013-03-08 18:07:21 +11:00
md_5
e18fe49cf9 Whats this? It compiles. Doesn't mean it near works though. 2013-03-08 17:52:17 +11:00
md_5
c3d702a5b3 Switch main packet interface to bytebuf 2013-03-08 17:35:01 +11:00
md_5
cdf26f7950 Nearing a compilale state, gonna have to redo the bootstrap. 2013-03-08 17:24:09 +11:00
md_5
644deee3c6 Redo parts of login and connection sequences 2013-03-07 21:33:49 +11:00
md_5
b6e76f4054 Cleanup permissions and disconnect sequences 2013-03-07 21:04:03 +11:00
md_5
0f9cc76633 Update Server interface to remove depreceated methods 2013-03-07 20:52:19 +11:00
md_5
0afc52c130 Upstream and downstream bridges are now uber sexy 2013-03-07 20:47:39 +11:00
md_5
0077af58d0 Start work on netty overhaul 2013-03-07 20:05:41 +11:00
197 changed files with 8221 additions and 2874 deletions

5
.gitignore vendored
View File

@@ -1,12 +1,11 @@
# Eclipse stuff
.classpath/
.project/
.classpath
.project
.settings/
# netbeans
nbproject/
nbactions.xml
nb-configuration.xml
# we use maven!
build.xml

31
api/nb-configuration.xml Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

View File

@@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-API</name>
@@ -22,13 +22,25 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>13.0.1</version>
<version>14.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.11</version>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -0,0 +1,46 @@
package net.md_5.bungee.api;
import com.google.common.base.Preconditions;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public abstract class AbstractReconnectHandler implements ReconnectHandler
{
@Override
public ServerInfo getServer(ProxiedPlayer player)
{
ServerInfo server = getForcedHost( player.getPendingConnection() );
if ( server == null )
{
server = getStoredServer( player );
if ( server == null )
{
server = ProxyServer.getInstance().getServerInfo( player.getPendingConnection().getListener().getDefaultServer() );
}
Preconditions.checkState( server != null, "Default server not defined" );
}
return server;
}
public static ServerInfo getForcedHost(PendingConnection con)
{
if ( con.getVirtualHost() == null )
{
return null;
}
String forced = con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
if ( forced == null && con.getListener().isForceDefault() )
{
forced = con.getListener().getDefaultServer();
}
return ProxyServer.getInstance().getServerInfo( forced );
}
protected abstract ServerInfo getStoredServer(ProxiedPlayer player);
}

View File

@@ -1,5 +1,7 @@
package net.md_5.bungee.api;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -105,13 +107,30 @@ public enum ChatColor
* Pattern to remove all colour codes.
*/
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" );
/**
* Colour instances keyed by their active character.
*/
private static final Map<Character, ChatColor> BY_CHAR = new HashMap<>();
/**
* The code appended to {@link #COLOR_CHAR} to make usable colour.
*/
private final char code;
/**
* This colour's colour char prefixed by the {@link #COLOR_CHAR}.
*/
private final String toString;
static
{
for ( ChatColor colour : values() )
{
BY_CHAR.put( colour.code, colour );
}
}
private ChatColor(char code)
{
this.code = code;
this.toString = new String( new char[]
{
COLOR_CHAR, code
@@ -153,4 +172,15 @@ public enum ChatColor
}
return new String( b );
}
/**
* Get the colour represented by the specified code.
*
* @param code the code to search for
* @return the mapped colour, or null if non exists
*/
public static ChatColor getByChar(char code)
{
return BY_CHAR.get( code );
}
}

View File

@@ -19,6 +19,14 @@ public interface CommandSender
*/
public void sendMessage(String message);
/**
* Send several messages to this sender. Each message will be sent
* separately.
*
* @param messages the messages to send
*/
public void sendMessages(String... messages);
/**
* Get all groups this user is part of. This returns an unmodifiable
* collection.

View File

@@ -2,6 +2,7 @@ package net.md_5.bungee.api;
import net.md_5.bungee.api.plugin.PluginManager;
import com.google.common.base.Preconditions;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Map;
@@ -10,8 +11,9 @@ import lombok.Getter;
import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.TaskScheduler;
import net.md_5.bungee.api.tab.CustomTabList;
public abstract class ProxyServer
{
@@ -46,6 +48,13 @@ public abstract class ProxyServer
*/
public abstract String getVersion();
/**
* Gets a localized string from the .properties file.
*
* @return the localized string
*/
public abstract String getTranslation(String name, Object... args);
/**
* Gets the main logger which can be used as a suitable replacement for
* {@link System#out} and {@link System#err}.
@@ -69,20 +78,6 @@ public abstract class ProxyServer
*/
public abstract ProxiedPlayer getPlayer(String name);
/**
* Get a server by its name. The instance returned will be taken from a
* player currently on that server to facilitate abstract proxy -> server
* actions.
*
* @param name the name to lookup
* @return the associated server
* @deprecated in most cases the {@link #getServerInfo(java.lang.String)}
* method should be used, as it will return a server even when no players
* are online.
*/
@Deprecated
public abstract Server getServer(String name);
/**
* Return all servers registered to this proxy, keyed by name. Unlike the
* methods in {@link ConfigurationAdapter#getServers()}, this will not
@@ -124,21 +119,6 @@ public abstract class ProxyServer
*/
public abstract void setConfigurationAdapter(ConfigurationAdapter adapter);
/**
* Get the currently in use tab list handle.
*
* @return the tab list handler
*/
public abstract TabListHandler getTabListHandler();
/**
* Set the used tab list handler, should not be changed once players have
* connected
*
* @param handler the tab list handler to set
*/
public abstract void setTabListHandler(TabListHandler handler);
/**
* Get the currently in use reconnect handler.
*
@@ -208,7 +188,63 @@ public abstract class ProxyServer
*
* @param name name of the server
* @param address connectable Minecraft address + port of the server
* @param motd the motd when used as a forced server
* @param restricted whether the server info restricted property will be set
* @return the constructed instance
*/
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address);
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted);
/**
* Returns the console overlord for this proxy. Being the console, this
* command server cannot have permissions or groups, and will be able to
* execute anything.
*
* @return the console command sender of this proxy
*/
public abstract CommandSender getConsole();
/**
* Return the folder used to load plugins from.
*
* @return the folder used to load plugin
*/
public abstract File getPluginsFolder();
/**
* Get the scheduler instance for this proxy.
*
* @return the in use scheduler
*/
public abstract TaskScheduler getScheduler();
/**
* Get the current number of connected users. The default implementation is
* more efficient than {@link #getPlayers()} as it does not take a lock or
* make a copy.
*
* @return the current number of connected players
*/
public abstract int getOnlineCount();
/**
* Send the specified message to the console and all connected players.
*
* @param message the message to broadcast
*/
public abstract void broadcast(String message);
/**
* Gets a new instance of this proxies custom tab list.
*
* @param player the player to generate this list in the context of
* @return a new {@link CustomTabList} instance
*/
public abstract CustomTabList customTabList(ProxiedPlayer player);
/**
* Gets the commands which are disabled and will not be run on this proxy.
*
* @return the set of disabled commands
*/
public abstract Collection<String> getDisabledCommands();
}

View File

@@ -12,7 +12,7 @@ public interface ReconnectHandler
* @param player the connecting player
* @return the server to connect to
*/
public ServerInfo getServer(ProxiedPlayer player);
ServerInfo getServer(ProxiedPlayer player);
/**
* Save the server of this player before they disconnect so it can be
@@ -20,12 +20,20 @@ public interface ReconnectHandler
*
* @param player the player to save
*/
public void setServer(ProxiedPlayer player);
void setServer(ProxiedPlayer player); // TOOD: String + String arguments?
/**
* Save all pending reconnect locations. Whilst not used for database
* connections, this method will be called at a predefined interval to allow
* the saving of reconnect files.
*/
public void save();
void save();
/**
* Close all connections indicating that the proxy is about to shutdown and
* all data should be saved. No new requests will be made after this method
* has been called.
*
*/
void close();
}

View File

@@ -43,6 +43,15 @@ public interface ConfigurationAdapter
*/
public boolean getBoolean(String path, boolean def);
/**
* Get a list from the specified path.
*
* @param path the path to retrieve the list form.
* @param def the default value
* @return the retrieved list
*/
public Collection<?> getList(String path, Collection<?> def);
/**
* Get the configuration all servers which may be accessible via the proxy.
*

View File

@@ -3,6 +3,7 @@ package net.md_5.bungee.api.config;
import java.net.InetSocketAddress;
import java.util.Map;
import lombok.Data;
import net.md_5.bungee.api.tab.TabListHandler;
/**
* Class representing the configuration of a server listener. Used for allowing
@@ -32,6 +33,11 @@ public class ListenerInfo
* Name of the server which users will be taken to by default.
*/
private final String defaultServer;
/**
* Name of the server which users will be taken when current server goes
* down.
*/
private final String fallbackServer;
/**
* Whether reconnect locations will be used, or else the user is simply
* transferred to the default server on connect.
@@ -42,4 +48,25 @@ public class ListenerInfo
* transferred depending on the host they connect to.
*/
private final Map<String, String> forcedHosts;
/**
* Class used to build tab lists for this player.
*/
private final Class<? extends TabListHandler> tabList;
/**
* Whether to set the local address when connecting to servers.
*/
private final boolean setLocalAddress;
/**
* Whether to pass the ping through when we can reliably get the target
* server (force default server).
*/
private final boolean pingPassthrough;
/**
* What port to run udp query on.
*/
private final int queryPort;
/**
* Whether to enable udp query.
*/
private final boolean queryEnabled;
}

View File

@@ -1,69 +1,56 @@
package net.md_5.bungee.api.config;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Synchronized;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/**
* Class used to represent a server to connect to.
*/
@Data
@AllArgsConstructor
public abstract class ServerInfo
public interface ServerInfo
{
/**
* Name this server displays as.
* Get the name of this server.
*
* @return the configured name for this server address
*/
private final String name;
/**
* Connectable address of this server.
*/
private final InetSocketAddress address;
/**
* Players connected to a server defined by these properties.
*/
private final Collection<ProxiedPlayer> players = new ArrayList<>();
String getName();
/**
* Add a player to the internal set of this server.
* Gets the connectable host + port pair for this server. Implementations
* expect this to be used as the unique identifier per each instance of this
* class.
*
* @param player the player to add
* @return the IP and port pair for this server
*/
@Synchronized("players")
public void addPlayer(ProxiedPlayer player)
{
players.add( player );
}
/**
* Remove a player form the internal set of this server.
*
* @param player the player to remove
*/
@Synchronized("players")
public void removePlayer(ProxiedPlayer player)
{
players.remove( player );
}
InetSocketAddress getAddress();
/**
* Get the set of all players on this server.
*
* @return an unmodifiable collection of all players on this server
*/
@Synchronized("players")
public Collection<ProxiedPlayer> getPlayers()
{
return Collections.unmodifiableCollection( players );
}
Collection<ProxiedPlayer> getPlayers();
/**
* Returns the MOTD which should be used when this server is a forced host.
*
* @return the motd
*/
String getMotd();
/**
* Whether the player can access this server. It will only return false when
* the player has no permission and this server is restricted.
*
* @param sender the player to check access for
* @return whether access is granted to this server
*/
boolean canAccess(CommandSender sender);
/**
* Send data by any available means to this server.
@@ -71,12 +58,12 @@ public abstract class ServerInfo
* @param channel the channel to send this data via
* @param data the data to send
*/
public abstract void sendData(String channel, byte[] data);
void sendData(String channel, byte[] data);
/**
* Asynchronously gets the current player count on this server.
*
* @param callback the callback to call when the count has been retrieved.
*/
public abstract void ping(Callback<ServerPing> callback);
void ping(Callback<ServerPing> callback);
}

View File

@@ -1,6 +1,7 @@
package net.md_5.bungee.api.connection;
import java.net.InetSocketAddress;
import net.md_5.bungee.protocol.packet.DefinedPacket;
/**
* A proxy connection is defined as a connection directly connected to a socket.
@@ -15,5 +16,33 @@ public interface Connection
*
* @return the remote address
*/
public InetSocketAddress getAddress();
InetSocketAddress getAddress();
/**
* Disconnects this end of the connection for the specified reason. If this
* is an {@link ProxiedPlayer} the respective server connection will be
* closed too.
*
* @param reason the reason shown to the player / sent to the server on
* disconnect
*/
void disconnect(String reason);
/**
* Get the unsafe methods of this class.
*
* @return the unsafe method interface
*/
Unsafe unsafe();
interface Unsafe
{
/**
* Send a packet to this connection.
*
* @param packet the packet to send
*/
void sendPacket(DefinedPacket packet);
}
}

View File

@@ -14,34 +14,26 @@ public interface PendingConnection extends Connection
*
* @return the requested username, or null if not set
*/
public String getName();
String getName();
/**
* Get the numerical client version of the player attempting to log in.
*
* @return the protocol version of the remote client
*/
public byte getVersion();
byte getVersion();
/**
* Get the requested virtual host that the client tried to connect to.
*
* @return request virtual host or null if invalid / not specified.
*/
public InetSocketAddress getVirtualHost();
/**
* Completely kick this user from the proxy and all of its child
* connections.
*
* @param reason the disconnect reason displayed to the player
*/
public void disconnect(String reason);
InetSocketAddress getVirtualHost();
/**
* Get the listener that accepted this connection.
*
* @return the accepting listener
*/
public ListenerInfo getListener();
ListenerInfo getListener();
}

View File

@@ -2,6 +2,7 @@ package net.md_5.bungee.api.connection;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.tab.TabListHandler;
/**
* Represents a player who's connection is being connected to somewhere else,
@@ -15,7 +16,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
*
* @return the players current display name
*/
public String getDisplayName();
String getDisplayName();
/**
* Sets this players display name to be used as their nametag and tab list
@@ -23,7 +24,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
*
* @param name the name to set
*/
public void setDisplayName(String name);
void setDisplayName(String name);
/**
* Connects / transfers this user to the specified connection, gracefully
@@ -32,28 +33,21 @@ public interface ProxiedPlayer extends Connection, CommandSender
*
* @param target the new server to connect to
*/
public void connect(ServerInfo target);
void connect(ServerInfo target);
/**
* Gets the server this player is connected to.
*
* @return the server this player is connected to
*/
public Server getServer();
Server getServer();
/**
* Gets the ping time between the proxy and this connection.
*
* @return the current ping time
*/
public int getPing();
/**
* Disconnect (remove) this player from the proxy with the specified reason.
*
* @param reason the reason displayed to the player
*/
public void disconnect(String reason);
int getPing();
/**
* Send a plugin message to this player.
@@ -61,12 +55,48 @@ public interface ProxiedPlayer extends Connection, CommandSender
* @param channel the channel to send this data via
* @param data the data to send
*/
public void sendData(String channel, byte[] data);
void sendData(String channel, byte[] data);
/**
* Get the pending connection that belongs to this player.
*
* @return the pending connection that this player used
*/
public PendingConnection getPendingConnection();
PendingConnection getPendingConnection();
/**
* Make this player chat (say something), to the server he is currently on.
*
* @param message the message to say
*/
void chat(String message);
/**
* Sets the new tab list for the user. At this stage it is not advisable to
* change after the user has logged in!
*
* @param list the new list
*/
void setTabList(TabListHandler list);
/**
* Get the current tab list.
*
* @return the tab list in use by this user
*/
TabListHandler getTabList();
/**
* Get the server which this player will be sent to next time the log in.
*
* @return the server, or null if default
*/
ServerInfo getReconnectServer();
/**
* Set the server which this player will be sent to next time the log in.
*
* @param server the server to set
*/
void setReconnectServer(ServerInfo server);
}

View File

@@ -1,7 +1,5 @@
package net.md_5.bungee.api.connection;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo;
/**
@@ -24,14 +22,4 @@ public interface Server extends Connection
* @param data the data to send
*/
public abstract void sendData(String channel, byte[] data);
/**
* Asynchronously gets the current player count on this server.
*
* @param callback the callback to call when the count has been retrieved.
* @deprecated use the corresponding method in {@link ServerInfo} for
* clarity
*/
@Deprecated
public abstract void ping(Callback<ServerPing> callback);
}

View File

@@ -0,0 +1,75 @@
package net.md_5.bungee.api.event;
import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.plugin.Event;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Represents an event which depends on the result of asynchronous operations.
*
* @param <T> Type of this event
*/
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class AsyncEvent<T> extends Event
{
private final Callback<T> done;
private final Set<Plugin> intents = Collections.newSetFromMap( new ConcurrentHashMap<Plugin, Boolean>() );
private final AtomicBoolean fired = new AtomicBoolean();
private final AtomicInteger latch = new AtomicInteger();
@Override
@SuppressWarnings("unchecked")
public void postCall()
{
fired.set( true );
if ( latch.get() == 0 )
{
done.done( (T) this, null );
}
}
/**
* Register an intent that this plugin will continue to perform work on a
* background task, and wishes to let the event proceed once the registered
* background task has completed.
*
* @param plugin the plugin registering this intent
*/
public void registerIntent(Plugin plugin)
{
Preconditions.checkState( !fired.get(), "Event %s has already been fired", this );
Preconditions.checkState( !intents.contains( plugin ), "Plugin %s already registered intent for event %s", plugin, this );
intents.add( plugin );
latch.incrementAndGet();
}
/**
* Notifies this event that this plugin has done all its required processing
* and wishes to let the event proceed.
*
* @param plugin a plugin which has an intent registered for this event
*/
@SuppressWarnings("unchecked")
public void completeIntent(Plugin plugin)
{
Preconditions.checkState( intents.contains( plugin ), "Plugin %s has not registered intent for event %s", plugin, this );
intents.remove( plugin );
if ( latch.decrementAndGet() == 0 && fired.get() )
{
done.done( (T) this, null );
}
}
}

View File

@@ -30,4 +30,14 @@ public class ChatEvent extends TargetedEvent implements Cancellable
super( sender, receiver );
this.message = message;
}
/**
* Checks whether this message is valid as a command
*
* @return if this message is a command
*/
public boolean isCommand()
{
return message.length() > 0 && message.charAt( 0 ) == '/';
}
}

View File

@@ -3,9 +3,9 @@ package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
/**
* Event called to represent a player logging in.
@@ -13,7 +13,7 @@ import net.md_5.bungee.api.plugin.Event;
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class LoginEvent extends Event implements Cancellable
public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
{
/**
@@ -28,4 +28,10 @@ public class LoginEvent extends Event implements Cancellable
* Connection attempting to login.
*/
private final PendingConnection connection;
public LoginEvent(PendingConnection connection, Callback<LoginEvent> done)
{
super( done );
this.connection = connection;
}
}

View File

@@ -0,0 +1,40 @@
package net.md_5.bungee.api.event;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Event;
/**
* Called when the permission of a CommandSender is checked.
*/
@Data
@AllArgsConstructor
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class PermissionCheckEvent extends Event
{
/**
* The command sender being checked for a permission.
*/
private final CommandSender sender;
/**
* The permission to check.
*/
private final String permission;
/**
* The outcome of this permission check.
*/
@Getter(AccessLevel.NONE)
private boolean hasPermission;
public boolean hasPermission()
{
return hasPermission;
}
}

View File

@@ -0,0 +1,34 @@
package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.protocol.packet.Packet2Handshake;
import net.md_5.bungee.api.plugin.Event;
/**
* Event called to represent a player first making their presence and username
* known.
*/
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class PlayerHandshakeEvent extends Event
{
/**
* Connection attempting to login.
*/
private final PendingConnection connection;
/**
* The handshake.
*/
private final Packet2Handshake handshake;
public PlayerHandshakeEvent(PendingConnection connection, Packet2Handshake handshake)
{
this.connection = connection;
this.handshake = handshake;
}
}

View File

@@ -0,0 +1,23 @@
package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Event;
/**
* Event called as soon as a connection has an {@link ProxiedPlayer} and is
* ready to be connected to a server.
*/
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class PostLoginEvent extends Event
{
/**
* The player involved with this event.
*/
private final ProxiedPlayer player;
}

View File

@@ -1,18 +1,18 @@
package net.md_5.bungee.api.event;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
@Data
@AllArgsConstructor
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class ServerConnectEvent extends Event
public class ServerConnectEvent extends Event implements Cancellable
{
/**
@@ -22,5 +22,16 @@ public class ServerConnectEvent extends Event
/**
* Server the player will be connected to.
*/
@NonNull
private ServerInfo target;
/**
* Cancelled state.
*/
private boolean cancelled;
public ServerConnectEvent(ProxiedPlayer player, ServerInfo target)
{
this.player = player;
this.target = target;
}
}

View File

@@ -0,0 +1,59 @@
package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Cancellable;
import net.md_5.bungee.api.plugin.Event;
/**
* Represents a player getting kicked from a server.
*/
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class ServerKickEvent extends Event implements Cancellable
{
/**
* Cancelled status.
*/
private boolean cancelled;
/**
* Player being kicked.
*/
private final ProxiedPlayer player;
/**
* Kick reason.
*/
private String kickReason;
/**
* Server to send player to if this event is cancelled.
*/
private ServerInfo cancelServer;
/**
* State in which the kick occured.
*/
private State state;
public enum State
{
CONNECTING, CONNECTED, UNKNOWN;
}
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer)
{
this( player, kickReason, cancelServer, State.UNKNOWN );
}
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer, State state)
{
this.player = player;
this.kickReason = kickReason;
this.cancelServer = cancelServer;
this.state = state;
}
}

View File

@@ -0,0 +1,22 @@
package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Event;
/**
* Called when a player has changed servers.
*/
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class ServerSwitchEvent extends Event
{
/**
* Player whom the server is for.
*/
private final ProxiedPlayer player;
}

View File

@@ -5,4 +5,11 @@ package net.md_5.bungee.api.plugin;
*/
public abstract class Event
{
/**
* Method called after this event has been dispatched to all handlers.
*/
public void postCall()
{
}
}

View File

@@ -1,6 +1,10 @@
package net.md_5.bungee.api.plugin;
import java.io.File;
import java.io.InputStream;
import java.util.logging.Logger;
import lombok.Getter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ConfigurationAdapter;
/**
@@ -12,6 +16,12 @@ public class Plugin
@Getter
private PluginDescription description;
@Getter
private ProxyServer proxy;
@Getter
private File file;
@Getter
private Logger logger;
/**
* Called when the plugin has just been loaded. Most of the proxy will not
@@ -36,13 +46,41 @@ public class Plugin
{
}
/**
* Gets the data folder where this plugin may store arbitrary data. It will
* be a child of {@link ProxyServer#getPluginsFolder()}.
*
* @return the data folder of this plugin
*/
public final File getDataFolder()
{
return new File( getProxy().getPluginsFolder(), getDescription().getName() );
}
/**
* Get a resource from within this plugins jar or container. Care must be
* taken to close the returned stream.
*
* @param name the full path name of this resource
* @return the stream for getting this resource, or null if it does not
* exist
*/
public final InputStream getResourceAsStream(String name)
{
return getClass().getClassLoader().getResourceAsStream( name );
}
/**
* Called by the loader to initialize the fields in this plugin.
*
* @param description the description that describes this plugin
* @param jarfile this plugins jar or container
*/
final void init(PluginDescription description)
final void init(ProxyServer proxy, PluginDescription description)
{
this.proxy = proxy;
this.description = description;
this.file = description.getFile();
this.logger = new PluginLogger( this );
}
}

View File

@@ -2,13 +2,18 @@ package net.md_5.bungee.api.plugin;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class PluginClassloader extends URLClassLoader
{
private static final Set<PluginClassloader> allLoaders = new HashSet<>();
private static final Set<PluginClassloader> allLoaders = new CopyOnWriteArraySet<>();
static
{
ClassLoader.registerAsParallelCapable();
}
public PluginClassloader(URL[] urls)
{
@@ -45,6 +50,6 @@ public class PluginClassloader extends URLClassLoader
}
}
}
throw new ClassNotFoundException(name);
throw new ClassNotFoundException( name );
}
}

View File

@@ -1,12 +1,17 @@
package net.md_5.bungee.api.plugin;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* POJO representing the plugin.yml file.
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PluginDescription
{
@@ -27,8 +32,12 @@ public class PluginDescription
* Plugin author.
*/
private String author;
public PluginDescription()
{
}
/**
* Plugin hard dependencies.
*/
private Set<String> depends = new HashSet<>();
/**
* File we were loaded from.
*/
private File file = null;
}

View File

@@ -0,0 +1,24 @@
package net.md_5.bungee.api.plugin;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import net.md_5.bungee.api.ProxyServer;
public class PluginLogger extends Logger
{
private String pluginName;
protected PluginLogger(Plugin plugin)
{
super( plugin.getClass().getCanonicalName(), null );
pluginName = "[" + plugin.getDescription().getName() + "] ";
}
@Override
public void log(LogRecord logRecord)
{
logRecord.setMessage( pluginName + logRecord.getMessage() );
ProxyServer.getInstance().getLogger().log( logRecord );
}
}

View File

@@ -1,51 +1,75 @@
package net.md_5.bungee.api.plugin;
import com.google.common.base.Preconditions;
import com.google.common.eventbus.EventBus;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.Subscribe;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.event.EventBus;
import net.md_5.bungee.event.EventHandler;
import org.yaml.snakeyaml.Yaml;
/**
* Class to manage bridging between plugin duties and implementation duties, for
* example event handling and plugin management.
*/
@RequiredArgsConstructor
public class PluginManager
{
private static final Pattern argsSplit = Pattern.compile( " " );
/*========================================================================*/
private final ProxyServer proxy;
/*========================================================================*/
private final Yaml yaml = new Yaml();
private final EventBus eventBus = new EventBus();
private final Map<String, Plugin> plugins = new HashMap<>();
private final EventBus eventBus;
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
private final Map<String, Command> commandMap = new HashMap<>();
private Map<String, PluginDescription> toLoad = new HashMap<>();
private Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
private Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
@SuppressWarnings("unchecked")
public PluginManager(ProxyServer proxy)
{
this.proxy = proxy;
eventBus = new EventBus( proxy.getLogger() );
}
/**
* Register a command so that it may be executed.
*
* @param plugin the plugin owning this command
* @param command the command to register
*/
public void registerCommand(Command command)
public void registerCommand(Plugin plugin, Command command)
{
commandMap.put( command.getName().toLowerCase(), command );
for ( String alias : command.getAliases() )
{
commandMap.put( alias.toLowerCase(), command );
}
commandsByPlugin.put( plugin, command );
}
/**
@@ -56,6 +80,26 @@ public class PluginManager
public void unregisterCommand(Command command)
{
commandMap.values().remove( command );
commandsByPlugin.values().remove( command );
}
/**
* Unregister all commands owned by a {@link Plugin}
*
* @param plugin the plugin to register the commands of
*/
public void unregisterCommands(Plugin plugin)
{
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
{
commandMap.values().remove( it.next() );
it.remove();
}
}
public boolean dispatchCommand(CommandSender sender, String commandLine)
{
return dispatchCommand( sender, commandLine, null );
}
/**
@@ -66,10 +110,21 @@ public class PluginManager
* arguments
* @return whether the command was handled
*/
public boolean dispatchCommand(CommandSender sender, String commandLine)
public boolean dispatchCommand(CommandSender sender, String commandLine, List<String> tabResults)
{
String[] split = argsSplit.split( commandLine );
Command command = commandMap.get( split[0].toLowerCase() );
// Check for chat that only contains " "
if ( split.length == 0 )
{
return false;
}
String commandName = split[0].toLowerCase();
if ( proxy.getDisabledCommands().contains( commandName ) )
{
return false;
}
Command command = commandMap.get( commandName );
if ( command == null )
{
return false;
@@ -78,14 +133,23 @@ public class PluginManager
String permission = command.getPermission();
if ( permission != null && !permission.isEmpty() && !sender.hasPermission( permission ) )
{
sender.sendMessage( ChatColor.RED + "You do not have permission to execute this command!" );
sender.sendMessage( proxy.getTranslation( "no_permission" ) );
return true;
}
String[] args = Arrays.copyOfRange( split, 1, split.length );
try
{
command.execute( sender, args );
if ( tabResults == null )
{
command.execute( sender, args );
} else if ( command instanceof TabExecutor )
{
for ( String s : ( (TabExecutor) command ).onTabComplete( sender, args ) )
{
tabResults.add( s );
}
}
} catch ( Exception ex )
{
sender.sendMessage( ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details." );
@@ -115,65 +179,114 @@ public class PluginManager
return plugins.get( name );
}
/**
* Enable all plugins by calling the {@link Plugin#onEnable()} method.
*/
public void enablePlugins()
public void loadAndEnablePlugins()
{
for ( Map.Entry<String, Plugin> entry : plugins.entrySet() )
Map<PluginDescription, Boolean> pluginStatuses = new HashMap<>();
for ( Map.Entry<String, PluginDescription> entry : toLoad.entrySet() )
{
PluginDescription plugin = entry.getValue();
if ( !enablePlugin( pluginStatuses, new Stack<PluginDescription>(), plugin ) )
{
ProxyServer.getInstance().getLogger().warning( "Failed to enable " + entry.getKey() );
}
}
toLoad.clear();
toLoad = null;
for ( Plugin plugin : plugins.values() )
{
Plugin plugin = entry.getValue();
try
{
plugin.onEnable();
ProxyServer.getInstance().getLogger().log( Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[]
{
entry.getKey(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
} );
} catch ( Exception ex )
} catch ( Throwable t )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + entry.getKey(), ex );
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + plugin.getDescription().getName(), t );
}
}
}
/**
* Load a plugin from the specified file. This file must be in jar format.
* This will not enable plugins, {@link #enablePlugins()} must be called.
*
* @param file the file to load from
* @throws Exception Any exceptions encountered when loading a plugin from
* this file.
*/
public void loadPlugin(File file) throws Exception
private boolean enablePlugin(Map<PluginDescription, Boolean> pluginStatuses, Stack<PluginDescription> dependStack, PluginDescription plugin)
{
Preconditions.checkNotNull( file, "file" );
Preconditions.checkArgument( file.isFile(), "Must load from file" );
try ( JarFile jar = new JarFile( file ) )
if ( pluginStatuses.containsKey( plugin ) )
{
JarEntry pdf = jar.getJarEntry( "plugin.yml" );
Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" );
return pluginStatuses.get( plugin );
}
try ( InputStream in = jar.getInputStream( pdf ) )
// success status
boolean status = true;
// try to load dependencies first
for ( String dependName : plugin.getDepends() )
{
PluginDescription depend = toLoad.get( dependName );
Boolean dependStatus = ( depend != null ) ? pluginStatuses.get( depend ) : Boolean.FALSE;
if ( dependStatus == null )
{
PluginDescription desc = yaml.loadAs( in, PluginDescription.class );
URLClassLoader loader = new PluginClassloader( new URL[]
if ( dependStack.contains( depend ) )
{
file.toURI().toURL()
} );
Class<?> main = loader.loadClass( desc.getMain() );
Plugin plugin = (Plugin) main.getDeclaredConstructor().newInstance();
StringBuilder dependencyGraph = new StringBuilder();
for ( PluginDescription element : dependStack )
{
dependencyGraph.append( element.getName() ).append( " -> " );
}
dependencyGraph.append( plugin.getName() ).append( " -> " ).append( dependName );
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Circular dependency detected: " + dependencyGraph );
status = false;
} else
{
dependStack.push( plugin );
dependStatus = this.enablePlugin( pluginStatuses, dependStack, depend );
dependStack.pop();
}
}
plugin.init( desc );
plugins.put( desc.getName(), plugin );
plugin.onLoad();
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
if ( dependStatus == Boolean.FALSE )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} (required by {1}) is unavailable", new Object[]
{
desc.getName(), desc.getVersion(), desc.getAuthor()
String.valueOf( depend.getName() ), plugin.getName()
} );
status = false;
}
if ( !status )
{
break;
}
}
// do actual loading
if ( status )
{
try
{
URLClassLoader loader = new PluginClassloader( new URL[]
{
plugin.getFile().toURI().toURL()
} );
Class<?> main = loader.loadClass( plugin.getMain() );
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
clazz.init( proxy, plugin );
plugins.put( plugin.getName(), clazz );
clazz.onLoad();
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
{
plugin.getName(), plugin.getVersion(), plugin.getAuthor()
} );
} catch ( Throwable t )
{
proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
}
}
pluginStatuses.put( plugin, status );
return status;
}
/**
@@ -181,7 +294,7 @@ public class PluginManager
*
* @param folder the folder to search for plugins in
*/
public void loadPlugins(File folder)
public void detectPlugins(File folder)
{
Preconditions.checkNotNull( folder, "folder" );
Preconditions.checkArgument( folder.isDirectory(), "Must load from a directory" );
@@ -190,9 +303,17 @@ public class PluginManager
{
if ( file.isFile() && file.getName().endsWith( ".jar" ) )
{
try
try ( JarFile jar = new JarFile( file ) )
{
loadPlugin( file );
JarEntry pdf = jar.getJarEntry( "plugin.yml" );
Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" );
try ( InputStream in = jar.getInputStream( pdf ) )
{
PluginDescription desc = yaml.loadAs( in, PluginDescription.class );
desc.setFile( file );
toLoad.put( desc.getName(), desc );
}
} catch ( Exception ex )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load plugin from file " + file, ex );
@@ -211,19 +332,64 @@ public class PluginManager
*/
public <T extends Event> T callEvent(T event)
{
Preconditions.checkNotNull( event, "event" );
long start = System.nanoTime();
eventBus.post( event );
event.postCall();
long elapsed = start - System.nanoTime();
if ( elapsed > 250000 )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Event {0} took more {1}ns to process!", new Object[]
{
event, elapsed
} );
}
return event;
}
/**
* Register a {@link Listener} for receiving called events. Methods in this
* Object which wish to receive events must be annotated with the
* {@link Subscribe} annotation.
* {@link EventHandler} annotation.
*
* @param plugin the owning plugin
* @param listener the listener to register events for
*/
public void registerListener(Listener listener)
public void registerListener(Plugin plugin, Listener listener)
{
for ( Method method : listener.getClass().getDeclaredMethods() )
{
Preconditions.checkArgument( !method.isAnnotationPresent( Subscribe.class ),
"Listener %s has registered using deprecated subscribe annotation! Please update to @EventHandler.", listener );
}
eventBus.register( listener );
listenersByPlugin.put( plugin, listener );
}
/**
* Unregister a {@link Listener} so that the events do not reach it anymore.
*
* @param listener the listener to unregister
*/
public void unregisterListener(Listener listener)
{
eventBus.unregister( listener );
listenersByPlugin.values().remove( listener );
}
/**
* Unregister all of a Plugin's listener.
*
* @param plugin
*/
public void unregisterListeners(Plugin plugin)
{
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
{
eventBus.unregister( it.next() );
it.remove();
}
}
}

View File

@@ -0,0 +1,10 @@
package net.md_5.bungee.api.plugin;
import net.md_5.bungee.api.CommandSender;
public interface TabExecutor
{
public Iterable<String> onTabComplete(CommandSender sender, String[] args);
}

View File

@@ -0,0 +1,36 @@
package net.md_5.bungee.api.scheduler;
import net.md_5.bungee.api.plugin.Plugin;
/**
* Represents a task scheduled for execution by the {@link TaskScheduler}.
*/
public interface ScheduledTask
{
/**
* Gets the unique ID of this task.
*
* @return this tasks ID
*/
int getId();
/**
* Return the plugin which scheduled this task for execution.
*
* @return the owning plugin
*/
Plugin getOwner();
/**
* Get the actual method which will be executed by this task.
*
* @return the {@link Runnable} behind this task
*/
Runnable getTask();
/**
* Cancel this task to suppress subsequent executions.
*/
void cancel();
}

View File

@@ -0,0 +1,74 @@
package net.md_5.bungee.api.scheduler;
import java.util.concurrent.TimeUnit;
import net.md_5.bungee.api.plugin.Plugin;
/**
* This interface represents a scheduler which may be used to queue, delay and
* execute tasks in an asynchronous fashion.
*/
public interface TaskScheduler
{
/**
* Cancel a task to prevent it from executing, or if its a repeating task,
* prevent its further execution.
*
* @param id the id of the task to cancel
*/
void cancel(int id);
/**
* Cancel a task to prevent it from executing, or if its a repeating task,
* prevent its further execution.
*
* @param task the task to cancel
*/
void cancel(ScheduledTask task);
/**
* Cancel all tasks owned by this plugin, this preventing them from being
* executed hereon in.
*
* @param plugin the plugin owning the tasks to be cancelled
* @return the number of tasks cancelled by this method
*/
int cancel(Plugin plugin);
/**
* Schedule a task to be executed asynchronously. The task will commence
* running as soon as this method returns.
*
* @param owner the plugin owning this task
* @param task the task to run
* @return the scheduled task
*/
ScheduledTask runAsync(Plugin owner, Runnable task);
/**
* Schedules a task to be executed asynchronously after the specified delay
* is up.
*
* @param owner the plugin owning this task
* @param task the task to run
* @param delay the delay before this task will be executed
* @param unit the unit in which the delay will be measured
* @return the scheduled task
*/
ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit);
/**
* Schedules a task to be executed asynchronously after the specified delay
* is up. The scheduled task will continue running at the specified
* interval. The interval will not begin to count down until the last task
* invocation is complete.
*
* @param owner the plugin owning this task
* @param task the task to run
* @param delay the delay in milliseconds before this task will be executed
* @param period the interval before subsequent executions of this task
* @param unit the unit in which the delay and period will be measured
* @return the scheduled task
*/
ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit);
}

View File

@@ -0,0 +1,20 @@
package net.md_5.bungee.api.score;
import lombok.Data;
/**
* Represents an objective entry.
*/
@Data
public class Objective
{
/**
* Name of the objective.
*/
private final String name;
/**
* Value of the objective.
*/
private final String value; // displayName
}

View File

@@ -0,0 +1,10 @@
package net.md_5.bungee.api.score;
/**
* Represents locations for a scoreboard to be displayed.
*/
public enum Position
{
LIST, SIDEBAR, BELOW;
}

View File

@@ -0,0 +1,24 @@
package net.md_5.bungee.api.score;
import lombok.Data;
/**
* Represents a scoreboard score entry.
*/
@Data
public class Score
{
/**
* Name to be displayed in the list.
*/
private final String itemName; // Player
/**
* Unique name of the score.
*/
private final String scoreName; // Score
/**
* Value of the score.
*/
private final int value;
}

View File

@@ -0,0 +1,100 @@
package net.md_5.bungee.api.score;
import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Scoreboard
{
/**
* Unique name for this scoreboard.
*/
private String name;
/**
* Position of this scoreboard.
*/
private Position position;
/**
* Objectives for this scoreboard.
*/
private final Map<String, Objective> objectives = new HashMap<>();
/**
* Scores for this scoreboard.
*/
private final Map<String, Score> scores = new HashMap<>();
/**
* Teams on this board.
*/
private final Map<String, Team> teams = new HashMap<>();
public Collection<Objective> getObjectives()
{
return Collections.unmodifiableCollection( objectives.values() );
}
public Collection<Score> getScores()
{
return Collections.unmodifiableCollection( scores.values() );
}
public Collection<Team> getTeams()
{
return Collections.unmodifiableCollection( teams.values() );
}
public void addObjective(Objective objective)
{
Preconditions.checkNotNull( objective, "objective" );
Preconditions.checkArgument( !objectives.containsKey( objective.getName() ), "Objective %s already exists in this scoreboard", objective.getName() );
objectives.put( objective.getName(), objective );
}
public void addScore(Score score)
{
Preconditions.checkNotNull( score, "score" );
scores.put( score.getItemName(), score );
}
public void addTeam(Team team)
{
Preconditions.checkNotNull( team, "team" );
Preconditions.checkArgument( !teams.containsKey( team.getName() ), "Team %s already exists in this scoreboard", team.getName() );
teams.put( team.getName(), team );
}
public Team getTeam(String name)
{
return teams.get( name );
}
public void removeObjective(String objectiveName)
{
objectives.remove( objectiveName );
}
public void removeScore(String scoreName)
{
scores.remove( scoreName );
}
public void removeTeam(String teamName)
{
teams.remove( teamName );
}
public void clear()
{
name = null;
position = null;
objectives.clear();
scores.clear();
teams.clear();
}
}

View File

@@ -0,0 +1,36 @@
package net.md_5.bungee.api.score;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import lombok.Data;
import lombok.NonNull;
@Data
public class Team
{
@NonNull
private final String name;
private String displayName;
private String prefix;
private String suffix;
private boolean friendlyFire;
private Set<String> players = new HashSet<>();
public Collection<String> getPlayers()
{
return Collections.unmodifiableSet( players );
}
public void addPlayer(String name)
{
players.add( name );
}
public void removePlayer(String name)
{
players.remove( name );
}
}

View File

@@ -0,0 +1,60 @@
package net.md_5.bungee.api.tab;
/**
* Represents a custom tab list, which may have slots manipulated.
*/
public interface CustomTabList extends TabListHandler
{
/**
* Blank out this tab list and update immediately.
*/
void clear();
/**
* Gets the columns in this list.
*
* @return the width of this list
*/
int getColumns();
/**
* Gets the rows in this list.
*
* @return the height of this list
*/
int getRows();
/**
* Get the total size of this list.
*
* @return {@link #getRows()} * {@link #getColumns()}
*/
int getSize();
/**
* Set the text in the specified slot and update immediately.
*
* @param row the row to set
* @param column the column to set
* @param text the text to set
* @return the padded text
*/
String setSlot(int row, int column, String text);
/**
* Set the text in the specified slot.
*
* @param row the row to set
* @param column the column to set
* @param text the text to set
* @param update whether or not to invoke {@link #update()} upon completion
* @return the padded text
*/
String setSlot(int row, int column, String text, boolean update);
/**
* Flush all queued changes to the user.
*/
void update();
}

View File

@@ -0,0 +1,39 @@
package net.md_5.bungee.api.tab;
import lombok.Getter;
import lombok.NoArgsConstructor;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@NoArgsConstructor
public abstract class TabListAdapter implements TabListHandler
{
@Getter
private ProxiedPlayer player;
@Override
public void init(ProxiedPlayer player)
{
this.player = player;
}
@Override
public void onConnect()
{
}
@Override
public void onDisconnect()
{
}
@Override
public void onServerChange()
{
}
@Override
public void onPingChange(int ping)
{
}
}

View File

@@ -1,23 +1,30 @@
package net.md_5.bungee.api;
package net.md_5.bungee.api.tab;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public interface TabListHandler
{
/**
* Called so that this class may set member fields to keep track of its
* internal state. You should not do any packet sending or manipulation of
* the passed player, other than storing it.
*
* @param player the player to be associated with this list
*/
void init(ProxiedPlayer player);
/**
* Called when this player first connects to the proxy.
*/
void onConnect();
/**
* Called when a player first connects to the proxy.
*
* @param player the connecting player
*/
public void onConnect(ProxiedPlayer player);
/**
* Called when a player changes their connected server.
*
* @param player the player who changed servers
*/
public void onServerChange(ProxiedPlayer player);
void onServerChange();
/**
* Called when a players ping changes. The new ping will have not updated in
@@ -26,14 +33,14 @@ public interface TabListHandler
* @param player the player who's ping changed
* @param ping the player's new ping.
*/
public void onPingChange(ProxiedPlayer player, int ping);
void onPingChange(int ping);
/**
* Called when a player disconnects.
*
* @param player the disconnected player
*/
public void onDisconnect(ProxiedPlayer player);
void onDisconnect();
/**
* Called when a list update packet is sent from server to client.
@@ -44,5 +51,5 @@ public interface TabListHandler
* @param ping ping of the subject player
* @return whether to send the packet to the client
*/
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping);
boolean onListUpdate(String name, boolean online, int ping);
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

97
bootstrap/pom.xml Normal file
View File

@@ -0,0 +1,97 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Bootstrap</name>
<description>Java 1.6 loader for BungeeCord</description>
<dependencies>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
<version>4.5</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>BungeeCord</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<!-- Don't deploy proxy to maven repo, only APIs -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>net.md_5.bungee.Bootstrap</Main-Class>
<Implementation-Version>${describe}</Implementation-Version>
<Specification-Version>${maven.build.timestamp}</Specification-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.SF</exclude>
<exclude>**/*.DSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,81 @@
package net.md_5.bungee;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.command.ConsoleCommandSender;
public class Bootstrap
{
private static List<String> list(String... params)
{
return Arrays.asList( params );
}
/**
* Starts a new instance of BungeeCord.
*
* @param args command line arguments, currently none are used
* @throws Exception when the server cannot be started
*/
public static void main(String[] args) throws Exception
{
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
parser.acceptsAll( list( "v", "version" ) );
OptionSet options = parser.parse( args );
if ( options.has( "version" ) )
{
System.out.println( Bootstrap.class.getPackage().getImplementationVersion() );
return;
}
if ( !System.getProperty( "java.version" ).startsWith( "1.7" ) )
{
System.err.println( "*** ERROR *** BungeeCord requires Java 7 to function!" );
return;
}
if ( BungeeCord.class.getPackage().getSpecificationVersion() != null )
{
Calendar deadline = Calendar.getInstance();
deadline.add( Calendar.WEEK_OF_YEAR, 2 );
if ( Calendar.getInstance().after( new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() ) ) )
{
System.err.println( "*** Warning, this build is outdated ***" );
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
System.err.println( "*** You will get NO support regarding this build ***" );
System.err.println( "*** Server will start in 30 seconds ***" );
Thread.sleep( TimeUnit.SECONDS.toMillis( 30 ) );
}
}
System.setProperty( "java.net.preferIPv4Stack", "true" );
BungeeCord bungee = new BungeeCord();
ProxyServer.setInstance( bungee );
bungee.getLogger().info( "Enabled BungeeCord version " + bungee.getVersion() );
bungee.start();
while ( bungee.isRunning )
{
String line = bungee.getConsoleReader().readLine( ">" );
if ( line != null )
{
if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
{
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

View File

@@ -6,29 +6,24 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Config</name>
<description>Generic java configuration API intended for use with BungeeCord</description>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.11</version>
<version>1.13</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -2,7 +2,7 @@ package net.md_5.bungee.config;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
@@ -13,36 +13,53 @@ public final class Configuration
{
private static final char SEPARATOR = '.';
private final Map<String, Object> self;
private Map<String, Object> comments = new HashMap<>();
final Map<String, Object> self;
private final Configuration defaults;
private Map<String, Object> getHolder(String path, Map<String, Object> parent, boolean create)
{
return null;
}
private Object get(String path, Map<String, Object> holder)
private Configuration getSectionFor(String path)
{
int index = path.indexOf( SEPARATOR );
String first, second;
if ( index == -1 )
{
second = path;
} else
{
first = path.substring( 0, index );
second = path.substring( index + 1, path.length() );
return this;
}
return null;
String root = path.substring( 0, index );
Object section = self.get( root );
if ( section == null )
{
section = new LinkedHashMap<>();
self.put( root, section );
}
if ( section instanceof Configuration )
{
return (Configuration) section;
}
return new Configuration( (Map) section, ( defaults == null ) ? null : defaults.getSectionFor( path ) );
}
private String getChild(String path)
{
int index = path.indexOf( SEPARATOR );
return ( index == -1 ) ? path : path.substring( index + 1 );
}
/*------------------------------------------------------------------------*/
@SuppressWarnings("unchecked")
public <T> T get(String path, T def)
{
Object val = get( path, self );
return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) defaults.get( path );
Configuration section = getSectionFor( path );
Object val;
if ( section == this )
{
val = self.get( path );
} else
{
val = section.get( getChild( path ), def );
}
return ( val != null ) ? (T) val : def;
}
public Object get(String path)
@@ -52,19 +69,26 @@ public final class Configuration
public Object getDefault(String path)
{
return defaults.get( path );
}
public void set(String path, Object value, String comment)
{
String child = path.substring( path.indexOf( SEPARATOR ) + 1 );
getHolder( path, self, true ).put( child, value );
getHolder( path, comments, true ).put( child, value );
return ( defaults == null ) ? null : defaults.get( path );
}
public void set(String path, Object value)
{
set( path, value, null );
Configuration section = getSectionFor( path );
if ( section == this )
{
self.put( path, value );
} else
{
section.set( getChild( path ), value );
}
}
/*------------------------------------------------------------------------*/
public Configuration getSection(String path)
{
Object def = getDefault( path );
return new Configuration( (Map) ( get( path, ( def instanceof Map ) ? def : Collections.EMPTY_MAP ) ), ( defaults == null ) ? null : defaults.getSection( path ) );
}
/*------------------------------------------------------------------------*/

View File

@@ -1,7 +1,9 @@
package net.md_5.bungee.config;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
@@ -15,13 +17,17 @@ public abstract class ConfigurationProvider
providers.put( YamlConfiguration.class, new YamlConfiguration() );
}
public ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
public static ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
{
return providers.get( provider );
}
/*------------------------------------------------------------------------*/
public abstract Configuration load(File file);
public abstract void save(Configuration config, File file) throws IOException;
public abstract void save(Configuration config, Writer writer);
public abstract Configuration load(File file) throws IOException;
public abstract Configuration load(Reader reader);

View File

@@ -1,14 +1,18 @@
package net.md_5.bungee.config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class YamlConfiguration extends ConfigurationProvider
{
@@ -24,14 +28,26 @@ public class YamlConfiguration extends ConfigurationProvider
};
@Override
public Configuration load(File file)
public void save(Configuration config, File file) throws IOException
{
try ( FileWriter writer = new FileWriter( file ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
yaml.get().dump( config.self, writer );
}
@Override
public Configuration load(File file) throws IOException
{
try ( FileReader reader = new FileReader( file ) )
{
return load( reader );
} catch ( IOException ex )
{
return null;
}
}

View File

@@ -0,0 +1,61 @@
package net.md_5.bungee.config;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
public class YamlConfigurationTest
{
private String docuement = ""
+ "receipt: Oz-Ware Purchase Invoice\n"
+ "date: 2012-08-06\n"
+ "customer:\n"
+ " given: Dorothy\n"
+ " family: Gale\n"
+ "\n"
+ "items:\n"
+ " - part_no: A4786\n"
+ " descrip: Water Bucket (Filled)\n"
+ " price: 1.47\n"
+ " quantity: 4\n"
+ "\n"
+ " - part_no: E1628\n"
+ " descrip: High Heeled \"Ruby\" Slippers\n"
+ " size: 8\n"
+ " price: 100.27\n"
+ " quantity: 1\n"
+ "\n"
+ "bill-to: &id001\n"
+ " street: |\n"
+ " 123 Tornado Alley\n"
+ " Suite 16\n"
+ " city: East Centerville\n"
+ " state: KS\n"
+ "\n"
+ "ship-to: *id001\n"
+ "\n"
+ "specialDelivery: >\n"
+ " Follow the Yellow Brick\n"
+ " Road to the Emerald City.\n"
+ " Pay no attention to the\n"
+ " man behind the curtain.";
@Test
public void testRead() throws Exception
{
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( docuement );
Assert.assertEquals( "receipt", "Oz-Ware Purchase Invoice", conf.getString( "receipt" ) );
// Assert.assertEquals( "date", "2012-08-06", conf.get( "date" ).toString() );
Configuration customer = conf.getSection( "customer" );
Assert.assertEquals( "customer.given", "Dorothy", customer.getString( "given" ) );
Assert.assertEquals( "customer.given", "Dorothy", conf.getString( "customer.given" ) );
List items = conf.getList( "items" );
Map item = (Map) items.get( 0 );
Assert.assertEquals( "items[0].part_no", "A4786", item.get( "part_no" ) );
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

20
event/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Event</name>
<description>Generic java event dispatching API intended for use with BungeeCord</description>
</project>

View File

@@ -0,0 +1,202 @@
package net.md_5.bungee.event;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
public class EventBus
{
private final Map<Class<?>, Map<Byte, Map<Object, Method[]>>> byListenerAndPriority = new HashMap<>();
private final Map<Class<?>, EventHandlerMethod[]> byEventBaked = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Logger logger;
public EventBus()
{
this( null );
}
public EventBus(Logger logger)
{
this.logger = ( logger == null ) ? Logger.getGlobal() : logger;
}
public void post(Object event)
{
lock.readLock().lock();
try
{
EventHandlerMethod[] handlers = byEventBaked.get( event.getClass() );
if ( handlers != null )
{
for ( EventHandlerMethod method : handlers )
{
try
{
method.invoke( event );
} catch ( IllegalAccessException ex )
{
throw new Error( "Method became inaccessible: " + event, ex );
} catch ( IllegalArgumentException ex )
{
throw new Error( "Method rejected target/argument: " + event, ex );
} catch ( InvocationTargetException ex )
{
logger.log( Level.WARNING, MessageFormat.format( "Error dispatching event {0} to listener {1}", event, method.getListener() ), ex.getCause() );
}
}
}
} finally
{
lock.readLock().unlock();
}
}
private Map<Class<?>, Map<Byte, Set<Method>>> findHandlers(Object listener)
{
Map<Class<?>, Map<Byte, Set<Method>>> handler = new HashMap<>();
for ( Method m : listener.getClass().getDeclaredMethods() )
{
EventHandler annotation = m.getAnnotation( EventHandler.class );
if ( annotation != null )
{
Class<?>[] params = m.getParameterTypes();
if ( params.length != 1 )
{
logger.log( Level.INFO, "Method {0} in class {1} annotated with {2} does not have single argument", new Object[]
{
m, listener.getClass(), annotation
} );
continue;
}
Map<Byte, Set<Method>> prioritiesMap = handler.get( params[0] );
if ( prioritiesMap == null )
{
prioritiesMap = new HashMap<>();
handler.put( params[0], prioritiesMap );
}
Set<Method> priority = prioritiesMap.get( annotation.priority() );
if ( priority == null )
{
priority = new HashSet<>();
prioritiesMap.put( annotation.priority(), priority );
}
priority.add( m );
}
}
return handler;
}
public void register(Object listener)
{
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
lock.writeLock().lock();
try
{
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
{
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.get( e.getKey() );
if ( prioritiesMap == null )
{
prioritiesMap = new HashMap<>();
byListenerAndPriority.put( e.getKey(), prioritiesMap );
}
for ( Map.Entry<Byte, Set<Method>> entry : e.getValue().entrySet() )
{
Map<Object, Method[]> currentPriorityMap = prioritiesMap.get( entry.getKey() );
if ( currentPriorityMap == null )
{
currentPriorityMap = new HashMap<>();
prioritiesMap.put( entry.getKey(), currentPriorityMap );
}
Method[] baked = new Method[ entry.getValue().size() ];
currentPriorityMap.put( listener, entry.getValue().toArray( baked ) );
}
bakeHandlers( e.getKey() );
}
} finally
{
lock.writeLock().unlock();
}
}
public void unregister(Object listener)
{
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
lock.writeLock().lock();
try
{
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
{
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.get( e.getKey() );
if ( prioritiesMap != null )
{
for ( Byte priority : e.getValue().keySet() )
{
Map<Object, Method[]> currentPriority = prioritiesMap.get( priority );
if ( currentPriority != null )
{
currentPriority.remove( listener );
if ( currentPriority.isEmpty() )
{
prioritiesMap.remove( priority );
}
}
}
if ( prioritiesMap.isEmpty() )
{
byListenerAndPriority.remove( e.getKey() );
}
}
bakeHandlers( e.getKey() );
}
} finally
{
lock.writeLock().unlock();
}
}
/**
* Shouldn't be called without first locking the writeLock; intended for use
* only inside {@link #register(java.lang.Object) register(Object)} or
* {@link #unregister(java.lang.Object) unregister(Object)}.
*/
private void bakeHandlers(Class<?> eventClass)
{
Map<Byte, Map<Object, Method[]>> handlersByPriority = byListenerAndPriority.get( eventClass );
if ( handlersByPriority != null )
{
List<EventHandlerMethod> handlersList = new ArrayList<>( handlersByPriority.size() * 2 );
for ( byte value = Byte.MIN_VALUE; value < Byte.MAX_VALUE; value++ )
{
Map<Object, Method[]> handlersByListener = handlersByPriority.get( value );
if ( handlersByListener != null )
{
for ( Map.Entry<Object, Method[]> listenerHandlers : handlersByListener.entrySet() )
{
for ( Method method : listenerHandlers.getValue() )
{
EventHandlerMethod ehm = new EventHandlerMethod( listenerHandlers.getKey(), method );
handlersList.add( ehm );
}
}
}
}
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) );
} else
{
byEventBaked.put( eventClass, null );
}
}
}

View File

@@ -0,0 +1,26 @@
package net.md_5.bungee.event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface EventHandler
{
/**
* Define the priority of the event handler.
* <p>
* Event handlers are called in order of priority:
* <ol>
* <li>LOWEST</li>
* <li>LOW</li>
* <li>NORMAL</li>
* <li>HIGH</li>
* <li>HIGHEST</li>
* </ol>
*/
byte priority() default EventPriority.NORMAL;
}

View File

@@ -0,0 +1,21 @@
package net.md_5.bungee.event;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public class EventHandlerMethod
{
@Getter
private final Object listener;
@Getter
private final Method method;
public void invoke(Object event) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
method.invoke( listener, event );
}
}

View File

@@ -0,0 +1,19 @@
package net.md_5.bungee.event;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* Importance of the {@link EventHandler}. When executing an Event, the handlers
* are called in order of their Priority.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class EventPriority
{
public static final byte LOWEST = -64;
public static final byte LOW = -32;
public static final byte NORMAL = 0;
public static final byte HIGH = 32;
public static final byte HIGHEST = 64;
}

View File

@@ -0,0 +1,42 @@
package net.md_5.bungee.event;
import java.util.concurrent.CountDownLatch;
import org.junit.Assert;
import org.junit.Test;
public class EventBusTest
{
private final EventBus bus = new EventBus();
private final CountDownLatch latch = new CountDownLatch( 2 );
@Test
public void testNestedEvents()
{
bus.register( this );
bus.post( new FirstEvent() );
Assert.assertEquals( 0, latch.getCount() );
}
@EventHandler
public void firstListener(FirstEvent event)
{
bus.post( new SecondEvent() );
Assert.assertEquals( 1, latch.getCount() );
latch.countDown();
}
@EventHandler
public void secondListener(SecondEvent event)
{
latch.countDown();
}
public static class FirstEvent
{
}
public static class SecondEvent
{
}
}

View File

@@ -0,0 +1,64 @@
package net.md_5.bungee.event;
import java.util.concurrent.CountDownLatch;
import org.junit.Assert;
import org.junit.Test;
public class EventPriorityTest
{
private final EventBus bus = new EventBus();
private final CountDownLatch latch = new CountDownLatch( 5 );
@Test
public void testPriority()
{
bus.register( this );
bus.register( new EventPriorityListenerPartner() );
bus.post( new PriorityTestEvent() );
Assert.assertEquals( 0, latch.getCount() );
}
@EventHandler(priority = EventPriority.LOWEST)
public void onLowestPriority(PriorityTestEvent event)
{
Assert.assertEquals( 5, latch.getCount() );
latch.countDown();
}
@EventHandler
public void onNormalPriority(PriorityTestEvent event)
{
Assert.assertEquals( 3, latch.getCount() );
latch.countDown();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onHighestPriority(PriorityTestEvent event)
{
Assert.assertEquals( 1, latch.getCount() );
latch.countDown();
}
public static class PriorityTestEvent
{
}
public class EventPriorityListenerPartner
{
@EventHandler(priority = EventPriority.HIGH)
public void onHighPriority(PriorityTestEvent event)
{
Assert.assertEquals( 2, latch.getCount() );
latch.countDown();
}
@EventHandler(priority = EventPriority.LOW)
public void onLowPriority(PriorityTestEvent event)
{
Assert.assertEquals( 4, latch.getCount() );
latch.countDown();
}
}
}

View File

@@ -0,0 +1,28 @@
package net.md_5.bungee.event;
import org.junit.Assert;
import org.junit.Test;
public class UnregisteringListenerTest
{
private final EventBus bus = new EventBus();
@Test
public void testPriority()
{
bus.register( this );
bus.unregister( this );
bus.post( new TestEvent() );
}
@EventHandler
public void onEvent(TestEvent evt)
{
Assert.fail( "Event listener wasn't unregistered" );
}
public static class TestEvent
{
}
}

31
nb-configuration.xml Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

31
pom.xml
View File

@@ -11,16 +11,16 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord</name>
<description>Parent project for all BungeeCord modules.</description>
<url>https://github.com/ElasticPortalSuite/BungeeCord</url>
<url>https://github.com/SpigotMC/BungeeCord</url>
<inceptionYear>2012</inceptionYear>
<organization>
<name>Elastic Portal Suite</name>
<url>https://github.com/ElasticPortalSuite</url>
<url>https://github.com/SpigotMC</url>
</organization>
<licenses>
<license>
@@ -38,18 +38,22 @@
<modules>
<module>api</module>
<module>bootstrap</module>
<module>config</module>
<module>event</module>
<module>protocol</module>
<module>proxy</module>
<module>query</module>
</modules>
<scm>
<connection>scm:git:git@github.com:ElasticPortalSuite/BungeeCord.git</connection>
<developerConnection>scm:git:git@github.com:ElasticPortalSuite/BungeeCord.git</developerConnection>
<url>git@github.com:ElasticPortalSuite/BungeeCord.git</url>
<connection>scm:git:git@github.com:SpigotMC/BungeeCord.git</connection>
<developerConnection>scm:git:git@github.com:SpigotMC/BungeeCord.git</developerConnection>
<url>git@github.com:SpigotMC/BungeeCord.git</url>
</scm>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/ElasticPortalSuite/BungeeCord/issues</url>
<url>https://github.com/SpigotMC/BungeeCord/issues</url>
</issueManagement>
<ciManagement>
<system>jenkins</system>
@@ -57,15 +61,22 @@
</ciManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<build.number>unknown</build.number>
<netty.version>4.0.9.Final</netty.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.11.6</version>
<version>0.12.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -92,7 +103,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

View File

@@ -6,15 +6,24 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId>
<version>1.4.7-SNAPSHOT</version>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Protocol</name>
<description>Minimal implementation of the Minecraft protocol for use in BungeeCord</description>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,10 @@
package net.md_5.bungee.protocol;
public class BadPacketException extends RuntimeException
{
public BadPacketException(String message)
{
super( message );
}
}

View File

@@ -0,0 +1,33 @@
package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import net.md_5.bungee.protocol.packet.DefinedPacket;
import net.md_5.bungee.protocol.packet.forge.Forge1Login;
import net.md_5.bungee.protocol.skip.PacketReader;
public class Forge extends Vanilla
{
@Getter
private static final Forge instance = new Forge();
public Forge()
{
classes[0x01] = Forge1Login.class;
skipper = new PacketReader( this ); // TODO: :(
}
@Override
public DefinedPacket read(short packetId, ByteBuf buf)
{
int start = buf.readerIndex();
DefinedPacket packet = read( packetId, buf, this );
if ( buf.readerIndex() == start )
{
packet = super.read( packetId, buf );
}
return packet;
}
}

View File

@@ -0,0 +1,38 @@
package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class MinecraftInput
{
private final ByteBuf buf;
public byte readByte()
{
return buf.readByte();
}
public short readUnisgnedByte()
{
return buf.readUnsignedByte();
}
public int readInt()
{
return buf.readInt();
}
public String readString()
{
short len = buf.readShort();
char[] c = new char[ len ];
for ( int i = 0; i < c.length; i++ )
{
c[i] = buf.readChar();
}
return new String( c );
}
}

View File

@@ -0,0 +1,56 @@
package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.Charset;
import java.util.Arrays;
public class MinecraftOutput
{
private final ByteBuf buf;
public MinecraftOutput()
{
buf = Unpooled.buffer();
}
public byte[] toArray()
{
if ( buf.hasArray() )
{
return Arrays.copyOfRange( buf.array(), buf.arrayOffset(), buf.arrayOffset() + buf.writerIndex() );
} else
{
byte[] b = new byte[ buf.writerIndex() ];
buf.readBytes( b );
return b;
}
}
public MinecraftOutput writeByte(byte b)
{
buf.writeByte( b );
return this;
}
public void writeInt(int i)
{
buf.writeInt( i );
}
public void writeString(String s)
{
char[] cc = s.toCharArray();
buf.writeShort( cc.length );
for ( char c : cc )
{
buf.writeChar( c );
}
}
public void writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket(String s)
{
buf.writeBytes( s.getBytes( Charset.forName( "UTF-8" ) ) );
}
}

View File

@@ -0,0 +1,7 @@
package net.md_5.bungee.protocol;
public enum OpCode
{
BOOLEAN, BULK_CHUNK, BYTE, BYTE_INT, DOUBLE, FLOAT, INT, INT_3, INT_BYTE, ITEM, LONG, METADATA, OPTIONAL_MOTION, SHORT, SHORT_BYTE, SHORT_ITEM, STRING, USHORT_BYTE, OPTIONAL_WINDOW
}

View File

@@ -0,0 +1,20 @@
package net.md_5.bungee.protocol;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Constructor;
import net.md_5.bungee.protocol.packet.DefinedPacket;
import net.md_5.bungee.protocol.skip.PacketReader;
public interface Protocol
{
PacketReader getSkipper();
DefinedPacket read(short packetId, ByteBuf buf);
OpCode[][] getOpCodes();
Class<? extends DefinedPacket>[] getClasses();
Constructor<? extends DefinedPacket>[] getConstructors();
}

View File

@@ -1,39 +1,131 @@
package net.md_5.mendax;
package net.md_5.bungee.protocol;
import static net.md_5.mendax.PacketDefinitions.OpCode.*;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import lombok.Getter;
import static net.md_5.bungee.protocol.OpCode.*;
import net.md_5.bungee.protocol.packet.DefinedPacket;
import net.md_5.bungee.protocol.packet.Packet0KeepAlive;
import net.md_5.bungee.protocol.packet.Packet1Login;
import net.md_5.bungee.protocol.packet.Packet2CEntityProperties;
import net.md_5.bungee.protocol.packet.Packet2Handshake;
import net.md_5.bungee.protocol.packet.Packet3Chat;
import net.md_5.bungee.protocol.packet.Packet9Respawn;
import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
import net.md_5.bungee.protocol.packet.PacketCBTabComplete;
import net.md_5.bungee.protocol.packet.PacketCCSettings;
import net.md_5.bungee.protocol.packet.PacketCDClientStatus;
import net.md_5.bungee.protocol.packet.PacketCEScoreboardObjective;
import net.md_5.bungee.protocol.packet.PacketCFScoreboardScore;
import net.md_5.bungee.protocol.packet.PacketD0DisplayScoreboard;
import net.md_5.bungee.protocol.packet.PacketD1Team;
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.protocol.packet.PacketFEPing;
import net.md_5.bungee.protocol.packet.PacketFFKick;
import net.md_5.bungee.protocol.skip.PacketReader;
public class PacketDefinitions
public class Vanilla implements Protocol
{
private static final int MAX_PACKET = 256;
public static final OpCode[][] opCodes = new OpCode[ MAX_PACKET * 2 ][];
public static final int VANILLA_PROTOCOL = 0;
public static final int FORGE_PROTOCOL = MAX_PACKET;
public static final byte PROTOCOL_VERSION = 78;
public static final String GAME_VERSION = "1.6.4";
@Getter
private static final Vanilla instance = new Vanilla();
/*========================================================================*/
@Getter
private final OpCode[][] opCodes = new OpCode[ 256 ][];
@SuppressWarnings("unchecked")
@Getter
protected Class<? extends DefinedPacket>[] classes = new Class[ 256 ];
@SuppressWarnings("unchecked")
@Getter
private Constructor<? extends DefinedPacket>[] constructors = new Constructor[ 256 ];
@Getter
protected PacketReader skipper;
/*========================================================================*/
public enum OpCode
public Vanilla()
{
BOOLEAN, BULK_CHUNK, BYTE, BYTE_INT, DOUBLE, FLOAT, INT, INT_3, INT_BYTE, ITEM, LONG, METADATA, OPTIONAL_MOTION, SHORT, SHORT_BYTE, SHORT_ITEM, STRING, USHORT_BYTE
classes[0x00] = Packet0KeepAlive.class;
classes[0x01] = Packet1Login.class;
classes[0x02] = Packet2Handshake.class;
classes[0x03] = Packet3Chat.class;
classes[0x09] = Packet9Respawn.class;
classes[0xC9] = PacketC9PlayerListItem.class;
classes[0x2C] = Packet2CEntityProperties.class;
classes[0xCC] = PacketCCSettings.class;
classes[0xCB] = PacketCBTabComplete.class;
classes[0xCD] = PacketCDClientStatus.class;
classes[0xCE] = PacketCEScoreboardObjective.class;
classes[0xCF] = PacketCFScoreboardScore.class;
classes[0xD0] = PacketD0DisplayScoreboard.class;
classes[0xD1] = PacketD1Team.class;
classes[0xFA] = PacketFAPluginMessage.class;
classes[0xFC] = PacketFCEncryptionResponse.class;
classes[0xFD] = PacketFDEncryptionRequest.class;
classes[0xFE] = PacketFEPing.class;
classes[0xFF] = PacketFFKick.class;
skipper = new PacketReader( this );
}
static
@Override
public DefinedPacket read(short packetId, ByteBuf buf)
{
opCodes[0x00] = new OpCode[]
int start = buf.readerIndex();
DefinedPacket packet = read( packetId, buf, this );
if ( buf.readerIndex() == start )
{
INT
};
opCodes[0x01] = new OpCode[]
throw new BadPacketException( "Unknown packet id " + packetId );
}
return packet;
}
public static DefinedPacket read(short id, ByteBuf buf, Protocol protocol)
{
DefinedPacket packet = packet( id, protocol );
if ( packet != null )
{
INT, STRING, BYTE, BYTE, BYTE, BYTE, BYTE
};
opCodes[0x02] = new OpCode[]
packet.read( buf );
return packet;
}
protocol.getSkipper().tryRead( id, buf );
return null;
}
public static DefinedPacket packet(short id, Protocol protocol)
{
DefinedPacket ret = null;
Class<? extends DefinedPacket> clazz = protocol.getClasses()[id];
if ( clazz != null )
{
BYTE, STRING, STRING, INT
};
opCodes[0x03] = new OpCode[]
{
STRING
};
try
{
Constructor<? extends DefinedPacket> constructor = protocol.getConstructors()[id];
if ( constructor == null )
{
constructor = clazz.getDeclaredConstructor();
constructor.setAccessible( true );
protocol.getConstructors()[id] = constructor;
}
if ( constructor != null )
{
ret = constructor.newInstance();
}
} catch ( NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex )
{
}
}
return ret;
}
{
opCodes[0x04] = new OpCode[]
{
LONG, LONG
@@ -52,11 +144,7 @@ public class PacketDefinitions
};
opCodes[0x08] = new OpCode[]
{
SHORT, SHORT, FLOAT
};
opCodes[0x09] = new OpCode[]
{
INT, BYTE, BYTE, SHORT, STRING
FLOAT, SHORT, FLOAT
};
opCodes[0x0A] = new OpCode[]
{
@@ -96,7 +184,7 @@ public class PacketDefinitions
};
opCodes[0x13] = new OpCode[]
{
INT, BYTE
INT, BYTE, INT
};
opCodes[0x14] = new OpCode[]
{
@@ -122,6 +210,10 @@ public class PacketDefinitions
{
INT, INT, INT, INT, SHORT
};
opCodes[0x1B] = new OpCode[]
{
FLOAT, FLOAT, BOOLEAN, BOOLEAN
};
opCodes[0x1C] = new OpCode[]
{
INT, SHORT, SHORT, SHORT
@@ -160,7 +252,7 @@ public class PacketDefinitions
};
opCodes[0x27] = new OpCode[]
{
INT, INT
INT, INT, BOOLEAN
};
opCodes[0x28] = new OpCode[]
{
@@ -214,6 +306,10 @@ public class PacketDefinitions
{
STRING, INT, INT, INT, FLOAT, BYTE
};
opCodes[0x3F] = new OpCode[]
{
STRING, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, INT
};
opCodes[0x46] = new OpCode[]
{
BYTE, BYTE
@@ -224,7 +320,7 @@ public class PacketDefinitions
};
opCodes[0x64] = new OpCode[]
{
BYTE, BYTE, STRING, BYTE
OPTIONAL_WINDOW
};
opCodes[0x65] = new OpCode[]
{
@@ -270,57 +366,21 @@ public class PacketDefinitions
{
INT, SHORT, INT, BYTE, SHORT_BYTE
};
opCodes[0x85] = new OpCode[]
{
BYTE, INT, INT, INT
};
opCodes[0xC3] = new OpCode[]
{
SHORT, SHORT, INT_BYTE
};
opCodes[0xC8] = new OpCode[]
{
INT, BYTE
};
opCodes[0xC9] = new OpCode[]
{
STRING, BOOLEAN, SHORT
INT, INT
};
opCodes[0xCA] = new OpCode[]
{
BYTE, BYTE, BYTE
};
opCodes[0xCB] = new OpCode[]
{
STRING
};
opCodes[0xCC] = new OpCode[]
{
STRING, BYTE, BYTE, BYTE, BOOLEAN
};
opCodes[0xCD] = new OpCode[]
{
BYTE
};
opCodes[0xFA] = new OpCode[]
{
STRING, SHORT_BYTE
};
opCodes[0xFC] = new OpCode[]
{
SHORT_BYTE, SHORT_BYTE
};
opCodes[0xFD] = new OpCode[]
{
STRING, SHORT_BYTE, SHORT_BYTE
};
opCodes[0xFE] = new OpCode[]
{
}; // Should be byte, screw you too bitchy server admins!
opCodes[0xFF] = new OpCode[]
{
STRING
};
/*========================== Minecraft Forge ===========================*/
opCodes[0x01 + FORGE_PROTOCOL] = new OpCode[]
{
INT, STRING, BYTE, INT, BYTE, BYTE, BYTE
BYTE, FLOAT, FLOAT
};
}
}

View File

@@ -1,70 +1,81 @@
package net.md_5.bungee.packet;
package net.md_5.bungee.protocol.packet;
public abstract class PacketHandler
public abstract class AbstractPacketHandler
{
private void nop(DefinedPacket packet)
{
throw new UnsupportedOperationException( "No handler defined for packet " + packet.getClass() );
}
public void handle(Packet0KeepAlive alive) throws Exception
{
nop( alive );
}
public void handle(Packet1Login login) throws Exception
{
nop( login );
}
public void handle(Packet2Handshake handshake) throws Exception
{
nop( handshake );
}
public void handle(Packet3Chat chat) throws Exception
{
nop( chat );
}
public void handle(Packet9Respawn respawn) throws Exception
{
nop( respawn );
}
public void handle(Packet2CEntityProperties properties) throws Exception
{
}
public void handle(PacketC9PlayerListItem playerList) throws Exception
{
nop( playerList );
}
public void handle(PacketCCSettings settings) throws Exception
{
}
public void handle(PacketCDClientStatus clientStatus) throws Exception
{
nop( clientStatus );
}
public void handle(PacketCEScoreboardObjective objective) throws Exception
{
}
public void handle(PacketCFScoreboardScore score) throws Exception
{
}
public void handle(PacketD0DisplayScoreboard displayScoreboard) throws Exception
{
}
public void handle(PacketD1Team team) throws Exception
{
}
public void handle(PacketFAPluginMessage pluginMessage) throws Exception
{
nop( pluginMessage );
}
public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception
{
nop( encryptResponse );
}
public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception
{
nop( encryptRequest );
}
public void handle(PacketFEPing ping) throws Exception
{
nop( ping );
}
public void handle(PacketFFKick kick) throws Exception
{
nop( kick );
}
public void handle(PacketCBTabComplete tabComplete) throws Exception
{
}
}

View File

@@ -0,0 +1,69 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public abstract class DefinedPacket
{
private final int id;
public final int getId()
{
return id;
}
public void writeString(String s, ByteBuf buf)
{
// TODO: Check len - use Guava?
buf.writeShort( s.length() );
for ( char c : s.toCharArray() )
{
buf.writeChar( c );
}
}
public String readString(ByteBuf buf)
{
// TODO: Check len - use Guava?
short len = buf.readShort();
char[] chars = new char[ len ];
for ( int i = 0; i < len; i++ )
{
chars[i] = buf.readChar();
}
return new String( chars );
}
public void writeArray(byte[] b, ByteBuf buf)
{
// TODO: Check len - use Guava?
buf.writeShort( b.length );
buf.writeBytes( b );
}
public byte[] readArray(ByteBuf buf)
{
// TODO: Check len - use Guava?
short len = buf.readShort();
byte[] ret = new byte[ len ];
buf.readBytes( ret );
return ret;
}
public abstract void read(ByteBuf buf);
public abstract void write(ByteBuf buf);
public abstract void handle(AbstractPacketHandler handler) throws Exception;
@Override
public abstract boolean equals(Object obj);
@Override
public abstract int hashCode();
@Override
public abstract String toString();
}

View File

@@ -0,0 +1,38 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet0KeepAlive extends DefinedPacket
{
private int randomId;
private Packet0KeepAlive()
{
super( 0x00 );
}
@Override
public void read(ByteBuf buf)
{
randomId = buf.readInt();
}
@Override
public void write(ByteBuf buf)
{
buf.writeInt( randomId );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,73 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet1Login extends DefinedPacket
{
protected int entityId;
protected String levelType;
protected byte gameMode;
protected int dimension;
protected byte difficulty;
protected byte unused;
protected byte maxPlayers;
protected Packet1Login()
{
super( 0x01 );
}
public Packet1Login(int entityId, String levelType, byte gameMode, byte dimension, byte difficulty, byte unused, byte maxPlayers)
{
this( entityId, levelType, gameMode, (int) dimension, difficulty, unused, maxPlayers );
}
public Packet1Login(int entityId, String levelType, byte gameMode, int dimension, byte difficulty, byte unused, byte maxPlayers)
{
this();
this.entityId = entityId;
this.levelType = levelType;
this.gameMode = gameMode;
this.dimension = dimension;
this.difficulty = difficulty;
this.unused = unused;
this.maxPlayers = maxPlayers;
}
@Override
public void read(ByteBuf buf)
{
entityId = buf.readInt();
levelType = readString( buf );
gameMode = buf.readByte();
dimension = buf.readByte();
difficulty = buf.readByte();
unused = buf.readByte();
maxPlayers = buf.readByte();
}
@Override
public void write(ByteBuf buf)
{
buf.writeInt( entityId );
writeString( levelType, buf );
buf.writeByte( gameMode );
buf.writeByte( dimension );
buf.writeByte( difficulty );
buf.writeByte( unused );
buf.writeByte( maxPlayers );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,47 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet2CEntityProperties extends DefinedPacket
{
public Packet2CEntityProperties()
{
super( 0x2C );
}
@Override
public void read(ByteBuf buf)
{
buf.readInt();
int recordCount = buf.readInt();
for ( int i = 0; i < recordCount; i++ )
{
readString( buf );
buf.readDouble();
short size = buf.readShort();
for ( short s = 0; s < size; s++ )
{
buf.skipBytes( 25 ); // long, long, double, byte
}
}
}
@Override
public void write(ByteBuf buf)
{
throw new UnsupportedOperationException();
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,49 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet2Handshake extends DefinedPacket
{
private byte protocolVersion;
private String username;
private String host;
private int port;
private Packet2Handshake()
{
super( 0x02 );
}
@Override
public void read(ByteBuf buf)
{
protocolVersion = buf.readByte();
username = readString( buf );
host = readString( buf );
port = buf.readInt();
}
@Override
public void write(ByteBuf buf)
{
buf.writeByte( protocolVersion );
writeString( username, buf );
writeString( host, buf );
buf.writeInt( port );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,46 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet3Chat extends DefinedPacket
{
private String message;
private Packet3Chat()
{
super( 0x03 );
}
public Packet3Chat(String message)
{
this();
this.message = message;
}
@Override
public void read(ByteBuf buf)
{
message = readString( buf );
}
@Override
public void write(ByteBuf buf)
{
writeString( message, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,58 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString
@EqualsAndHashCode(callSuper = false)
public class Packet9Respawn extends DefinedPacket
{
private int dimension;
private byte difficulty;
private byte gameMode;
private short worldHeight;
private String levelType;
private Packet9Respawn()
{
super( 0x09 );
}
public Packet9Respawn(int dimension, byte difficulty, byte gameMode, short worldHeight, String levelType)
{
this();
this.dimension = dimension;
this.difficulty = difficulty;
this.gameMode = gameMode;
this.worldHeight = worldHeight;
this.levelType = levelType;
}
@Override
public void read(ByteBuf buf)
{
dimension = buf.readInt();
difficulty = buf.readByte();
gameMode = buf.readByte();
worldHeight = buf.readShort();
levelType = readString( buf );
}
@Override
public void write(ByteBuf buf)
{
buf.writeInt( dimension );
buf.writeByte( difficulty );
buf.writeByte( gameMode );
buf.writeShort( worldHeight );
writeString( levelType, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,52 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketC9PlayerListItem extends DefinedPacket
{
private String username;
private boolean online;
private short ping;
private PacketC9PlayerListItem()
{
super( 0xC9 );
}
public PacketC9PlayerListItem(String username, boolean online, short ping)
{
super( 0xC9 );
this.username = username;
this.online = online;
this.ping = ping;
}
@Override
public void read(ByteBuf buf)
{
username = readString( buf );
online = buf.readBoolean();
ping = buf.readShort();
}
@Override
public void write(ByteBuf buf)
{
writeString( username, buf );
buf.writeBoolean( online );
buf.writeShort( ping );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,51 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketCBTabComplete extends DefinedPacket
{
private String cursor;
private String[] commands;
private PacketCBTabComplete()
{
super( 0xCB );
}
public PacketCBTabComplete(String[] alternatives)
{
this();
commands = alternatives;
}
@Override
public void read(ByteBuf buf)
{
cursor = readString( buf );
}
@Override
public void write(ByteBuf buf)
{
StringBuilder tab = new StringBuilder();
for ( String alternative : commands )
{
tab.append( alternative );
tab.append( "\00" );
}
writeString( tab.substring( 0, tab.length() - 1 ), buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,48 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketCCSettings extends DefinedPacket
{
private String locale;
private byte viewDistance;
private byte chatFlags;
private byte difficulty;
private boolean showCape;
private PacketCCSettings()
{
super( 0xCC );
}
@Override
public void read(ByteBuf buf)
{
locale = readString( buf );
viewDistance = buf.readByte();
chatFlags = buf.readByte();
difficulty = buf.readByte();
showCape = buf.readBoolean();
}
@Override
public void write(ByteBuf buf)
{
writeString( locale, buf );
buf.writeByte( viewDistance );
buf.writeByte( chatFlags );
buf.writeByte( difficulty );
buf.writeBoolean( showCape );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,42 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketCDClientStatus extends DefinedPacket
{
private byte payload;
private PacketCDClientStatus()
{
super( 0xCD );
}
public PacketCDClientStatus(byte payload)
{
this();
this.payload = payload;
}
@Override
public void read(ByteBuf buf)
{
payload = buf.readByte();
}
@Override
public void write(ByteBuf buf)
{
buf.writeByte( payload );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,55 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketCEScoreboardObjective extends DefinedPacket
{
private String name;
private String text;
/**
* 0 to create, 1 to remove.
*/
private byte action;
private PacketCEScoreboardObjective()
{
super( 0xCE );
}
public PacketCEScoreboardObjective(String name, String text, byte action)
{
this();
this.name = name;
this.text = text;
this.action = action;
}
@Override
public void read(ByteBuf buf)
{
name = readString( buf );
text = readString( buf );
action = buf.readByte();
}
@Override
public void write(ByteBuf buf)
{
writeString( name, buf );
writeString( text, buf );
buf.writeByte( action );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,56 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketCFScoreboardScore extends DefinedPacket
{
private String itemName;
/**
* 0 = create / update, 1 = remove.
*/
private byte action;
private String scoreName;
private int value;
private PacketCFScoreboardScore()
{
super( 0xCF );
}
@Override
public void read(ByteBuf buf)
{
itemName = readString( buf );
action = buf.readByte();
if ( action != 1 )
{
scoreName = readString( buf );
value = buf.readInt();
}
}
@Override
public void write(ByteBuf buf)
{
writeString( itemName, buf );
buf.writeByte( action );
if ( action != 1 )
{
writeString( scoreName, buf );
buf.writeInt( value );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,44 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketD0DisplayScoreboard extends DefinedPacket
{
/**
* 0 = list, 1 = side, 2 = below.
*/
private byte position;
private String name;
private PacketD0DisplayScoreboard()
{
super( 0xD0 );
}
@Override
public void read(ByteBuf buf)
{
position = buf.readByte();
name = readString( buf );
}
@Override
public void write(ByteBuf buf)
{
buf.writeByte( position );
writeString( name, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,92 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketD1Team extends DefinedPacket
{
private String name;
/**
* 0 - create, 1 remove, 2 info update, 3 player add, 4 player remove.
*/
private byte mode;
private String displayName;
private String prefix;
private String suffix;
private boolean friendlyFire;
private short playerCount;
private String[] players;
private PacketD1Team()
{
super( 0xD1 );
}
/**
* Packet to destroy a team.
*
* @param name
*/
public PacketD1Team(String name)
{
this();
this.name = name;
this.mode = 1;
}
@Override
public void read(ByteBuf buf)
{
name = readString( buf );
mode = buf.readByte();
if ( mode == 0 || mode == 2 )
{
displayName = readString( buf );
prefix = readString( buf );
suffix = readString( buf );
friendlyFire = buf.readBoolean();
}
if ( mode == 0 || mode == 3 || mode == 4 )
{
players = new String[ buf.readShort() ];
for ( int i = 0; i < getPlayers().length; i++ )
{
players[i] = readString( buf );
}
}
}
@Override
public void write(ByteBuf buf)
{
writeString( name, buf );
buf.writeByte( mode );
if ( mode == 0 || mode == 2 )
{
writeString( displayName, buf );
writeString( prefix, buf );
writeString( suffix, buf );
buf.writeBoolean( friendlyFire );
}
if ( mode == 0 || mode == 3 || mode == 4 )
{
buf.writeShort( players.length );
for ( int i = 0; i < players.length; i++ )
{
writeString( players[i], buf );
}
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,64 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.md_5.bungee.protocol.MinecraftInput;
import net.md_5.bungee.protocol.MinecraftOutput;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketFAPluginMessage extends DefinedPacket
{
private String tag;
private byte[] data;
private PacketFAPluginMessage()
{
super( 0xFA );
}
public PacketFAPluginMessage(String tag, byte[] data)
{
this();
this.tag = tag;
this.data = data;
}
@Override
public void read(ByteBuf buf)
{
tag = readString( buf );
data = readArray( buf );
}
@Override
public void write(ByteBuf buf)
{
writeString( tag, buf );
writeArray( data, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
public DataInput getStream()
{
return new DataInputStream( new ByteArrayInputStream( data ) );
}
public MinecraftInput getMCStream()
{
return new MinecraftInput( Unpooled.wrappedBuffer( data ) );
}
}

View File

@@ -0,0 +1,48 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketFCEncryptionResponse extends DefinedPacket
{
private byte[] sharedSecret;
private byte[] verifyToken;
private PacketFCEncryptionResponse()
{
super( 0xFC );
}
public PacketFCEncryptionResponse(byte[] sharedSecret, byte[] verifyToken)
{
this();
this.sharedSecret = sharedSecret;
this.verifyToken = verifyToken;
}
@Override
public void read(ByteBuf buf)
{
sharedSecret = readArray( buf );
verifyToken = readArray( buf );
}
@Override
public void write(ByteBuf buf)
{
writeArray( sharedSecret, buf );
writeArray( verifyToken, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,52 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketFDEncryptionRequest extends DefinedPacket
{
private String serverId;
private byte[] publicKey;
private byte[] verifyToken;
private PacketFDEncryptionRequest()
{
super( 0xFD );
}
public PacketFDEncryptionRequest(String serverId, byte[] publicKey, byte[] verifyToken)
{
this();
this.serverId = serverId;
this.publicKey = publicKey;
this.verifyToken = verifyToken;
}
@Override
public void read(ByteBuf buf)
{
serverId = readString( buf );
publicKey = readArray( buf );
verifyToken = readArray( buf );
}
@Override
public void write(ByteBuf buf)
{
writeString( serverId, buf );
writeArray( publicKey, buf );
writeArray( verifyToken, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,36 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketFEPing extends DefinedPacket
{
private byte version;
private PacketFEPing()
{
super( 0xFE );
}
@Override
public void read(ByteBuf buf)
{
version = buf.readByte();
}
@Override
public void write(ByteBuf buf)
{
buf.writeByte( version );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,44 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
public class PacketFFKick extends DefinedPacket
{
private String message;
private PacketFFKick()
{
super( 0xFF );
}
public PacketFFKick(String message)
{
this();
this.message = message;
}
@Override
public void read(ByteBuf buf)
{
message = readString( buf );
}
@Override
public void write(ByteBuf buf)
{
writeString( message, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,52 @@
package net.md_5.bungee.protocol.packet.forge;
import net.md_5.bungee.protocol.packet.*;
import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@ToString
@EqualsAndHashCode(callSuper = false)
public class Forge1Login extends Packet1Login
{
private Forge1Login()
{
super();
}
public Forge1Login(int entityId, String levelType, byte gameMode, int dimension, byte difficulty, byte unused, byte maxPlayers)
{
super( entityId, levelType, gameMode, dimension, difficulty, unused, maxPlayers );
}
@Override
public void read(ByteBuf buf)
{
entityId = buf.readInt();
levelType = readString( buf );
gameMode = buf.readByte();
dimension = buf.readInt();
difficulty = buf.readByte();
unused = buf.readByte();
maxPlayers = buf.readByte();
}
@Override
public void write(ByteBuf buf)
{
buf.writeInt( entityId );
writeString( levelType, buf );
buf.writeByte( gameMode );
buf.writeInt( dimension );
buf.writeByte( difficulty );
buf.writeByte( unused );
buf.writeByte( maxPlayers );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@@ -0,0 +1,16 @@
package net.md_5.bungee.protocol.skip;
import io.netty.buffer.ByteBuf;
public class BulkChunk extends Instruction
{
@Override
void read(ByteBuf in)
{
short count = in.readShort();
int size = in.readInt();
in.readBoolean();
in.skipBytes( size + count * 12 );
}
}

View File

@@ -1,7 +1,6 @@
package net.md_5.mendax.datainput;
package net.md_5.bungee.protocol.skip;
import java.io.DataInput;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
class ByteHeader extends Instruction
{
@@ -14,12 +13,12 @@ class ByteHeader extends Instruction
}
@Override
void read(DataInput in, byte[] buffer) throws IOException
void read(ByteBuf in)
{
byte size = in.readByte();
for ( byte b = 0; b < size; b++ )
{
child.read( in, buffer );
child.read( in );
}
}
}

View File

@@ -1,7 +1,6 @@
package net.md_5.mendax.datainput;
package net.md_5.bungee.protocol.skip;
import java.io.DataInput;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
abstract class Instruction
{
@@ -24,13 +23,11 @@ abstract class Instruction
static final Instruction SHORT_ITEM = new ShortHeader( ITEM );
static final Instruction STRING = new ShortHeader( new Jump( 2 ) );
static final Instruction USHORT_BYTE = new UnsignedShortByte();
static final Instruction OPTIONAL_WINDOW = new OptionalWindow();
// Illegal forward references below this line
static final Instruction BYTE_INT = new ByteHeader( INT );
// Custom instructions
static final Instruction STRING_ARRAY = new ShortHeader( STRING );
abstract void read(DataInput in, byte[] buffer) throws IOException;
final void skip(DataInput in, byte[] buffer, int len) throws IOException
{
in.readFully( buffer, 0, len );
}
abstract void read(ByteBuf in);
}

View File

@@ -1,7 +1,6 @@
package net.md_5.mendax.datainput;
package net.md_5.bungee.protocol.skip;
import java.io.DataInput;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
class IntHeader extends Instruction
{
@@ -14,12 +13,12 @@ class IntHeader extends Instruction
}
@Override
void read(DataInput in, byte[] buffer) throws IOException
void read(ByteBuf in)
{
int size = in.readInt();
for ( int i = 0; i < size; i++ )
{
child.read( in, buffer );
child.read( in );
}
}
}

View File

@@ -0,0 +1,18 @@
package net.md_5.bungee.protocol.skip;
import io.netty.buffer.ByteBuf;
class Item extends Instruction
{
@Override
void read(ByteBuf in)
{
short type = in.readShort();
if ( type >= 0 )
{
in.skipBytes( 3 );
SHORT_BYTE.read( in );
}
}
}

View File

@@ -1,7 +1,6 @@
package net.md_5.mendax.datainput;
package net.md_5.bungee.protocol.skip;
import java.io.DataInput;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
class Jump extends Instruction
{
@@ -18,8 +17,8 @@ class Jump extends Instruction
}
@Override
void read(DataInput in, byte[] buffer) throws IOException
void read(ByteBuf in)
{
skip( in, buffer, len );
in.skipBytes( len );
}
}

View File

@@ -1,13 +1,12 @@
package net.md_5.mendax.datainput;
package net.md_5.bungee.protocol.skip;
import java.io.DataInput;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
class MetaData extends Instruction
{
@Override
void read(DataInput in, byte[] buffer) throws IOException
void read(ByteBuf in)
{
int x = in.readUnsignedByte();
while ( x != 127 )
@@ -16,25 +15,25 @@ class MetaData extends Instruction
switch ( type )
{
case 0:
BYTE.read( in, buffer );
BYTE.read( in );
break;
case 1:
SHORT.read( in, buffer );
SHORT.read( in );
break;
case 2:
INT.read( in, buffer );
INT.read( in );
break;
case 3:
FLOAT.read( in, buffer );
FLOAT.read( in );
break;
case 4:
STRING.read( in, buffer );
STRING.read( in );
break;
case 5:
ITEM.read( in, buffer );
ITEM.read( in );
break;
case 6:
skip( in, buffer, 12 ); // int, int, int
in.skipBytes( 12 ); // int, int, int
break;
default:
throw new IllegalArgumentException( "Unknown metadata type " + type );

View File

@@ -0,0 +1,17 @@
package net.md_5.bungee.protocol.skip;
import io.netty.buffer.ByteBuf;
class OptionalMotion extends Instruction
{
@Override
void read(ByteBuf in)
{
int data = in.readInt();
if ( data > 0 )
{
in.skipBytes( 6 );
}
}
}

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