Compare commits

...
611 Commits
Author SHA1 Message Date
Myles 9e42a368e0 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-08-01 14:06:11 +01:00
Myles 27982efd29 Bump version to 0.9.8 2016-08-01 14:05:07 +01:00
Mason c3b343fbc8 Allow non-solid blocks to be placed at feet (#472) 2016-07-22 21:06:51 +01:00
Matsv 9bedb6c741 Move some classes to other packages 2016-07-17 12:00:46 +02:00
Matsv 873f4dd298 Give it some protection 2016-07-11 22:06:00 +02:00
Matsv 693990644f Rename the Meta(List)1_9_1_10Type to Metadata(List)1_9Type and cleanup the listeners 2016-07-11 20:27:44 +02:00
Matsv b2680d76a6 WIP cleanup 2016-07-11 15:52:06 +02:00
Matsv db935b454f Make the Metadata types version based and remove the NoGravity tag init since it doesn't seem needed. 2016-07-11 13:48:48 +02:00
Myles c207a9bfff Count other worlds as nether instead of imploding. 2016-07-10 12:35:46 +01:00
Myles f5bd041c7b Fix PacketListenerAPI load to be before Via, fixes #463. Tested with NickNamer 2016-07-09 15:21:17 +01:00
Myles 07d89b24af Custom reload message #459 2016-07-09 14:41:07 +01:00
Myles 1d0c0c527c Snapshot 2016-07-08 12:56:34 +01:00
Myles 7a9cb86563 0.9.7 release 2016-07-08 12:55:05 +01:00
Myles 87b1919863 Let the normal send go through the event loop. Fix signs are sent before the chunks on a 1.9.4 server with a 1.9-1.9.2 client (#460) 2016-07-03 12:05:32 +01:00
Myles d164e413c2 Snapshot 2016-07-02 23:34:31 +01:00
Myles 76d7db044f Version bump + small dead code fix 2016-07-02 23:28:54 +01:00
Myles 046ebb8ecc Fix chunk bug 2016-07-02 23:22:44 +01:00
Myles bccde04ace Back to snapshot 2016-07-02 22:37:29 +01:00
Myles 9385f03722 Bump version and tiny bit of formatting fix 2016-07-02 22:33:54 +01:00
Myles b48fc17ead Transform block 36 for 1.9.2 reading, and also use PartialType. 2016-07-02 22:32:40 +01:00
Myles b50d0075ca PacketWrapper allow returning of ChannelFuture with send, and fix blocked protocols disconnect.
Also remove a TODO.
2016-07-02 22:19:43 +01:00
Myles 84d006c71d Merge branch 'lenis-patch' 2016-07-02 22:06:39 +01:00
Myles 212da9c46c Fix resetReader being wrong, ty @Matsv for helping solve this 2016-07-02 22:05:08 +01:00
Myles 8edb7048a1 Code cleanup and implement index fix by @Matsv 2016-07-02 21:23:28 +01:00
Myles abe3c4b0c9 Identify unsigned byte properly 2016-07-02 21:07:41 +01:00
Myles c6d3c97c65 Fix clearing of wrapper 2016-07-02 21:07:22 +01:00
Matsv 13c6a9d612 Change getBlockId to get instead of indexOf 2016-07-02 20:45:34 +02:00
Myles 7d2ef743ac Fix stupidity, thanks @Pokechu22 <3 2016-07-02 19:09:38 +01:00
Myles 598d0f96d8 Not sure if i'm working forward or backwards on this, but pushing for progress 2016-07-01 20:17:25 +01:00
Matsv cbc22922d3 Set default force-sign-transformer to false 2016-07-01 18:51:42 +02:00
Myles 49783d36c2 Add link to docs. 2016-07-01 17:13:01 +01:00
Myles 70d91b4f87 Blocked versions now included when server sends supported versions, javadoc fixes & simple colour for blocked-msg. 2016-07-01 16:36:19 +01:00
Myles 17f3d13267 Fix #450, ProtocolSupport concurrency issues, also make listwrapper sync'd 2016-06-30 00:26:12 +01:00
Myles 559674bf58 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-06-29 16:43:42 +01:00
Myles fbc298bc30 Add some more detail to the config 2016-06-29 16:38:38 +01:00
Matsv e36902c441 Add possibility to block specific protocol versions 2016-06-29 12:26:03 +02:00
Matsv 805c78989a Port all the clients to prevent issues like ViaVersions BossBarAPI not working for clients on the same protocol. (If you use the api on a 1.9> server) 2016-06-29 11:35:15 +02:00
Mats 85e416171c Let the transformer handle the signs (#456) 2016-06-28 13:16:36 +02:00
Mats b55c0d0783 Possibility to force the json transformer (#455)
* Possibility to force the json transform

* Escape all the Strings. Who likes double quotes anyways.
2016-06-26 21:47:08 +01:00
Myles 33b4b3835f Update Contributors and version in README 2016-06-25 23:38:04 +01:00
Matsv 8ccd772105 Change the formatting a bit. merged #421 2016-06-25 13:22:18 +02:00
Matsv 8677c632df Merge remote-tracking branch 'jor/potion' into upmaster 2016-06-25 13:19:14 +02:00
Myles 560476c56f Should fix #452 2016-06-24 14:02:29 +01:00
lenis0012 20bbe7cec6 Support 1.9.2 servers
This code basically reads 1.9 data so it can then be transformed to add
in the tile entities.
it geta a little funky when it already loaded it as a 1.8 chunk tho, so
i had to add some methods to the chunk api.

in short: I hate minecraft
2016-06-23 04:00:59 +02:00
Myles 1a002486d0 Move back to snapshot, oops 2016-06-22 23:37:58 +01:00
Myles 26fcdfe3bc Allow ability to replace piston extension block to prevent crashing. 2016-06-22 23:34:32 +01:00
Mats 4af98b220c Fix piston tile entity crash (#443) 2016-06-22 21:37:53 +01:00
Myles f91fcb4ea8 Bump version 2016-06-22 21:33:25 +01:00
Myles b3060e0dc8 Start work on 1.9.2 chunk stuff, no where near done bit stuck on detecting skylight. 2016-06-22 21:32:26 +01:00
Myles 808a9a7d82 Small PPS change to allow %pps to be used as a placeholder. 2016-06-22 21:31:27 +01:00
Myles 32c43e6023 Fix chunks not being written and array type being weird. 2016-06-22 21:22:19 +01:00
Matsv 4c9c50f939 WIP: Move the TileEntities writer to the 1.9 transformer. 2016-06-22 22:00:24 +02:00
Matsv ac1b35379e Remove not required tags, and remove tested todo's 2016-06-22 20:38:40 +02:00
Myles b743589d77 This works but lags, only for 1.8 server. 2016-06-22 19:22:38 +01:00
Myles 9dad0a0d5e Fix the arrays 2016-06-22 18:20:42 +01:00
Matsv f5b49bc9ce Experimental implementation for block entities into chunks 2016-06-22 19:07:46 +02:00
Matsv b3612a68b0 Merge branch '1.10.1-chunkrefactor' of https://github.com/MylesIsCool/ViaVersion into 1.10.1 2016-06-22 18:36:42 +02:00
Myles 7385db02c2 Reorganise packages and push initial interface 2016-06-22 17:35:07 +01:00
Matsv 501d2ec3a2 Rewrite block tile entities. Not tested yet 2016-06-22 18:03:27 +02:00
Myles 1217a9b7e2 Make versions ordered by the index inserted. (Seems to work best over alphabetical) 2016-06-19 23:32:41 +01:00
Myles 6740c5c6dc Spring cleaning & make /viaver pps say when no players. 2016-06-19 22:36:15 +01:00
Myles 44e8056fb3 Add more versions & use ProtocolSupport API if not ported. 2016-06-19 22:35:49 +01:00
Myles d1da412cf7 Disable our system when an unknown handshake happens, fixes support for older mc versions. 2016-06-19 22:04:54 +01:00
Myles 6534a5414e Basic compatibility with ProtocolSupport, doesn't seem to work with 1.6.4 due to issues with our Login Handler. 2016-06-19 18:08:49 +01:00
Myles 91344a0b50 Cleanup some of the block placement code. 2016-06-19 18:07:00 +01:00
Myles cdd9ff4469 Back to snapshot 2016-06-15 19:47:10 +01:00
Myles d88b76db85 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-06-15 19:45:28 +01:00
Myles bc1d57853c Bump version 2016-06-15 19:44:25 +01:00
Troy Frew 27d6c12556 Added TacoSpigot to the block place fix. (#437)
TacoSpigot is a fork of PaperSpigot that people use.
2016-06-13 09:29:10 +02:00
Mats a76dd1ba49 Merge pull request #427 from Harry5573/master
Correct hologram Y offset
2016-06-10 15:38:52 +02:00
Mats 1a4388b3e7 Convert the Elytra sound properly they added in 1.9.2. Fix #430 (#432)
* Convert the Elytra sound properly they added in 1.9.2. Fix #430

* Change wrong version in comment

* Remove the passthrough
2016-06-09 16:03:01 +01:00
Mats f1b81f77d6 Use Myles new Magic transformer for the ArmorListener (#429)
* Use Myles new Magic transformer for the ArmorListener

* Use Myles new Magic transformer for the CommandBlockListener
2016-06-09 10:49:31 +01:00
Myles d6edec3a55 Allow packets to be transformed after sent by specifying the current protocol, woo! 2016-06-09 02:44:12 +01:00
Harry 094f4c6d58 Correct hologram Y offset
https://github.com/filoghost/HolographicDisplays/blob/master/HolographicDisplays/Plugin/com/gmail/filoghost/holographicdisplays/util/Offsets.java#L15 The offset is by default -1.25 for 1.8, however 1.9 clients require only -0.29. (-1.25 - -0.29) = -0.96 which should be the correct offset.
2016-06-08 21:43:15 +01:00
Matsv c57d0f60f9 Change to DEV version 2016-06-08 20:40:50 +02:00
Matsv dd5cd1ca48 Remove experimental message from readme 2016-06-08 20:38:39 +02:00
joserobjr ab4a565700 Update README.md (#426) 2016-06-08 20:36:29 +02:00
Myles f8ac54e237 Fix splash potion crash. 2016-06-08 19:02:11 +01:00
joserobjr 089e07fe49 Changes the random chest sounds to normal chest. (#424) 2016-06-08 19:09:19 +02:00
yzimroni 1d3b8f802c Update names from 'snapshot' to '1.10' (#422) 2016-06-08 18:00:21 +02:00
Myles 27283e48a2 Bump the version to avoid bad downloads. 2016-06-08 16:10:59 +01:00
Matsv d22584afbc Bye bungee we will not miss you, you eat our memory 2016-06-08 17:02:13 +02:00
Matsv 249ab01425 Rename package 2016-06-08 16:41:00 +02:00
Matsv 851097de44 Rename package 2016-06-08 16:38:59 +02:00
Matsv c095a51f7c 1.10 support and version bump 2016-06-08 16:35:06 +02:00
Matsv 5e62b7001e Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion into 1.10 2016-06-08 15:35:55 +02:00
joserobjr a79533bf72 Fixed uncraftable potion conversions from 1.8 to 1.9 2016-06-08 10:31:03 -03:00
joserobjr e3510d01d6 Fixes potion data conversion from 1.8 to 1.9 2016-06-08 08:09:13 -03:00
Mats 8cc4ba168a Patch EchoPet wrong metadata value (#419) 2016-06-08 11:29:08 +01:00
Matsv 264a21d092 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion into 1.10 2016-06-08 11:37:23 +02:00
Mats e2585db350 Make the main class cleaner by giving the config his own class (#418) 2016-06-07 19:18:48 +02:00
Matsv a2f7a52d31 Support for 1.10-pre2 2016-06-07 17:29:30 +02:00
Matsv d04121202d Modify the config comments to & 1.10 2016-06-07 09:11:33 +02:00
Matsv 95517ade2c Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion into 1.10 2016-06-03 22:18:28 +02:00
Matsv c9441de7e4 Change from info to severe 2016-06-03 21:15:53 +02:00
Matsv dc946cb845 An amazing feature. 2016-06-03 20:49:06 +02:00
Myles 5fa30d9adb Merge branch 'master' into 1.10 2016-06-03 18:52:52 +01:00
Myles a7043424ec Support ProtocolLib + late-bind, also it now tells you the plugin to blame if it goes wrong. How nice! 2016-06-03 18:52:25 +01:00
Matsv e1b3d21732 Woops, the sounds were still broken. Now it should be fixed. no lies this time 2016-06-02 21:19:48 +02:00
Matsv 8ffc056a7e Cleanup and change class/package names from 1.9.3 2016-06-02 21:00:18 +02:00
Matsv 7c274fb03d Handle new sounds 2016-06-02 20:52:55 +02:00
Matsv 3b533b5138 Compatibility with 1.10-pre1 (number 2, git didn't push everything for some reason) 2016-06-02 18:37:05 +02:00
Matsv 5665510f7e Compatibility with 1.10-pre1 2016-06-02 18:34:04 +02:00
Matsv 47faa21ef4 Add latest build to readme & auto-build test 2016-05-27 19:44:21 +02:00
Myles 575f457830 0.8.5 SNAPSHOT 2016-05-27 18:37:34 +01:00
Matsv d5bf7909e8 Sync with master 2016-05-27 19:16:22 +02:00
Myles fdf90b7931 0.8.4 Release 2016-05-27 18:05:46 +01:00
Myles e3305e4eae Automatically buffer unknown entities, removes 2 config values and deprecate api 2016-05-27 01:00:01 +01:00
Matsv 15fe8d394e Support for 16w21b 2016-05-26 19:02:06 +02:00
Matsv 082db38c40 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion into 1.10 2016-05-26 17:03:40 +02:00
Myles be54dc41d1 Add SkinRestorer to plugin.yml unsure if this will fix anything 2016-05-26 14:27:27 +01:00
Myles 487e79c043 Fix javadocs 2016-05-26 13:54:22 +01:00
Matsv ef6390a0b8 Update version for the buildserver 2016-05-26 11:16:12 +02:00
Matsv 9d9fc65633 Support for 16w21a, how fun. A snapshot without packet changes 2016-05-25 16:44:20 +02:00
Matsv 6eac61c912 Sync with master 2016-05-24 21:17:30 +02:00
Matsv d89362a271 Sync with master 2016-05-24 21:13:28 +02:00
Matsv 0a407069fa Add Burger to sources :) 2016-05-24 21:09:04 +02:00
Myles 661fdb1127 Bump version 2016-05-22 11:42:53 +01:00
Myles 9e6c0f72a8 Update version to be 1.9.3/4 2016-05-22 11:41:59 +01:00
Myles 70ad2613f1 Update config to look a bit more nicer, doesn't have the extra space when generated by bukkit. 2016-05-22 11:41:27 +01:00
Myles 9052946c45 Merge branch 'master' into 1.10 2016-05-21 22:12:10 +01:00
Myles 3ddc43bf7b Implement isSpigot() in the API and make it so xray does not activate if they do not use spigot. 2016-05-21 22:07:20 +01:00
Matsv cdb757eae5 Implement Myles idea to just use templates instead of defining compatibility 2016-05-21 21:19:20 +02:00
Matsv 50a3e03649 Possibility to add 'isCompatible' with other types. Fixes crashes on a 1.8 server 2016-05-21 20:54:26 +02:00
Matsv 957284930e Fix sounds 2016-05-21 16:19:12 +02:00
Matsv 198a24371c Sync with master 2016-05-21 15:01:25 +02:00
Mats bcc994b0dd Add possibility to get the supported versions from the api and status response (#402)
* Possibility  to send the Supported versions inside the status response packet

* Make lowercase
2016-05-19 18:56:42 +01:00
Matsv f870bd5a32 Transform pitch correctly 2016-05-19 13:07:51 +02:00
Matsv a14abd6f4f Handle the new Metadata value for 16w20a 2016-05-19 12:18:04 +02:00
Matsv 2456c3cf17 Basic support for the new 1.10 snapshot 16w20a 2016-05-18 16:43:57 +02:00
Myles 9828e4ae1d Add maven default goal.
Requested by our lord and saviour @Aikar
2016-05-17 23:40:00 +01:00
Myles 030aa887c7 Version bump to 0.8.3-SNAPSHOT #hype 2016-05-17 22:56:52 +01:00
Myles ba624a2b48 1.9.4 backport (#399)
Allow 1.9.4 spigot to handle 1.9, 1.9.1, 1.9.2
2016-05-17 22:48:56 +01:00
Myles e7582cb1ec Change license to be more appropriate, this one is more open and allows much more creativity. 2016-05-11 14:19:30 +01:00
Mats 82bf11fcbc Fix anti-xray for 1.9 (#393)
* Fix anti-xray for 1.9

* Bye NMS.

* Perform

* Add config option
2016-05-10 19:53:37 +01:00
Myles ac6e8b1709 Bump version 2016-05-10 15:03:55 +01:00
Myles 00cc545795 Using javassist add compatibility for Spigot builds with protocol compatibility (eg. 1.9.1 & 1.9.2)
Also fix issue with protocol passthrough
*whew*
2016-05-10 14:37:31 +01:00
Myles c7ee816aba Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-05-10 10:27:32 +01:00
Myles e7f85e67f6 Change our data structures to use concurrent equivalents, netty is multi-threaded. 2016-05-10 10:26:49 +01:00
Mats d239d2f967 Stop depending the bossbar metadata rewriter on the bukkit api (#391)
* Don't depend the bossbar metadata rewriter on the bukkit api

* Rename field
2016-05-09 17:44:10 +01:00
Myles 63970c6d82 Version bump 2016-05-08 22:45:46 +01:00
Mats 4cffdd4f64 Don't call PlayerInteractEvent twice and fix the gamemode message (#390)
* Experimental feature to fix the 'Your gamemode has been updated to ' message

* Don't fire PlayerInteractEvent twice, fix #326
2016-05-08 19:49:13 +01:00
Mats cb3f0291b7 Well, this feature never worked. (#389) 2016-05-04 20:03:48 +01:00
Mats edaffad045 1.9.3 support 2016-05-04 17:32:38 +02:00
Myles 172f89940a Implement passthroughAll to make it easier for adding things to the end of a packet. 2016-05-03 21:09:48 +01:00
Myles fb4bc397c6 Add fallback to metaindex to living entity. 2016-04-30 20:40:09 +01:00
Myles e595344941 Implement rewriting for villager trade info. 2016-04-29 17:09:24 +01:00
Myles 05dbc53fd0 Add javassist to the libraries for future use. Apologies for the like extra 600kb :( 2016-04-27 21:57:13 +01:00
Mats 0374da573b Check if the player is ported, fix NullPointerException post 876 on spigotmc.org (#374) 2016-04-24 12:29:52 +01:00
Myles 8e64fb8c21 Add magical unknown protocol version, so that if it's not registered it doesn't NPE. 2016-04-23 20:39:16 +01:00
Myles 0f55402171 Version bump 2016-04-22 17:17:40 +01:00
Myles acb7372eb7 Ensure that the player is online. 2016-04-22 13:36:10 +01:00
Myles 057ab050ea Make it so base protocol actually registers its listeners Credit to @jollyolbrits for finding this silly one. 2016-04-22 13:28:54 +01:00
Myles a01997fe53 Typo 2016-04-21 23:12:40 +01:00
Myles e4adbf4a1a Add terorbility build server and remove filip's since it's dead for now. 2016-04-21 22:47:01 +01:00
Myles 261d68c58e Fix blocking shield not going away :P 2016-04-21 21:13:10 +01:00
Myles 38617d1f61 Version bump 2016-04-21 16:20:45 +01:00
Myles cc5bcb8a64 Allow NMS packet receiving 2016-04-21 16:19:29 +01:00
Mats b6794f5597 Cancel swap item, fix #364 (#365)
* Cancel swap item, fix #364

* Remove canceling drop item
2016-04-20 18:31:18 +01:00
Myles 18f77308f5 Bump version to .0.7.8-SNAPSHOT 2016-04-20 15:59:23 +01:00
Myles 6bb473ea8d Change PlayerMovementMapper to a handler and fix the mappings so it works. 2016-04-20 01:33:01 +01:00
Myles 7984f6400c Clean up not used code 2016-04-20 01:25:00 +01:00
Myles 3498d093b0 Thanks @jollyolbrits for debugging, fix the issue with ground not being sent properly for movement.
Fixes anti-cheat issues.
Placement issues.
Probably 100 billion other issues.
Fix me being an idiot and changing numbers.
2016-04-20 01:22:58 +01:00
Myles a3db32758c Add new is feature to PacketWrapper :) 2016-04-20 01:09:39 +01:00
Myles 45952d3759 Move Idle thread. 2016-04-20 00:50:44 +01:00
Myles c552b12696 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-04-19 22:53:48 +01:00
Myles 0ae9d9dbbf Fix bossbars so they send correctly, credits to @jollyolbrits for detailed reporting of where the issue may take place. 2016-04-19 22:53:27 +01:00
Mats 8852e3b3a3 Change item from main hand, not offhand. Fixes #329 (#363) 2016-04-19 16:32:03 +01:00
Myles a496b2d3a8 This branch would be better here as it won't be applicable if elsewhere. 2016-04-17 12:59:01 +01:00
Myles 6198dbfe70 Change to match the config 2016-04-17 12:55:34 +01:00
Myles a81d52a54f Implement a packet limiting system,
This means that if a client sends more than a maximum, it will be disconnected.
It also means if a client goes over a threshold multiple times over a period of time, it will be disconnected.

Improvements are welcome, it's mostly down to how the user configures it.
(Some values are higher so that we don't kill every server with a tiny bit of lag)
2016-04-17 12:55:18 +01:00
Myles cf20e8ac5f Bump version 2016-04-17 00:53:49 +01:00
Myles 4f8a248c6b Add item-cache as a less expensive way of getting items. (Will rewrite eventually to not depend on Bukkit) 2016-04-17 00:52:35 +01:00
Mats 57d58db35e Fix item showing twice, one in the new slot (#359) 2016-04-15 18:48:28 +01:00
Mats c214ca02e8 Make commandblocks compatible with all 1.8 spigot/craftbukkit versions, fix #355 (#356) 2016-04-14 12:59:23 +01:00
Myles 6b8b0e1771 Bump version to 0.7.6-SNAPSHOT 2016-04-13 19:42:53 +01:00
Myles e6671513f2 Improve an issue to do with block breaking ghosting back, note this is not a fully fix, but improves the issue quite a bit. 2016-04-13 16:54:18 +01:00
Myles 4c7b50d6fb Fix chunk sending order, Fixes #338, #292 (I believe.) 2016-04-13 15:05:50 +01:00
Mats 1c9229a2fc Don't unload the chunks twice (#350) 2016-04-13 12:25:41 +01:00
Mats d11c18c024 Remove MCProtocolLib (#349) 2016-04-12 12:40:12 +01:00
Mats dc4b5b4d35 Possibility to show the new 1.9 death messages (#348) 2016-04-12 12:01:37 +01:00
Mats 517299d673 Show skeletons' bow like 1.8, not down as 1.9 without target (#347) 2016-04-12 11:18:58 +01:00
Mats a8baa7af50 Transform Combat packet (#346) 2016-04-12 11:18:51 +01:00
Myles a1f847c905 Patch respawn packet to reset bulk / loaded cache. 2016-04-11 20:17:48 +01:00
Mats f3ea43b1eb Reformat / optimize imports (#344) 2016-04-10 18:43:08 +01:00
Mats 551b5d0654 Rewrite effect ids (#342)
* Rewrite effect ids

* Remove test line

* Remove Lombok unused thingy

* No need to check.
2016-04-10 14:29:25 +01:00
Mats 9f39662df6 Check if custom name is visible and if custom name is not empty. Fix …
* Check if custom name is visible and if custom name is not empty. Fix #327

* Fix typo
2016-04-06 13:50:09 +01:00
Myles 7ea2156f37 Bump version 2016-04-05 14:31:40 +01:00
Mats 5032e7d07e Only apply the 'Hologram patch' to small entities since it only happens to them.
Only apply the 'Hologram patch' to small entities (Doesn't fix issue but hey)
2016-04-04 15:55:48 +01:00
Myles c7c6ee9fbc Delay registration of protocols until the plugin has loaded to prevent it being done at the wrong time, #323 #316 Fixed 2016-04-03 23:30:10 +01:00
Mats 4431ca63c2 Fix viaversion list command 2016-04-03 11:26:27 +01:00
Myles 1fa7211cf0 Construct List properly, Fix #314 2016-04-03 01:51:38 +01:00
Myles de576795dc Blame @Matsv 2016-04-02 22:59:40 +01:00
Myles f6286bcc25 Bump version 2016-04-02 22:13:30 +01:00
Myles 8276b212e9 Merge pull request #313 from Matsv/master
Stop allowing everyone to change the instance
2016-04-02 21:32:46 +01:00
Matsv aabd9247a6 Stop allowing everyone to change the instance 2016-04-02 21:45:24 +02:00
Myles 997c2ad6a1 Fix Potions: ThrownPotion is now correct, and the particles are too.
Fixes #223
Also changes a tiny bit of javadoc :)
2016-04-02 14:46:30 +01:00
Myles 233a2ba5df Merge pull request #312 from Matsv/dev
Fix custom NBT for potions / spawneggs
2016-04-02 14:09:00 +01:00
Matsv ed0d5a7cfb Fix NBT for potions 2016-04-02 15:06:10 +02:00
Matsv 87f083460c Fix custom named spawneggs 2016-04-02 15:02:41 +02:00
Myles 2d6dedefb8 Add some packet plugins to loadbefore to ensure it works better with them. 2016-04-02 13:50:21 +01:00
Myles 8adbf36a3a Merge pull request #311 from Matsv/dev
Make command sender messages cleaner
2016-04-02 13:30:10 +01:00
Matsv 8c706b665c Don't format if no args are given 2016-04-02 11:58:15 +02:00
Matsv 2e3677a592 Make command sender messages cleaner 2016-04-02 11:51:17 +02:00
Myles 3602c5087b Don't send a meta data packet when list is empty. #288 2016-04-01 18:13:23 +01:00
Myles 5c84b3d8cc Merge pull request #309 from HugoDaBosss/master
Implement subcommand to reload the config
2016-04-01 16:41:03 +01:00
Hugo Kerstens 7defe7129f Implement subcommand to reload the config 2016-04-01 17:31:44 +02:00
Myles 995dc135b8 Merge pull request #308 from Matsv/boss
Cleanup BossBar class & add new bossbar api method, addPlayers()
2016-04-01 15:07:04 +01:00
Matsv 3f64fb7d5f Cleanup BossBar class & add new bossbar api method, addPlayers() 2016-04-01 16:03:56 +02:00
Myles ac8f7a00ae Merge pull request #305 from HugoDaBosss/master
Implement new protocol version registry
2016-03-31 22:45:39 +01:00
Myles 6893f34289 Support reloading to some extent, if you use protocol lib it will kick all your players... (So you probably should just get a PluginManager...)
One day i'll fully patch to work... (If I don't kick the players it ends up that ProtocolLib implodes and nobody can connect.)
2016-03-31 22:45:15 +01:00
Hugo Kerstens 0a69d62cbe Fixed typo (blame Mats) 2016-03-31 23:26:13 +02:00
Myles 5e0096aa2c Merge pull request #307 from Matsv/master
Woops use the same instance
2016-03-31 21:49:42 +01:00
Matsv 7326205495 Woops use the same instance 2016-03-31 22:48:20 +02:00
Myles a8212db7f2 Merge pull request #306 from Matsv/tabcomplete
Tabcomplete
2016-03-31 19:55:11 +01:00
Matsv 2905d77206 Reformatting moved color to the top ;( 2016-03-31 20:53:03 +02:00
Matsv cb8ec2ce20 Add tab-complete possibility and help subcommand 2016-03-31 20:50:22 +02:00
Hugo Kerstens 09f484f956 Implement new protocol version registry 2016-03-31 19:50:04 +02:00
Myles c48922eb3e Merge pull request #304 from Matsv/cmd
Implement new command API
2016-03-31 17:56:08 +01:00
Matsv b701a0ef67 Change debug mode subcmd description 2016-03-31 18:55:05 +02:00
Matsv eb50f4e907 Merge branch 'master' of https://github.com/Matsv/ViaVersion into cmd 2016-03-31 17:53:12 +02:00
Matsv 6480ea34fc Changed javadoc 2016-03-31 17:52:06 +02:00
Matsv 511941462f Add javadoc 2016-03-31 17:51:30 +02:00
Matsv 34cc783cac Fix missing description, add javadocs, make sure subcommand is valid, check permission 2016-03-31 17:48:15 +02:00
Matsv ecc79b4f49 Command API to keep it clean and make it possible for developers to add their own viaversion subcommands if they want to. 2016-03-31 17:22:42 +02:00
Myles 76f10c463f Merge pull request #301 from Matsv/master
Handle discontinued player item in hand, fixes #299
2016-03-31 15:49:24 +01:00
Matsv 41d5144b57 Handle discontinued player item in hand, fixes #299 2016-03-31 16:28:56 +02:00
Myles de196f2e4f Merge pull request #300 from HugoDaBosss/master
Small optimization in join packet
2016-03-31 14:10:52 +01:00
Hugo Kerstens 0acc2f95fb Remove unneeded code 2016-03-31 15:08:19 +02:00
Myles d16eb9b27e Version bump 2016-03-30 17:46:00 +01:00
Myles 8760b53a0a Fix Disconnect Issue (It's not really harmful but still) 2016-03-30 17:45:24 +01:00
Myles a40182186f Fix debug issue with 1.9.2 2016-03-30 17:34:13 +01:00
Myles ef2b173749 Merge pull request #295 from Matsv/master
Rename 1_9_1 PRE to just 1_9_1
2016-03-30 17:33:15 +01:00
Matsv 75c9284cda Rename 1_9_1 PRE to just 1_9_1 2016-03-30 18:23:52 +02:00
Myles 2abecba7bf Bump version 2016-03-30 16:54:49 +01:00
Myles fb6055cbfe 1.9.2 support (no protocol changes from what I've seen) 2016-03-30 16:51:55 +01:00
Myles 639c9ea8c1 Fix 1.8R0.1 not working, ensure flying packets are sent from right place in pipeline, should fix #273 2016-03-30 16:43:01 +01:00
Myles 1872845d2b Add additional information when packets aren't sent correctly. 2016-03-30 15:58:31 +01:00
Myles 93755c6732 Move patch to update health so it works better and is applied upon login. 2016-03-29 18:22:40 +01:00
Myles 68973fd136 Merge pull request #291 from Matsv/gitter
Add Gitter badge to README.md
2016-03-29 16:08:43 +01:00
Matsv 1a0bd37a01 Add gitter badge to ReadMe 2016-03-29 16:43:42 +02:00
Myles 3551779600 Merge pull request #290 from Matsv/master
Add JavaDocs link to README.md
2016-03-29 15:39:40 +01:00
Matsv b8deddcd2c Add JavaDocs link to README.md 2016-03-29 16:36:21 +02:00
Myles c49bf89ead Merge pull request #289 from Matsv/debug
Show all errors on debug
2016-03-29 15:03:36 +01:00
Myles 4ff4fe2ab2 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-03-29 15:02:04 +01:00
Myles 1b99e2cf57 Move EntityNBT to different file and fix the issue to do with respawn chunks unloading. #287 2016-03-29 15:01:38 +01:00
Matsv 55830b0dfb Show all errors on debug 2016-03-29 16:00:56 +02:00
Myles e61f56b2e0 Merge pull request #283 from Matsv/slpfix
Woops the new api broke ServerListPlus custom outdated message again …
2016-03-28 12:04:06 +01:00
Mats 95ea95be13 Woops the new api broke ServerListPlus custom outdated message again fixes #282 2016-03-28 11:52:29 +02:00
Myles d72b7fc4df Fix shields not being configurable 2016-03-27 23:52:57 +01:00
Myles 0992c74351 Improve block placing a bit 2016-03-27 23:40:32 +01:00
Myles 081c23ad8b Small Javadocs 2016-03-27 22:45:25 +01:00
Myles 258f0fc636 Change the README back ;) 2016-03-27 21:50:49 +01:00
Myles c4e3864fc0 Pom pom 2016-03-27 21:46:11 +01:00
Myles 405b6e8047 Merge pull request #280 from HugoDaBosss/apiv2
Make BossBar API easier to use
2016-03-27 21:37:14 +01:00
Hugo Kerstens 9847912128 Make BossBar API easier to use 2016-03-27 21:30:31 +02:00
Myles d89a34cca3 Allow packets to be written to the server using passthrouh ID, shouldn't break anything I also updated comment on why interaction is half broken 2016-03-27 19:13:19 +01:00
Myles 6197138380 Merge pull request #279 from HugoDaBosss/apiv2
Update BossBar API to use protocol version and add protocol version check by uuid API method
2016-03-27 18:31:17 +01:00
Hugo Kerstens f5f4876182 Add check for isPorted because server can be using 1.9 2016-03-27 18:05:04 +01:00
Hugo Kerstens 293c1229ff Update BossBar API to use protocol version and add protocol version by uuid API method 2016-03-27 17:58:31 +01:00
Myles ba60f10744 Match the source for SPIGOT-1.8 2016-03-27 16:37:42 +01:00
Myles c0493de4df Does not fix armour issue completely but improves right click armour items (it's still bugged, working on it) 2016-03-27 14:57:13 +01:00
Myles 46b2f69b01 Fix healing potion :) 2016-03-27 14:06:55 +01:00
Myles f926113c66 Improve paper patch to allow for latency in towering up. 2016-03-27 13:56:06 +01:00
Myles 0e4df51613 Better placement detection 2016-03-26 23:29:09 +00:00
Myles c5f72dc728 Wrong way oops 2016-03-26 22:22:19 +00:00
Myles cee5b1ee42 Improve the patch to check the pipe and to handle above head placement. 2016-03-26 15:55:13 +00:00
Myles f1b9cd2e56 Add PaperSpigot patch to fix block placement (Applies to all protocols for now, until someone finds an issue with this) 2016-03-26 15:28:42 +00:00
Myles 7807e6d9c4 Merge pull request #275 from HugoDaBosss/apiv2
Fix for block place sounds
2016-03-26 14:51:55 +00:00
Hugo Kerstens 4b354f806d Check if user is indeed using 1.9 to 1.8 protocol conversion 2016-03-26 15:38:15 +01:00
Hugo Kerstens 41707ca867 Not needed 2016-03-26 15:22:23 +01:00
Hugo Kerstens 5bca3a97ec Merge remote-tracking branch 'origin/apiv2' into apiv2 2016-03-26 15:18:39 +01:00
Hugo Kerstens 3679aa618f Fix for block place sounds 2016-03-26 15:17:00 +01:00
Myles e9d96f2daf Fix hologram offset. 2016-03-26 14:08:23 +00:00
Myles f371419396 Fix shields not being for the right entity >.> and also print out value for metadata 2016-03-26 13:07:06 +00:00
Myles f32d3211ed Fix issue with Bukkit materials which aren't found by ID 2016-03-26 12:33:22 +00:00
Hugo Kerstens 45f99d4c31 Small fixes and formatting 2016-03-25 23:34:02 +01:00
Myles 71a9c90fe9 Fix team packet 2016-03-25 22:02:25 +00:00
Myles 406500b0bd Fix type conversion not being instant, (causes issue when reading later on)
Introduce packet ID counting (so we can mark something for the next packet etc)
Move USE Item
Add patch to handle placement properly and not break items yay. (Requires a list of special items >.>)
(And lastplaceblock packet index)
2016-03-24 15:45:16 +00:00
Myles 9257298e17 Handle not found metadata properly, and register the player as a type.
Fixes #270
2016-03-23 17:56:02 +00:00
Myles 0376602894 Update TODO list, add pipeline cache 2016-03-23 14:00:48 +00:00
Myles 95ceabb495 Merge fix for duplicated events for placement 2016-03-23 13:41:11 +00:00
Myles 6c8ccb1b1e Don't send place block twice (1.9 will use use_item to handle items), fixes #244 (may fix more) 2016-03-23 13:37:45 +00:00
Myles f351dd03e7 Merge pull request #269 from Matsv/effectapiv2
Reimplementing the effect indicator
2016-03-23 12:43:20 +00:00
Myles c1e77a49b6 Merge branch 'master' into apiv2 2016-03-23 12:40:08 +00:00
Myles 9adf6040fa Optimise ViaIdleThread, use 1 object for all packets. (Quite a big speed up) 2016-03-23 12:35:38 +00:00
Mats 3e320618f9 Merge branch 'apiv2' of https://github.com/MylesIsCool/ViaVersion into apiv2 2016-03-23 13:13:33 +01:00
Myles 6c1de57d32 Merge pull request #268 from Matsv/apiv2
Fix small teampacket bug
2016-03-23 12:12:19 +00:00
Mats 7694d311d1 Reimplement effect indicator 2016-03-23 12:42:03 +01:00
Mats eee1fd941e Fix small teampacket bug 2016-03-23 11:34:13 +01:00
Hugo Kerstens 9c5c181389 Small fixes and formatting 2016-03-23 00:26:38 +01:00
Myles b4b85b1602 Merge pull request #266 from HugoDaBosss/apiv2
Implement new Config API at some more places
2016-03-22 23:23:50 +00:00
Hugo Kerstens f6bb1b48f5 Implement new Config API at some more places 2016-03-22 23:35:01 +01:00
Myles 4ce846a899 Make more errors informative :) 2016-03-22 19:37:15 +00:00
Myles ef08117f34 oops ;) better read the tin better 2016-03-22 19:28:37 +00:00
Myles 4b582a7279 Make PacketWrapper exceptions more informative :) 2016-03-22 19:27:27 +00:00
Myles ad53c1ed7f Merge pull request #265 from HugoDaBosss/apiv2
Optimise SoundEffect searching
2016-03-22 19:25:33 +00:00
Hugo Kerstens 6e46d018a4 Removed import? 2016-03-22 20:18:07 +01:00
Myles 6beacf9804 Merge pull request #264 from HugoDaBosss/apiv2
Removed some debug code
2016-03-22 19:17:28 +00:00
Hugo Kerstens e15c8d7257 Optimise sound searching 2016-03-22 20:16:39 +01:00
Hugo Kerstens 3518804cbf Remove some debug code 2016-03-22 20:11:24 +01:00
Myles 101f86c8cd Merge pull request #263 from HugoDaBosss/apiv2
Fixed spawn experience orb packet
2016-03-22 18:32:42 +00:00
Hugo Kerstens 22c2435656 Fixed spawn experience orb packet 2016-03-22 19:30:24 +01:00
Myles af53275ab9 JavaDoc for quite a lot of the API classes... yay 2016-03-22 18:02:46 +00:00
Myles eccbb567e8 Clean up some code in Base and MetaIndex 2016-03-22 16:56:36 +00:00
Myles bae3599388 Update DEBUG to work in APIv2, also fix a few usages to the config API (may need more) 2016-03-22 16:53:07 +00:00
Myles 88ab4e53a7 Merge pull request #261 from HugoDaBosss/apiv2
Add config option to suppress 'Unable to get entity for ID' errors (apiv2)
2016-03-22 16:48:13 +00:00
Hugo Kerstens 25fa2eabbb Small update for descriptions 2016-03-22 17:22:49 +01:00
Hugo Kerstens e12d8ec466 Add descriptions for the new Config API 2016-03-22 17:17:13 +01:00
Hugo Kerstens a7022bddf8 Small typo 2016-03-22 17:00:13 +01:00
Hugo Kerstens 523c27237d Small changes for the new Config API 2016-03-22 16:55:58 +01:00
Hugo Kerstens 147891f76b Implement config to the API 2016-03-22 16:53:53 +01:00
Myles a5ba52ce05 Rename ChunkHandler
Introduce Packet Filtering
2016-03-22 15:36:11 +00:00
Hugo Kerstens ccb2a4756f Add config option to suppress 'Unable to get entity for ID' errors 2016-03-22 16:27:39 +01:00
Myles f5a96b791d Move listeners to respectful classes to be registered. 2016-03-22 15:03:02 +00:00
Myles c628a8a23f Merge pull request #257 from HugoDaBosss/apiv2
Fix armorstands moving incorrectly when using relative movement packets (apiv2)
2016-03-22 14:38:33 +00:00
Myles 80f63d79ef Merge pull request #258 from HugoDaBosss/master
Fix armorstands moving incorrectly when using relative movement packets
2016-03-22 14:37:40 +00:00
Hugo Kerstens b225afe6ef Fix armorstands moving incorrectly when using relative movement packets 2016-03-22 15:28:00 +01:00
Hugo Kerstens 4e1625b017 Merge pull request #14 from MylesIsCool/master
Update from master
2016-03-22 15:27:12 +01:00
Hugo Kerstens 5c4867365e Fix armorstands moving incorrectly when using relative movement packets 2016-03-22 15:22:21 +01:00
Myles 3549a823cb Don't move when relative 2016-03-22 12:07:43 +00:00
Myles 23a00d2555 Match master 2016-03-21 22:30:05 +00:00
Myles 57931e7231 Patch inventory shield bug 2016-03-21 22:28:11 +00:00
Myles 9e19e0c8af Patch inventory sword bug 2016-03-21 22:24:03 +00:00
Myles 74461609c1 Change to use maps, much better for optimisation. 2016-03-21 19:42:52 +00:00
Myles 7d3e6bc7cb This is why people should read over code :)) 2016-03-21 19:13:55 +00:00
Myles 175606f320 Version bump 2016-03-20 16:40:03 +00:00
Myles b226e94981 Patch the other mem leak fix across 2016-03-19 23:49:26 +00:00
Myles 7d0687aa4a Fix chance of another leak happening... 2016-03-19 23:47:03 +00:00
Myles d152b8b9e1 Merge branch 'master' into apiv2 2016-03-19 22:05:57 +00:00
Myles 1fbd561aec Oops, fix 1.8 clients 2016-03-19 22:04:17 +00:00
Myles a8295c9de0 Merge pull request #254 from Matsv/ifremoveifremoveif
Remove unnecessary if statement, this is always true.
2016-03-19 21:37:04 +00:00
Mats e894a3c733 Remove unnecessary if statement, this is always true. 2016-03-19 21:53:26 +01:00
Myles a2f8f28010 Fix memory leak, add command. Merge from master 2016-03-19 20:51:23 +00:00
Myles 704c876772 One line of code can make holes in the world, one line can fix them. (Fixes packet mem leak, also adds useful secret displayleaks command :) ) 2016-03-19 20:45:07 +00:00
Myles 0233e2ab27 Merge pull request #250 from HugoDaBosss/apiv2
Change protocol constants to final fields
2016-03-19 20:25:32 +00:00
BuildTools 5ae8a35740 Change protocol constants to final fields 2016-03-19 01:11:16 +01:00
Myles ed766eb656 Merge pull request #247 from HugoDaBosss/apiv2
Small optimization for armor searching
2016-03-18 22:04:05 +00:00
Myles b1b35fe025 Bump version 2016-03-18 21:59:13 +00:00
HugoDaBosss 9b6a9fca3d Small optimization for armor searching 2016-03-18 22:57:16 +01:00
Myles 615128eba2 Bongo bongo bongo 2016-03-18 21:25:41 +00:00
Myles 8f3b938e39 Update readme so I don't forget 2016-03-18 21:24:16 +00:00
Myles 625a1d2191 Eventually we should have some sort of handler for this, but this is fine for now 2016-03-18 21:22:09 +00:00
Myles 8a35c0235e Move everything into the right package.
Clean up a lot of code.
Remove PacketUtil (evil laugh)
Add Pipeline Util
Organise listeners, and add protocol pipe checks
2016-03-18 21:18:48 +00:00
Myles 69e8ddcbf6 Update to match master and all current fixes 2016-03-18 20:22:38 +00:00
Myles ce8a504750 Merge from other branch to ensure we don't have to redo some of these patches 2016-03-18 18:25:58 +00:00
Myles 11f3844d63 Use GSON instead, should fix memory leak issue with JSON. Also make sure that we use a copy of players for the bossbar. 2016-03-18 18:14:58 +00:00
Myles 56d5f8eec6 Add protocol registry.
Fix some issues with PacketWrapper
Add 1.9.1 port
Add ProtocolVersion detection on boot
Add more type converters
Implement Pipeline properly
2016-03-17 21:24:25 +00:00
Myles 7a98cdd28f Remove more debug code
Correct casting detector in packet wrapper.
Re-order some packets
Implement Plugin Message Transformers
Implement Sound Transformer
Implement Block Entity Transformer
2016-03-17 13:58:49 +00:00
Mats d40c5851e9 Merge pull request #239 from Matsv/master
Add api method to get player's protocol id
2016-03-17 12:38:51 +01:00
Myles ccda9f11c8 Remove some debug info, make it so StoredObject protects user.
Implement rewriting of Slot in rewriter.
Implement Enchanting Patch
Implement Brewing Patch
Implement Auto-Team Patch
Implement Inventory Tracker
Remove some TODOs
Implement Item Throwing on elytra
(Should just be plugin channels and a few packets + sounds left)
2016-03-16 23:34:03 +00:00
Myles 7e133a0be8 Include UserConnection in StoredObject
Handle Blocking
Handle BossBars, Holograms
2016-03-16 21:52:00 +00:00
Mats d0e573613b Add api method to get player's protocol id, 2016-03-16 21:01:04 +01:00
Myles 2197b938f8 Implement ItemRewritter
Upgrade ViaIdleThread to new system
Add new method to ProtocolPipeline
Implement Use Item
2016-03-16 19:46:16 +00:00
Myles 0d3ba67233 Remove compress / decompress, rethrow errors if they occur from another handler, Fixes #233 2016-03-16 13:42:17 +00:00
Myles 9d57521b29 Bump Version 2016-03-15 21:57:38 +00:00
Myles d98d4ff466 Merge pull request #236 from Matsv/meta11
Discountinue player metadata 11.
2016-03-15 21:06:37 +00:00
Myles 71e27b4799 Merge pull request #232 from Matsv/dropcreative
Throw items when you try to put things in your second hand in creative.
2016-03-15 21:06:04 +00:00
Myles f1354edf20 Merge pull request #231 from Matsv/effect
Make it possible to use the new effect indicators in 1.9
2016-03-15 21:05:55 +00:00
Mats 4d82112286 Discountinue metadata 11. 2016-03-15 21:42:40 +01:00
Mats ba5a44d2d2 Remove debug message 2016-03-15 20:40:26 +01:00
Mats 597ddc7f82 Throw items when you try to put things in your second hand in creative. 2016-03-15 20:37:45 +01:00
Mats 6a7bd209a3 Make it possible to use the new effect indicators in 1.9 2016-03-15 20:20:39 +01:00
Myles 722f28f086 Merge pull request #228 from Matsv/slp
Make compatible with ServerListPlus custom outdated message. Fix #227
2016-03-15 17:51:56 +00:00
Mats daed15d61f Make compatible with ServerListPlus custom outdated message. Fix #227 2016-03-15 14:14:10 +01:00
Myles c300c47a14 Implement Optional UUIDs
Implement Meta Rewriting
Implement Type Converters

Implement System so it can be tested.

Most of it works excluding the missing packets, also fixes some stupid mistakes :)
2016-03-15 00:34:20 +00:00
Myles 89427cb2da PacketWrapper now has an ID attached and can be reset so that it can be read from stored values.
Removed some parameters from protocol, the ID will now be attached to the PacketWrapper (made more sense)
BaseProtocol doesn't handle ProtocolInfo anymore
Implement ProtocolPipeline (WIP)
2016-03-14 18:05:29 +00:00
Myles fce7f1740e Add packet cancelling, implement quite a few of the todo's 2016-03-14 16:51:56 +00:00
Myles 0357d8e6aa Implement Partial Types (Types which require constructing with info), Implement Items, Implement NBT, add exceptions so they go down the tree! 2016-03-14 16:09:50 +00:00
Myles 55335944e3 Update apiv2 to match master 2016-03-14 12:59:15 +00:00
Myles c0b2985343 Just a reminder :) 2016-03-14 12:55:17 +00:00
Myles 91ae5990b1 Almost forgot response handler woops, also allow PacketWrapper to be modifier :) 2016-03-14 12:48:05 +00:00
Myles 33f1a8975c Another quite big update:
Implement Unsigned Short
Implement Most of the Incoming Packets (Still need to implement a few, when I add some sort of packet sending / id changing and packet cancelling)
Implement a base protocol

Still need to do plugin messaging (I will probably forget)
2016-03-14 12:40:23 +00:00
Myles 7cfba0b602 Merge pull request #210 from Matsv/fixarmortjes
Fix #209 woops my fault
2016-03-13 17:02:07 +00:00
Myles 9b28129187 Using PacketType as a checklist, implement most of the base outgoing packets.
Add new REMAINING_BYTES type.
Add an outline of what ItemType will be like
Add a passthrough option to PacketWrapper to make it easy to passthrough and grab the type.
By default passthrough all the bytes :)
2016-03-13 17:01:36 +00:00
Mats 78ab7c840a Fix #209 woops my fault 2016-03-13 16:48:07 +01:00
Myles 669ec3f453 Merge pull request #208 from Matsv/drop
Drop SpaceHQ mcprotocol
2016-03-13 15:17:20 +00:00
Mats dd32b46055 Remove unused imports 2016-03-13 16:13:45 +01:00
Mats 7daa43146e Drop spacehq MC protocol since it's no longer used 2016-03-13 16:12:31 +01:00
Myles 89d5f2cc4f Merge pull request #207 from Matsv/armorattfix
Fix armor not showing on Respawn (With keepinventory true) & world change
2016-03-13 14:30:56 +00:00
Mats 53fb753284 Fix armor not showing on Respawn (With keepinventory true) & world change 2016-03-13 15:22:23 +01:00
Myles 81d89d3839 Rename methods in UserConnection, add new PacketHandler.
Change the protection of some methods to be appropriate.
Actually register packets
Save entity types
2016-03-13 13:40:53 +00:00
Myles 469d81df72 Merge pull request #206 from Matsv/cmdfix
Fix unable to open commandblock after respawn/world change
2016-03-13 13:18:22 +00:00
Mats 7d7f5a0bda Fix unable to open commandblock after respawn/world change 2016-03-13 14:02:10 +01:00
Myles 9954195a8f Merge pull request #205 from Matsv/master
Fix commandblocks not able to change command on update
2016-03-13 12:26:40 +00:00
Mats 62d210de68 Fix commandblocks not able to change command on every-tick commandblock update 2016-03-13 11:06:18 +01:00
Myles e19a2920b9 API: Work towards rewriting metadata, (This is nowhere near finished and I need to work on Item and NBT), Also change the names of a few classes to be more appropriate and implement transformation of the doubles.
(I probably messed up somewhere, nothing is tested as this is essentially API design)
2016-03-12 22:33:43 +00:00
Myles 8d2189cb8e Bump versions 2016-03-12 20:52:46 +00:00
Myles 44a044848f Fix ServerConnection #198 2016-03-12 20:48:04 +00:00
Myles 4f133366e1 Add limitation to NBT data, we'll stick with this for now. I don't see this easily being beaten. 2016-03-12 20:41:04 +00:00
Myles 7c66507960 Merge pull request #200 from lenis0012/chunks
Implement new chunk transformer
2016-03-12 20:27:44 +00:00
Lennart ten Wolde e436988303 transform chunk bulk packets 2016-03-12 15:47:35 +01:00
Lennart ten Wolde 8b65efc4bd Implement new chunk transformer 2016-03-12 13:58:10 +01:00
Myles 7cff20f218 Intitial APIv2, this does not work. Type conversion is not implemented, as well as quite a few things, most things will probably change. 2016-03-11 23:07:13 +00:00
Myles 131517105e Change README 2016-03-11 23:05:47 +00:00
Myles ae2592f3d1 Update to 1.9.1 PRE 2 :) 2016-03-11 16:20:15 +00:00
Myles c009827622 Merge pull request #192 from HugoDaBosss/optimize2
Optimize packet searching
2016-03-11 12:55:15 +00:00
HugoDaBosss afe18379e0 Optimize packet searching 2016-03-11 11:48:42 +01:00
Myles 5ac61fa71d Must of missed this ;) 0.6.3 in desc 2016-03-10 22:52:29 +00:00
HugoDaBosss 3511f9a7b2 Optimized packet searching 2016-03-10 23:13:23 +01:00
Myles e3f7493616 Merge pull request #191 from Matsv/master
Fix Bungeecord "Team viaversion already exists in this scoreboard" and might fix #172
2016-03-10 19:47:43 +00:00
Mats a769599448 Fix Bungeecord "Team viaversion already exists in this scoreboard" and might fix #86 2016-03-10 20:33:32 +01:00
Myles 5df8a1e8e7 Bump version 2016-03-10 16:47:52 +00:00
Myles a3d124b552 Merge pull request #190 from lenis0012/master
Add config wrapper to update config
2016-03-10 16:44:20 +00:00
Lennart ten Wolde 6d95af3963 Add config wrapper to update config
Configuration reads old config and moves it's values over to a new
config copied from the resources directory.

normally, when you save it would delete the comments, but they are
written back in to the new config by this wrapper

now people their config files will actually update
2016-03-10 17:40:40 +01:00
Myles c08a38ff21 Merge pull request #189 from lenis0012/master
fix metadata type mismatch
2016-03-10 16:21:02 +00:00
Lennart ten Wolde 4a804bae7c fix metadata type mismatch & add anti-flicker 2016-03-10 16:52:31 +01:00
Myles fd42c7eba6 Merge pull request #188 from lenis0012/master
fixed default boss title
2016-03-10 14:15:30 +00:00
Lennart ten Wolde 1af86d1354 fixed default boss title 2016-03-10 15:14:27 +01:00
Myles 1b77e1c89f Fix BarAPI, (adds new metaindex, and change colour to be right and remove debug) 2016-03-10 14:07:27 +00:00
Myles c42b9351b8 Remove sync-chunks 2016-03-10 13:25:49 +00:00
Myles ab8c8cd7c8 Merge pull request #187 from lenis0012/chunks
Add chunk handler to netty pipeline. Fixes #48
2016-03-10 13:22:48 +00:00
Myles 83518b92fe Make bossbar patch a configurable option 2016-03-10 13:22:32 +00:00
Myles 1bf1e8981c Merge pull request #186 from lenis0012/master
Add support for 1.8 boss bars. Fixes #41
2016-03-10 13:13:55 +00:00
Lennart ten Wolde b1f076936d Add chunk handler to netty pipeline. FIxes #48 2016-03-10 12:47:09 +01:00
Lennart ten Wolde 319e793cd6 Add support for 1.8 boss bars
Automatically converts legacy boss bars to 1.9 ones using ViaVersions's
boss API.

I suggest you add a config option
Note: also fixed crash on wither/dragon spawn
2016-03-10 03:14:30 +01:00
Myles c9e1360951 Version bump 2016-03-09 21:40:11 +00:00
Myles c11ad7930f Tiny cleanup allow it to be disabled via config and add lenis0012 to contributors <3 2016-03-09 21:30:43 +00:00
Myles 7b36a9de51 Merge pull request #185 from lenis0012/master
Manually perform idle updates. Fixed #160 #99
2016-03-09 21:21:59 +00:00
Lennart ten Wolde d5e9170109 Manually perform idle updates. Fixed #160 #99
Manually performs idle updates by keeping track of the player's
movement.
It compensates for the missing idle packets attempting to get a ratio of
20 movement related packets per second.
2016-03-09 22:17:17 +01:00
Myles 47b447f195 Add the option to use a hologram patch to fix invisible holograms being in wrong place, by default disabled. 2016-03-09 21:08:50 +00:00
Myles e2d27df1a8 Add another build server 2016-03-09 14:37:21 +00:00
Myles 9a781d940f Bump version 2016-03-09 14:29:30 +00:00
Myles fed36c9487 synchronize all the things! 2016-03-09 14:12:50 +00:00
Myles 463327c2a7 Bump version to 0.6.1 snapshot 2016-03-09 12:09:24 +00:00
Myles b0050d4a8d Add config option for blocking and fix crash due to synchronization 2016-03-09 12:08:21 +00:00
Myles a743895c3f Bump version to 0.6.0-SNAPSHOT 2016-03-09 01:13:24 +00:00
Myles f65666b7a6 Better support for ServerConnection detection, and also adding injectors. (Basic late-bind support is now available, but does not work with ProtocolLib due to it injecting first.) 2016-03-09 00:51:50 +00:00
Myles 3a217503fc Merge pull request #179 from HugoDaBosss/master
Stop error fetching hand item spamming console.
2016-03-08 21:24:47 +00:00
Myles c71b75e13b Oops 2016-03-08 21:23:57 +00:00
HugoDaBosss 0c890c3a30 Print errors while in debug mode 2016-03-08 22:23:36 +01:00
HugoDaBosss f38bb0ca22 Stop error fetching hand item spamming console. 2016-03-08 22:20:52 +01:00
Myles 2144fa1837 Handle any exception so it doesn't implode. (Still prints to the console.) 2016-03-08 21:16:34 +00:00
Myles fc4a617da7 Don't send chunk packets with no chunks :) 2016-03-08 21:13:15 +00:00
Myles 126ee6e03f Formatting 2016-03-08 20:54:03 +00:00
Myles 498867032f Merge pull request #178 from HugoDaBosss/master
Fix animation for bows
2016-03-08 20:51:02 +00:00
HugoDaBosss aef8eca790 Fix animation for bows 2016-03-08 21:48:21 +01:00
Myles d8bbb51721 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-03-08 19:27:24 +00:00
Myles 6e4fd5a63b Only show blocking if it knows that we're blocking #176 2016-03-08 19:27:04 +00:00
Myles e7bd6245c2 Merge pull request #175 from Matsv/master
Reimplement bossbar methods
2016-03-08 14:02:18 +00:00
Mats 6242cb0b47 Merge remote-tracking branch 'origin/master' 2016-03-08 13:48:20 +01:00
Mats bf5072e1cf Add removed bossbar methods 2016-03-08 13:48:03 +01:00
Mats c24b673550 Add removed bossbar methods 2016-03-08 13:46:30 +01:00
Myles dfc1e1cf51 Merge pull request #174 from Matsv/master
Add /viaversion debug to the commandlist
2016-03-08 12:42:16 +00:00
Mats c600ab6dd1 Add /viaversion debug to the commandlist 2016-03-08 13:30:53 +01:00
Myles 29754c0787 Bump version 2016-03-07 23:53:15 +00:00
Myles 9144980474 Read full dig packet 2016-03-07 23:52:12 +00:00
Myles 6a449f8db1 Allow the suppressing of metadata errors. 2016-03-07 22:55:57 +00:00
Myles 3780210f76 Merge branch 'master' of https://github.com/MylesIsCool/ViaVersion 2016-03-07 22:21:47 +00:00
Myles 67bad0dec8 Add it so when you're on 1.9 you can block using shields. Also change ConnectionInfo to use lombok. 2016-03-07 22:21:32 +00:00
Hugo Kerstens 79291fd7d9 Merge pull request #171 from Matsv/jukeboxfixje
Fix jukebox
2016-03-07 23:10:23 +01:00
Mats ee9d8d6365 Add comment for other people 2016-03-07 23:08:34 +01:00
Mats cc354db464 Formatting 2016-03-07 23:07:17 +01:00
Mats 2b29d27b0d Fix jukebox 2016-03-07 23:04:24 +01:00
Myles 75db62ee6f Merge pull request #167 from rj0495/patch-1
Added fallback options on CommandHandler
2016-03-07 20:53:11 +00:00
Myles 7cd7b5ba24 Be nice and set a user agent for updater 2016-03-07 20:13:01 +00:00
Ryan James a3bfcefdca Added fallback options on CommandHandler 2016-03-07 19:39:10 +00:00
Myles 098b787355 Update to 0.5.8-SNAPSHOT 2016-03-07 19:36:47 +00:00
Myles abb9665813 Merge pull request #166 from StamBoom/master
Change DataInputStream / DataOutputStream to readNBT / writeNBT
2016-03-07 19:30:41 +00:00
Myles 012eec47b5 Temp arrays are evil, (memory optimisation) 2016-03-07 19:19:14 +00:00
Mats 2d40afa3a1 Change DataInputstream / Outputstream to readNBT / writeNBT 2016-03-07 19:58:07 +01:00
Myles a92a7d6e02 Merge pull request #165 from StamBoom/savedthehorses
Fixed horses inventory/elytra exception
2016-03-07 18:52:11 +00:00
Myles fc7cdb4244 Clear bytes instead of reading them, close streams when done. (May fix a few memory leaks) 2016-03-07 18:51:18 +00:00
Mats d5b375b264 Fixed horses inventory/elytra exception 2016-03-07 19:45:00 +01:00
Myles 99eadbe343 Update readme 2016-03-07 16:50:50 +00:00
Myles 38d33dba16 Remove more methods (Sorry last one didn't build!) 2016-03-07 16:44:55 +00:00
Myles b3de4de0cd Remove us.myles.ViaVersion.chunks, I must have looked past this but it's not used. 2016-03-07 16:34:22 +00:00
Myles 6b5c166a22 Merge pull request #162 from phenomax/master
General code improvements
2016-03-07 16:28:04 +00:00
Phenomax 1aea00036f [~] smaller bugfixes]
[~] switched back to jdk 7
2016-03-07 16:22:11 +01:00
Phenomax 1262847a0e [+] added lombok in order to smaller code by removing unnecessary getter, setter and constructors
[~] switched to bytecode version 1.8 (lambda expressions)
[~] general code cleanup (lambda expressions, for each, collapsed catch blocks, diamond maps)
2016-03-07 15:43:31 +01:00
Myles 21cfb1297f Fix powered minecart data 2016-03-07 11:51:51 +00:00
Myles 0b1cb61986 Send team at difficulty to avoid any issues with bungee #161 2016-03-07 11:31:04 +00:00
Myles 44907b3e8d Add /viaversion autoteam to toggle auto teaming for 1.8 colliding. 2016-03-07 11:09:43 +00:00
Myles dac616d72c Bump snapshot version up 2016-03-06 23:42:27 +00:00
Myles 528b234d5a Add collision options, fixes #95. (By default auto teams players until they're added to a team so you can't push!) 2016-03-06 23:22:45 +00:00
HugoDaBosss e4288383f4 Merge pull request #159 from HugoDaBosss/patch
Change package name from bossbarapi to lowercase.
2016-03-06 23:39:52 +01:00
BuildTools bb17eb01b8 Update 2016-03-06 23:17:51 +01:00
Myles ca6638c740 return null if the item is null :) 2016-03-06 21:40:15 +00:00
Myles d8ce66ce29 Merge pull request #158 from StamBoom/bossbar
Implement 1.9 BossBarAPI for developers
2016-03-06 18:35:55 +00:00
Mats 8460c157a5 Commit API 2016-03-06 19:27:26 +01:00
Mats 0b807569ad Implement 1.9 BossBarAPI for developers 2016-03-06 19:20:39 +01:00
Myles 75d001d09b Merge pull request #157 from rj0495/patch-3
Travis Build Status
2016-03-06 17:37:37 +00:00
Ryan James 2118379cf7 Travis Build Status 2016-03-06 17:35:54 +00:00
Myles cd2441ee52 Update README.md 2016-03-06 17:22:56 +00:00
Myles ffb4fb5c5a Merge pull request #155 from sgdc3/master
Improve POM and fix dead code
2016-03-06 16:48:41 +00:00
Myles c404f2206c Blame a class when the childHandler doesn't inject 2016-03-06 16:16:26 +00:00
Gabriele C aec5aa48da Bump 2016-03-06 16:38:58 +01:00
Gabriele C b63051a796 Improve POM and fix dead code 2016-03-06 16:36:54 +01:00
Myles ea4650000e Bump to 0.5.5 2016-03-06 15:16:36 +00:00
Myles 2d2018b8d0 Disable latest feature due to it breaking signs (no more sync chunks for now) 2016-03-06 15:10:54 +00:00
HugoDaBosss 736a853a85 Merge pull request #153 from HugoDaBosss/patch
Make Metadata Rewriter exception output more clear
2016-03-06 16:00:50 +01:00
HugoDaBosss dfd4c5f93e Formatting 2016-03-06 15:55:53 +01:00
HugoDaBosss 2ac87acc8a Make Metadata Rewriter exception output more clear 2016-03-06 15:52:06 +01:00
Myles 3c5a6a3b7b Fix README, also change a bit of the fixJson so that it can handle quotes on signs. 2016-03-06 14:40:23 +00:00
Myles 6efb5c1b64 Merge pull request #151 from HugoDaBosss/patch
Fix checkforupdates changing from false to true
2016-03-06 14:20:45 +00:00
HugoDaBosss 91de7e5a22 Fix checkforupdates changing from false to true
FIXED:
When starting the server when checkforupdates is false, it won't register the listener.
So when you enable checkforupdates using /viaversion dontbugme it won't send you messages until a restart.
2016-03-06 15:11:36 +01:00
Myles 1c42ae1ee8 Update version to 0.5.4 2016-03-06 13:52:38 +00:00
Myles c5ac3c9b3d Don't freeze current thread when sending chunks 2016-03-06 13:49:33 +00:00
Myles 0ea32b3318 Merge pull request #150 from HugoDaBosss/patch
Fix mob spawners when no EntityId is given
2016-03-06 13:45:56 +00:00
Myles 8afc850ed3 Add new config option "sync-chunks", chunks will now be sent in sync with the MC thread when true, this fixes timings (paper spigot mostly issue) 2016-03-06 13:45:26 +00:00
HugoDaBosss 3c6dcfe5bf Update OutgoingTransformer.java 2016-03-06 14:42:50 +01:00
HugoDaBosss 59d637e0f5 More formatting (stupid eclipse) 2016-03-06 14:42:22 +01:00
HugoDaBosss 923f3088c0 Formatting 2016-03-06 14:40:52 +01:00
HugoDaBosss 4f8aff9c01 Forgot to remove debug message 2016-03-06 14:37:51 +01:00
HugoDaBosss 99ceb9ae79 Fix mob spawners when no EntityId is given 2016-03-06 14:32:57 +01:00
Myles 6e0554f4a4 Fix enchanting tooltips 2016-03-06 13:22:56 +00:00
Myles 36879f8d02 Fix small issue with updater 2016-03-06 13:02:54 +00:00
Myles fe77df1434 Fix brewing #141 2016-03-06 12:25:54 +00:00
Myles 713361f973 Merge pull request #148 from StamBoom/master
Fix commandblock minecarts
2016-03-06 11:20:50 +00:00
Mats a314b86f57 Fix commandblock minecarts 2016-03-06 12:18:18 +01:00
Myles 840c90f871 Don't use GSON >.> 2016-03-06 11:03:41 +00:00
Myles 2a247595c8 Handle invalid version numbers 2016-03-06 10:49:21 +00:00
Myles 4124c3454e Change it so when there is no connection we don't bug them. Also change it to use http instead of https, as https requires certain certificate info by linux. 2016-03-06 10:46:38 +00:00
HugoDaBosss c4185e3056 Merge pull request #147 from fillefilip8/patch-4
Made the config use the default bukkit config methods insteed.
2016-03-06 10:56:07 +01:00
fillefilip8 d6403d495d Opps :) Github likes me :D Removed the new api methods from this branch :D 2016-03-06 10:42:26 +01:00
fillefilip8 d7f54048ff Made the config use the default bukkit config methods insteed. 2016-03-06 10:39:58 +01:00
Myles e487eeb395 Update to 0.5.3, add inventory title tracking so we're working towards some of the inventory bugs with new ones. 2016-03-06 00:25:24 +00:00
Myles 0d0e1c16ea Fix issue with formatting :) (fixes quotes) 2016-03-05 23:24:23 +00:00
Myles f462ff9e8a Fix weird closedchannel bug 2016-03-05 22:16:43 +00:00
Myles 5582556d8a Fix issue with biomes on chunks, #125 2016-03-05 22:05:17 +00:00
Myles ef6214a442 Fix getHandItem across reloads, though half the things will still break on reload :( 2016-03-05 21:23:14 +00:00
Myles 369710333c Change updating so it doesn't tell you on current version up to date but warns if you're on a newer version than expected / older one in console. 2016-03-05 21:15:51 +00:00
Myles 30c4fea044 Add new /viaversion dontbugme, change method if the version looks like it's custom / debug (not compiled by maven) 2016-03-05 20:54:35 +00:00
Myles eccc5091b5 Merge pull request #139 from HugoDaBosss/master
Added proper update message (based on checkplys)
2016-03-05 20:40:48 +00:00
HugoDaBosss 65770d7c5b Added proper update message 2016-03-05 21:37:12 +01:00
Myles 715e873bae Bump version to 0.5.2 2016-03-05 20:21:21 +00:00
Myles eced599818 Merge pull request #138 from StamBoom/master
Fix commandblocks
2016-03-05 20:06:54 +00:00
Mats 6db7755633 Fix commandblocks 2016-03-05 20:36:06 +01:00
Myles 653c3d3984 Merge pull request #131 from StamBoom/patch
Fix book formatting and invalid book tag at empty book
2016-03-05 19:18:39 +00:00
HugoDaBosss 5ca841837d Added BungeeCord to the Issue Template 2016-03-05 20:04:16 +01:00
HugoDaBosss 554e037044 Merge pull request #133 from fillefilip8/patch-2
Fixed some maven warnings.
2016-03-05 19:48:26 +01:00
fillefilip8 457d7e4777 Fixed some maven warnings. 2016-03-05 14:37:01 +01:00
Mats b3dc465498 Remove debug message 2016-03-05 11:35:32 +01:00
Mats c56109a64c Fix book formatting and invalid book tag at empty book 2016-03-05 11:30:17 +01:00
Myles d5e720fe09 Merge pull request #130 from HugoDaBosss/patch-8
Fix spawners showing the correct mob
2016-03-05 00:28:24 +00:00
HugoDaBosss a42526bb88 Small formatting 2016-03-05 01:24:15 +01:00
HugoDaBosss bd5f44b477 Fixed spawners showing the correct mob 2016-03-05 01:21:37 +01:00
Myles d5d8881677 Add debug to show metadata ID on error 2016-03-04 23:30:37 +00:00
Myles ac2178a247 Add debug mode so we can analyse packets 2016-03-04 23:10:07 +00:00
Myles 24fa8aec35 Removed channel closed exception 2016-03-04 23:07:22 +00:00
Myles 2ba92a0d47 Merge pull request #126 from HugoDaBosss/herobrine
Removed Herobrine.
2016-03-04 23:03:45 +00:00
HugoDaBosss ace178834e Removed Herobrine. 2016-03-05 00:00:50 +01:00
HugoDaBosss 9c88d0a37f Merge pull request #10 from MylesIsCool/master
Update from master
2016-03-04 23:54:38 +01:00
Myles bafc1b6799 Merge pull request #122 from HugoDaBosss/patch-7
Fixed double flint and steel sound and added support to ignore sounds in 1.9
2016-03-04 22:29:39 +00:00
HugoDaBosss c9a575f45d Merge pull request #9 from MylesIsCool/master
Update Version I accidentally deployed debug version - 0.5.1
2016-03-04 23:23:44 +01:00
HugoDaBosss c071c895e7 Fixed double flint and steel sound and added support to ignore sounds in
1.9
2016-03-04 22:58:40 +01:00
Myles a8799bd493 Update Version I accidentally deployed debug version - 0.5.1 2016-03-04 21:51:56 +00:00
HugoDaBosss 20d4a94792 Merge pull request #8 from MylesIsCool/master
Update from master
2016-03-04 22:33:12 +01:00
Myles 89e0948f97 Updated version to 0.5.0 :) 2016-03-04 21:21:51 +00:00
Myles 6fe3c15f7d Remove 1.9 chunk unloading, should fix #38 2016-03-04 21:16:12 +00:00
Myles fb5dace6a6 Add armour, based on HugoDaBoss code but modified to work correctly with shift click. Also fix small issue from last commit. 2016-03-04 20:03:46 +00:00
Myles f71e51c85e Add packet sending to API 2016-03-04 19:24:44 +00:00
HugoDaBosss 0dd530a593 Merge pull request #7 from MylesIsCool/master
Update from master
2016-03-04 14:43:10 +01:00
Myles 12df86a142 As per wiki.vg only unload if bitmask = 0 and full chunk (not sure if this fixes chunk issue) 2016-03-04 10:09:06 +00:00
Myles 963f021226 Fix books, also makes ItemSlotRewriter.ItemStack fields public 2016-03-04 10:04:50 +00:00
Myles cb4a8b24d4 Merge pull request #113 from fillefilip8/patch-1
Some README.md fixes.
2016-03-04 09:10:05 +00:00
fillefilip8 76c908b132 Update README.md 2016-03-04 10:05:44 +01:00
Myles 89311af76a Small issue with README 2016-03-04 09:05:05 +00:00
fillefilip8 1ecf515006 Fixed README formatting. 2016-03-04 09:58:31 +01:00
Myles 5c18028577 Bump version to 0.4.9 2016-03-04 08:14:26 +00:00
Myles 678a7de664 Correct README 2016-03-04 01:02:35 +00:00
Myles 0aa190353e Add potions, including splash. 2016-03-04 01:01:04 +00:00
Myles a42b113618 Use new JSONParsers or they all implode. 2016-03-03 23:40:09 +00:00
Myles 2704611977 Cancel sounds properly, fixes block placing issue on bungee. Updated version to 0.4.8 2016-03-03 22:48:17 +00:00
Myles be6245e693 Bump version 0.4.7 2016-03-03 22:46:17 +00:00
Myles d7b7c4916a Read any remaining bytes, not sure if this fixes any errors but we ideally should to prevent issues. 2016-03-03 22:01:49 +00:00
Myles caae4e4cca Merge pull request #108 from gigosaurus/patch-2
Fix some MalformedJsonExceptions
2016-03-03 21:33:57 +00:00
gigosaurus ee58fbedbe Fix some MalformedJsonExceptions
This should fix the last possible cause of issue #70
2016-03-03 21:28:40 +00:00
Myles a84b45f5dd Add new contributor, make format of output match spigot 2016-03-03 21:15:20 +00:00
Myles c2edf45846 Change package for slot rewriter. 2016-03-03 21:06:36 +00:00
Myles 88ff4ee9ca Merge pull request #96 from Mystalion/spawnegg-and-potions
support for rewriting SpawnEggs
2016-03-03 21:03:50 +00:00
Paulomart fd704f6a29 Merge remote-tracking branch 'origin/spawnegg-and-potions'
Conflicts:
	src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java
	src/main/java/us/myles/ViaVersion/util/PacketUtil.java
2016-03-03 21:38:16 +01:00
Paulomart c97b443cf2 I dont even Java. 2016-03-03 21:32:01 +01:00
Paulomart 00df80e6fd Replace nms code with fancy library and own code. 2016-03-03 21:31:56 +01:00
Paulomart 64c2ba243f Basic support for rewriting SpawnEggs and Potions, still needs more work 2016-03-03 21:31:50 +01:00
Myles 0ad2e6478d Merge pull request #103 from StamBoom/master
Fix skin overlay
2016-03-03 19:56:55 +00:00
Myles ab9f786999 Don't send a signed byte for digging. 2016-03-03 19:56:00 +00:00
Mats e826b339f6 Fixed missing Player metadata 2016-03-03 20:49:29 +01:00
Mats f06851f57a Fix skin overlay 2016-03-03 20:37:46 +01:00
Myles 1a90f0eb28 Use new method for finding cause, might need updating with disconnect. Can't replicate disconnect spam on any version on my machine. Also move to JSON for all because older versions don't have GSON :( in main package 2016-03-03 19:24:37 +00:00
Myles fee986d215 Make the injectors work in any 1.8 version. Now looks through fields for suitable in case of different field names also construct slot using known arguments. 2016-03-03 18:12:10 +00:00
fillefilip8 9108e78491 Added more yml info and remove author name from the message in the command. 2016-03-03 18:30:13 +01:00
Myles 1b75526892 Implement changes to entity effect 2016-03-03 18:30:00 +01:00
fillefilip8 5930a83765 Added a command and a new API function "getVersion()" 2016-03-03 18:29:59 +01:00
fillefilip8 ef118a3a64 * One JavaDoc to the api XD
* Added faster way to change version number.
2016-03-03 17:33:47 +01:00
fillefilip8 bb42cda4a8 . 2016-03-03 17:33:28 +01:00
fillefilip8 121bc9de6c * Modifyed that fancy message when 1.9 clients try to enter a Minecart or a Boat :)
* Renamed the listener to something better.
2016-03-03 17:33:27 +01:00
fillefilip8 1e873c123c Added that fancy message when 1.9 clients try to enter a Minecart :) 2016-03-03 17:33:27 +01:00
Myles c704b3709a Implement changes to entity effect 2016-03-03 15:17:31 +00:00
HugoDaBosss 618e09b202 Merge pull request #6 from MylesIsCool/master
Update from master
2016-03-03 14:13:41 +01:00
Myles fd0bd53826 Bump version to 0.4.6 2016-03-03 13:07:57 +00:00
Myles e11c8320f0 Merge pull request #83 from StamBoom/master
Fix unmount
2016-03-03 12:56:54 +00:00
Myles 624595e9f6 Merge pull request #84 from HugoDaBosss/patch-4
Fix animals appearing as babies instead of parents
2016-03-03 12:56:37 +00:00
HugoDaBosss cc813545d8 Formatting 2016-03-03 12:22:54 +01:00
HugoDaBosss e1ba6e07c2 Fix animals appearing as babies instead of parent 2016-03-03 12:20:19 +01:00
Mats 1bf49b1f0b Fix unmount 2016-03-03 12:18:23 +01:00
HugoDaBosss 5e34fda7e4 Merge pull request #4 from MylesIsCool/master
Merge from master
2016-03-03 12:17:06 +01:00
Myles aa70ab8b78 Extra line 2016-03-03 10:37:43 +00:00
Myles 186ba22dc8 Update README with chat, and change issue template 2016-03-03 10:37:10 +00:00
Myles b10aa30d9b Change error correction to use super, should restore default functionality to errors. 2016-03-03 10:24:01 +00:00
Myles 615b9f847c Merge pull request #77 from HugoDaBosss/patch-2
Don't send malformed JSON anymore, preventing kicks.
2016-03-03 10:04:54 +00:00
Myles 8f132fed14 Merge pull request #64 from HugoDaBosss/master
Fixed double placing sound and small packet finding optimization. (I suck at github)
2016-03-03 10:04:33 +00:00
HugoDaBosss 854e24f8fc More formatting 2016-03-03 10:47:22 +01:00
HugoDaBosss ff0544f29a Eclipse is changing my bracket markup x.x 2016-03-03 10:46:38 +01:00
HugoDaBosss 72ae12bc77 Don't send malformed JSON anymore, preventing kicks. 2016-03-03 10:44:57 +01:00
HugoDaBosss 29d2334ef0 Fixed bracket markup ;) 2016-03-03 10:09:38 +01:00
HugoDaBosss afb96c4878 Fixed double break sound 2016-03-03 10:06:24 +01:00
HugoDaBosss e4346611c9 Small optimization 2016-03-03 01:40:24 +01:00
BuildTools f15e11272a Merge branch 'master' of https://github.com/HugoDaBosss/ViaVersion 2016-03-03 01:37:25 +01:00
HugoDaBosss 8764d24a16 Merge pull request #3 from MylesIsCool/master
Update from Fork
2016-03-03 01:37:25 +01:00
HugoDaBosss b6c2a46a86 Merge pull request #2 from MylesIsCool/master
Update From Original #2
2016-03-02 11:44:24 +01:00
179 changed files with 13537 additions and 2989 deletions

No files matched your search

+115 -2
View File
@@ -1,3 +1,116 @@
target/
.idea/
### Java files ###
*.class
# Package Files
#*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
*.iml
# Ignore IDEA directory
.idea/*
# Include the project's code style settings file
!.idea/codeStyleSettings.xml
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!.gitignore
+12
View File
@@ -0,0 +1,12 @@
sudo: false
language: java
jdk: oraclejdk7
cache:
directories:
- '$HOME/.m2/repository'
script:
- mvn dependency:purge-local-repository -DactTransitively=false -DreResolve=false
- mvn clean install -B -U
+12
View File
@@ -0,0 +1,12 @@
### What version of ViaVersion are you using? Type /ver viaversion
### What version of Spigot are you using? Type /ver
### What plugins are you using? Type /plugins
### Are you using any additional software like BungeeCord? If so, what software and version? (Please list your plugins as well)
### How does this error happen? login? Using an item?
### Is there an error in the console? Use pastebin.com. Is there a kick message?
+24
View File
@@ -0,0 +1,24 @@
License:
--------
MIT License
Copyright (c) 2016
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+48 -17
View File
@@ -1,20 +1,15 @@
# ViaVersion 0.4.5
**Allows the connection of 1.8 clients to 1.9**
# ViaVersion 0.9.8
[![Build Status](https://travis-ci.org/MylesIsCool/ViaVersion.svg?branch=master)](https://travis-ci.org/MylesIsCool/ViaVersion)
[![Gitter](https://badges.gitter.im/MylesIsCool/ViaVersion.svg)](https://gitter.im/MylesIsCool/ViaVersion)
This plugin modifies netty to allow connection of 1.9 clients to 1.8,
**Allows the connection of higher client versions to lower server versions**
**Don't use late bind*
Allows 1.10, 1.9 on 1.8 server and 1.10 on a 1.9 server.
**As of this point it doesn't have everything, I need to fix:**
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
Attempt to make boats nicer when they don't work
**Contributor Chat:** https://gitter.im/MylesIsCool/ViaVersion
Remap spawn eggs
If you have a bug with entities, please report the full stack trace
This took hours of work, so if you enjoy this consider looking into contacting me and supporting my projects.
Sources:
@@ -22,22 +17,58 @@ Sources:
**wiki.vg** (Protocol info, though I did have to find a lot myself)
**MCProtocolLib** (used for chunk reading & some of writing.)
**Burger** We use this tool to get protocol and other useful information for new / undocumented Minecraft versions
Contributors:
**OpenNBT** (used for slot rewriting)
All Time Contributors:
--------
**Myself** (harhar)
**Matsv/StamBoom**
**Matsv**
**HugoDaBosss**
**SanderGielisse**
**Paulomart**
**gigosaurus**
**fillefilip8**
**lenis0012**
**fuzzy_bot**
**joserobjr**
Releases / Dev Builds:
--------
You can find official releases here:
https://www.spigotmc.org/resources/viaversion.19254/history
----------
You can find official dev builds here:
**Jenkins:** https://ci.viaversion.com
**JavaDocs:** https://jd.viaversion.com
**Maven Repo:** https://repo.viaversion.com
License:
--------
You may modify this work, all rights are still owned by myself excluding any files in the spacebase package as they belong to the respected contributors. Please credit the original author (myself) when forking etc. (or if it helped you understand the new protocol or netty!)
MIT License, see LICENSE for more details.
Thanks!
Thanks!
+11
View File
@@ -0,0 +1,11 @@
machine:
java:
version: oraclejdk7
general:
artifacts:
- "target/*.jar"
test:
override:
- mvn clean install -B
post:
- cp ./target/*.jar $CIRCLE_ARTIFACTS
+188 -19
View File
@@ -1,54 +1,223 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>us.myles</groupId>
<artifactId>ViaVersion</artifactId>
<version>1.0-SNAPSHOT</version>
<artifactId>viaversion</artifactId>
<version>0.9.8</version>
<packaging>jar</packaging>
<name>ViaVersion</name>
<description>Allow 1.8 clients to join 1.9 bukkit servers!</description>
<inceptionYear>2016</inceptionYear>
<url>https://www.spigotmc.org/resources/viaversion.19254/</url>
<prerequisites>
<maven>3.3.3</maven>
</prerequisites>
<properties>
<!-- Project Properties -->
<projectEncoding>UTF-8</projectEncoding>
<project.build.sourceEncoding>${projectEncoding}</project.build.sourceEncoding>
<project.build.outputEncoding>${projectEncoding}</project.build.outputEncoding>
<jdkVersion>1.7</jdkVersion>
<!-- <testJreVersion>1.7</testJreVersion> -->
<!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.8.8-R0.1-SNAPSHOT</bukkitVersion>
</properties>
<build>
<finalName>${project.name}-${project.version}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<defaultGoal>clean install</defaultGoal>
<!-- <testSourceDirectory>src/test/java</testSourceDirectory> -->
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>false</filtering>
<directory>.</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
<!--
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
-->
<plugins>
<!-- Maven Java Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>${jdkVersion}</source>
<target>${jdkVersion}</target>
<!--
<testSource>${testJreVersion}</testSource>
<testTarget>${testJreVersion}</testTarget>
-->
</configuration>
</plugin>
<!-- Unit Test Plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=${projectEncoding} ${argLine}</argLine>
</configuration>
</plugin>
-->
<!-- Libs Shading and Relocation -->
<plugin>
<!--Relocate all lib we use in order to fix class loading errors if we use different versions
than already loaded libs (i.e. by Mojang -> gson)-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.spacehq.opennbt</pattern>
<shadedPattern>us.myles.viaversion.libs.opennbt</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>us.myles.viaversion.libs.gson</shadedPattern>
</relocation>
<relocation>
<pattern>org.javassist</pattern>
<shadedPattern>us.myles.viaversion.libs.javassist</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<!-- SpigotMC Repo (Bukkit API) -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
</repository>
<!-- SpaceHQ Repo-->
<repository>
<id>spacehq-repo</id>
<url>https://repo.spacehq.org/content/repositories/releases/</url>
</repository>
<!-- Bungee repo -->
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<dependencies>
<!-- Bukkit API, http://www.spigotmc.org/ or http://bukkit.org/ -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8.8-R0.1-SNAPSHOT</version>
<version>${bukkitVersion}</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
</exclusion>
<exclusion>
<artifactId>persistence-api</artifactId>
<groupId>javax.persistence</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Javassist (Bytecode Library) -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- NBT Edit Library -->
<dependency>
<groupId>org.spacehq</groupId>
<artifactId>opennbt</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- GSON (JSON Library) -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- Netty (Network Library) -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.20.Final</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.4</version>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
<scope>provided</scope>
</dependency>
<!--Bungeecord-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
</project>
@@ -1,126 +0,0 @@
package org.spacehq.mc.protocol.data.game.chunk;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.util.PacketUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BlockStorage {
private int bitsPerEntry;
private List<Integer> states;
private FlexibleStorage storage;
public BlockStorage() {
this.bitsPerEntry = 4;
this.states = new ArrayList<Integer>();
this.states.add(0);
this.storage = new FlexibleStorage(this.bitsPerEntry, 4096);
}
public BlockStorage(ByteBuf in) throws IOException {
this.bitsPerEntry = in.readUnsignedByte();
this.states = new ArrayList<Integer>();
int stateCount = PacketUtil.readVarInt(in);
for (int i = 0; i < stateCount; i++) {
this.states.add(PacketUtil.readVarInt(in));
}
this.storage = new FlexibleStorage(this.bitsPerEntry, PacketUtil.readLongs(PacketUtil.readVarInt(in), in));
}
public void write(ByteBuf out) throws IOException {
out.writeByte(this.bitsPerEntry);
PacketUtil.writeVarInt(this.states.size(), out);
for (int state : this.states) {
PacketUtil.writeVarInt(state, out);
}
long[] data = this.storage.getData();
PacketUtil.writeVarInt(data.length, out);
PacketUtil.writeLongs(data, out);
}
public int getBitsPerEntry() {
return this.bitsPerEntry;
}
public List<Integer> getStates() {
return Collections.unmodifiableList(this.states);
}
public FlexibleStorage getStorage() {
return this.storage;
}
public int get(int x, int y, int z) {
int id = this.storage.get(index(x, y, z));
return this.bitsPerEntry <= 8 ? (id >= 0 && id < this.states.size() ? this.states.get(id) : 0) : id;
}
public void set(int x, int y, int z, int state) {
set(index(x, y, z), state);
}
public void set(int ind, int state) {
int id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : state;
if (id == -1) {
this.states.add(state);
if (this.states.size() > 1 << this.bitsPerEntry) {
this.bitsPerEntry++;
List<Integer> oldStates = this.states;
if (this.bitsPerEntry > 8) {
oldStates = new ArrayList<Integer>(this.states);
this.states.clear();
this.bitsPerEntry = 13;
}
FlexibleStorage oldStorage = this.storage;
this.storage = new FlexibleStorage(this.bitsPerEntry, this.storage.getSize());
for (int index = 0; index < this.storage.getSize(); index++) {
int value = oldStorage.get(index);
this.storage.set(index, this.bitsPerEntry <= 8 ? value : oldStates.get(value));
}
}
id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : state;
}
this.storage.set(ind, id);
}
public boolean isEmpty() {
for (int index = 0; index < this.storage.getSize(); index++) {
if (this.storage.get(index) != 0) {
return false;
}
}
return true;
}
private static int index(int x, int y, int z) {
return y << 8 | z << 4 | x;
}
@Override
public boolean equals(Object o) {
return this == o || (o instanceof BlockStorage && this.bitsPerEntry == ((BlockStorage) o).bitsPerEntry && this.states.equals(((BlockStorage) o).states) && this.storage.equals(((BlockStorage) o).storage));
}
@Override
public int hashCode() {
int result = this.bitsPerEntry;
result = 31 * result + this.states.hashCode();
result = 31 * result + this.storage.hashCode();
return result;
}
}
@@ -1,46 +0,0 @@
package org.spacehq.mc.protocol.data.game.chunk;
public class Chunk {
private BlockStorage blocks;
private NibbleArray3d blocklight;
private NibbleArray3d skylight;
public Chunk(boolean skylight) {
this(new BlockStorage(), new NibbleArray3d(2048), skylight ? new NibbleArray3d(2048) : null);
}
public Chunk(BlockStorage blocks, NibbleArray3d blocklight, NibbleArray3d skylight) {
this.blocks = blocks;
this.blocklight = blocklight;
this.skylight = skylight;
}
public BlockStorage getBlocks() {
return this.blocks;
}
public NibbleArray3d getBlockLight() {
return this.blocklight;
}
public NibbleArray3d getSkyLight() {
return this.skylight;
}
public boolean isEmpty() {
return this.blocks.isEmpty();
}
@Override
public boolean equals(Object o) {
return this == o || (o instanceof Chunk && this.blocks.equals(((Chunk) o).blocks) && this.blocklight.equals(((Chunk) o).blocklight) && ((this.skylight == null && (((Chunk) o).skylight == null)) || (this.skylight != null && this.skylight.equals(((Chunk) o).skylight))));
}
@Override
public int hashCode() {
int result = this.blocks.hashCode();
result = 31 * result + this.blocklight.hashCode();
result = 31 * result + (this.skylight != null ? this.skylight.hashCode() : 0);
return result;
}
}
@@ -1,69 +0,0 @@
package org.spacehq.mc.protocol.data.game.chunk;
public class Column {
private int x;
private int z;
private Chunk chunks[];
private byte biomeData[];
private boolean skylight;
public Column(int x, int z, Chunk chunks[]) {
this(x, z, chunks, null);
}
public Column(int x, int z, Chunk chunks[], byte biomeData[]) {
if(chunks.length != 16) {
throw new IllegalArgumentException("Chunk array length must be 16.");
}
if(biomeData != null && biomeData.length != 256) {
throw new IllegalArgumentException("Biome data array length must be 256.");
}
this.skylight = false;
boolean noSkylight = false;
for(int index = 0; index < chunks.length; index++) {
if(chunks[index] != null) {
if(chunks[index].getSkyLight() == null) {
noSkylight = true;
} else {
this.skylight = true;
}
}
}
if(noSkylight && this.skylight) {
throw new IllegalArgumentException("Either all chunks must have skylight values or none must have them.");
}
this.x = x;
this.z = z;
this.chunks = chunks;
this.biomeData = biomeData;
}
public int getX() {
return this.x;
}
public int getZ() {
return this.z;
}
public Chunk[] getChunks() {
return this.chunks;
}
public boolean hasBiomeData() {
return this.biomeData != null;
}
public byte[] getBiomeData() {
return this.biomeData;
}
public boolean hasSkylight() {
return this.skylight;
}
}
@@ -1,104 +0,0 @@
package org.spacehq.mc.protocol.data.game.chunk;
import java.util.Arrays;
public class FlexibleStorage {
private final long[] data;
private final int bitsPerEntry;
private final int size;
private final long maxEntryValue;
public FlexibleStorage(int bitsPerEntry, int size) {
this(bitsPerEntry, new long[roundToNearest(size * bitsPerEntry, 64) / 64]);
}
public FlexibleStorage(int bitsPerEntry, long[] data) {
if(bitsPerEntry < 1 || bitsPerEntry > 32) {
throw new IllegalArgumentException("BitsPerEntry cannot be outside of accepted range.");
}
this.bitsPerEntry = bitsPerEntry;
this.data = data;
this.size = this.data.length * 64 / this.bitsPerEntry;
this.maxEntryValue = (1L << this.bitsPerEntry) - 1;
}
public long[] getData() {
return this.data;
}
public int getBitsPerEntry() {
return this.bitsPerEntry;
}
public int getSize() {
return this.size;
}
public int get(int index) {
if(index < 0 || index > this.size - 1) {
throw new IndexOutOfBoundsException();
}
int bitIndex = index * this.bitsPerEntry;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64;
int startBitSubIndex = bitIndex % 64;
if(startIndex == endIndex) {
return (int) (this.data[startIndex] >>> startBitSubIndex & this.maxEntryValue);
} else {
int endBitSubIndex = 64 - startBitSubIndex;
return (int) ((this.data[startIndex] >>> startBitSubIndex | this.data[endIndex] << endBitSubIndex) & this.maxEntryValue);
}
}
public void set(int index, int value) {
if(index < 0 || index > this.size - 1) {
throw new IndexOutOfBoundsException();
}
if(value < 0 || value > this.maxEntryValue) {
throw new IllegalArgumentException("Value cannot be outside of accepted range.");
}
int bitIndex = index * this.bitsPerEntry;
int startIndex = bitIndex / 64;
int endIndex = ((index + 1) * this.bitsPerEntry - 1) / 64;
int startBitSubIndex = bitIndex % 64;
this.data[startIndex] = this.data[startIndex] & ~(this.maxEntryValue << startBitSubIndex) | ((long) value & this.maxEntryValue) << startBitSubIndex;
if(startIndex != endIndex) {
int endBitSubIndex = 64 - startBitSubIndex;
this.data[endIndex] = this.data[endIndex] >>> endBitSubIndex << endBitSubIndex | ((long) value & this.maxEntryValue) >> endBitSubIndex;
}
}
private static int roundToNearest(int value, int roundTo) {
if(roundTo == 0) {
return 0;
} else if(value == 0) {
return roundTo;
} else {
if(value < 0) {
roundTo *= -1;
}
int remainder = value % roundTo;
return remainder != 0 ? value + roundTo - remainder : value;
}
}
@Override
public boolean equals(Object o) {
return this == o || (o instanceof FlexibleStorage && Arrays.equals(this.data, ((FlexibleStorage) o).data) && this.bitsPerEntry == ((FlexibleStorage) o).bitsPerEntry && this.size == ((FlexibleStorage) o).size && this.maxEntryValue == ((FlexibleStorage) o).maxEntryValue);
}
@Override
public int hashCode() {
int result = Arrays.hashCode(this.data);
result = 31 * result + this.bitsPerEntry;
result = 31 * result + this.size;
result = 31 * result + (int) this.maxEntryValue;
return result;
}
}
@@ -1,71 +0,0 @@
package org.spacehq.mc.protocol.data.game.chunk;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import java.util.Arrays;
public class NibbleArray3d {
private byte[] data;
public NibbleArray3d(int size) {
this.data = new byte[size];
}
public NibbleArray3d(byte[] array) {
this.data = array;
}
public NibbleArray3d(ByteBuf in, int size) throws IOException {
this.data = new byte[size];
in.readBytes(this.data);
}
public void write(ByteBuf out) throws IOException {
out.writeBytes(this.data);
}
public byte[] getData() {
return this.data;
}
public int get(int x, int y, int z) {
int key = y << 8 | z << 4 | x;
int index = key >> 1;
int part = key & 1;
return part == 0 ? this.data[index] & 15 : this.data[index] >> 4 & 15;
}
public void set(int x, int y, int z, int val) {
int key = y << 8 | z << 4 | x;
int index = key >> 1;
int part = key & 1;
if(part == 0) {
this.data[index] = (byte) (this.data[index] & 240 | val & 15);
} else {
this.data[index] = (byte) (this.data[index] & 15 | (val & 15) << 4);
}
}
public void fill(int val) {
for(int index = 0; index < this.data.length << 1; index++) {
int ind = index >> 1;
int part = index & 1;
if(part == 0) {
this.data[ind] = (byte) (this.data[ind] & 240 | val & 15);
} else {
this.data[ind] = (byte) (this.data[ind] & 15 | (val & 15) << 4);
}
}
}
@Override
public boolean equals(Object o) {
return this == o || (o instanceof NibbleArray3d && Arrays.equals(this.data, ((NibbleArray3d) o).data));
}
@Override
public int hashCode() {
return Arrays.hashCode(this.data);
}
}
@@ -1,114 +0,0 @@
package org.spacehq.mc.protocol.util;
import io.netty.buffer.ByteBuf;
import org.spacehq.mc.protocol.data.game.chunk.Chunk;
import org.spacehq.mc.protocol.data.game.chunk.Column;
import org.spacehq.mc.protocol.data.game.chunk.NibbleArray3d;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
/* From https://github.com/Steveice10/MCProtocolLib/ */
/* No credit taken for writing this code, and used accordance to it's license
Original by Steveice10, modified to suit this plugin.
*/
public class NetUtil {
public static int writeNewColumn(ByteBuf out, Column column, boolean fullChunk, boolean hasSkylight) throws IOException {
int mask = 0;
Chunk chunks[] = column.getChunks();
for(int index = 0; index < chunks.length; index++) {
Chunk chunk = chunks[index];
if(chunk != null && (!fullChunk || !chunk.isEmpty())) {
mask |= 1 << index;
chunk.getBlocks().write(out);
chunk.getBlockLight().write(out);
if(hasSkylight || column.hasSkylight()) {
chunk.getSkyLight().write(out); // TODO: Make a PR to original lib to correct this
}
}
}
if(fullChunk) {
out.writeBytes(column.getBiomeData());
}
return mask;
}
public static Column readOldChunkData(int x, int z, boolean isFullChunk, int bitmask, byte[] input, boolean checkForSky, boolean hasSkyLight) {
int pos = 0;
int expected = isFullChunk ? 256 : 0;
boolean sky = false;
ShortBuffer buf = ByteBuffer.wrap(input).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
// 0 = Calculate expected length and determine if the packet has skylight.
// 1 = Create chunks from mask and get blocks.
// 2 = Get block light.
// 3 = Get sky light.
Chunk[] chunks = new Chunk[16];
for(int pass = 0; pass < 4; pass++) {
for(int ind = 0; ind < 16; ind++) {
if((bitmask & 1 << ind) != 0) {
if(pass == 0) {
// Block length + Blocklight length
expected += (4096 * 2) + 2048;
}
if(pass == 1) {
chunks[ind] = new Chunk(sky || hasSkyLight);
buf.position(pos / 2);
short[] tempData = new short[4096];
buf.get(tempData, 0, tempData.length);
// convert short array to new one
int index = 0;
for(short ss:tempData){
// s is 16 bits, 12 bits id and 4 bits data
int data = ss & 0xF;
int id = (ss >> 4) << 4 | data;
int newCombined = id ; // test
chunks[ind].getBlocks().set(index, newCombined);
index++;
}
pos += tempData.length * 2;
}
if(pass == 2) {
NibbleArray3d blocklight = chunks[ind].getBlockLight();
System.arraycopy(input, pos, blocklight.getData(), 0, blocklight.getData().length);
pos += blocklight.getData().length;
}
if(pass == 3) {
if(sky) {
NibbleArray3d skylight = chunks[ind].getSkyLight();
System.arraycopy(input, pos, skylight.getData(), 0, skylight.getData().length);
pos += skylight.getData().length;
}
}
}
}
if(pass == 0) {
// If we have more data than blocks and blocklight combined, there must be skylight data as well.
if(input.length > expected) {
sky = checkForSky;
}
}
}
byte biomeData[] = null;
if(isFullChunk) {
biomeData = new byte[256];
System.arraycopy(input, pos, biomeData, 0, biomeData.length);
}
Column column = new Column(x, z, chunks, biomeData);
return column;
}
}
@@ -0,0 +1,18 @@
package us.myles.ViaVersion;
import net.md_5.bungee.api.plugin.Plugin;
import static net.md_5.bungee.api.ChatColor.RED;
public class Bungee extends Plugin {
@Override
public void onEnable() {
getLogger().severe(RED + "===============================================");
getLogger().severe(RED + "ViaVersion is NOT a Bungeecord plugin");
getLogger().severe(RED + "Install this plugin on all your spigot/bukkit");
getLogger().severe(RED + "servers and use the latest Bungeecord version");
getLogger().severe(RED + "to make ViaVersion work with BungeeCord.");
getLogger().severe(RED + "===============================================");
}
}
@@ -1,4 +0,0 @@
package us.myles.ViaVersion;
public class CancelException extends Exception{
}
@@ -1,78 +0,0 @@
package us.myles.ViaVersion;
import io.netty.channel.socket.SocketChannel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.packets.State;
import java.util.UUID;
public class ConnectionInfo {
private final SocketChannel channel;
private Object lastPacket;
private java.util.UUID UUID;
private State state = State.HANDSHAKE;
private int protocol = 0;
private int compression = 0;
private boolean active = true;
public ConnectionInfo(SocketChannel socketChannel) {
this.channel = socketChannel;
}
public int getProtocol() {
return protocol;
}
public void setProtocol(int protocol) {
this.protocol = protocol;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void setCompression(int compression) {
this.compression = compression;
}
public int getCompression() {
return compression;
}
public void setLastPacket(Object lastPacket) {
this.lastPacket = lastPacket;
}
public Object getLastPacket() {
return lastPacket;
}
public void setUUID(UUID UUID) {
this.UUID = UUID;
}
public java.util.UUID getUUID() {
return UUID;
}
public Player getPlayer() {
return UUID == null ? null : Bukkit.getPlayer(UUID);
}
public SocketChannel getChannel() {
return channel;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
@@ -0,0 +1,188 @@
package us.myles.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.util.Configuration;
import java.io.File;
import java.util.List;
public class ViaConfig implements ViaVersionConfig {
private final ViaVersionPlugin plugin;
public ViaConfig(ViaVersionPlugin plugin) {
this.plugin = plugin;
generateConfig();
}
public void generateConfig() {
File file = new File(plugin.getDataFolder(), "config.yml");
if (file.exists()) {
// Update conf options
Configuration oldConfig = new Configuration(file);
oldConfig.reload(false); // Load current options from conf
file.delete(); // Delete old conf
plugin.saveDefaultConfig(); // Generate new conf
Configuration newConfig = new Configuration(file);
newConfig.reload(true); // Load default options
for (String key : oldConfig.getKeys(false)) {
// Set option in new conf if exists
if (newConfig.contains(key)) {
newConfig.set(key, oldConfig.get(key));
}
}
newConfig.save();
} else {
plugin.saveDefaultConfig();
}
}
@Override
public boolean isCheckForUpdates() {
return plugin.getConfig().getBoolean("checkforupdates", true);
}
@Override
public boolean isPreventCollision() {
return plugin.getConfig().getBoolean("prevent-collision", true);
}
@Override
public boolean isNewEffectIndicator() {
return plugin.getConfig().getBoolean("use-new-effect-indicator", true);
}
@Override
public boolean isShowNewDeathMessages() {
return plugin.getConfig().getBoolean("use-new-deathmessages", false);
}
@Override
public boolean isSuppressMetadataErrors() {
return plugin.getConfig().getBoolean("suppress-metadata-errors", false);
}
@Override
public boolean isShieldBlocking() {
return plugin.getConfig().getBoolean("shield-blocking", true);
}
@Override
public boolean isHologramPatch() {
return plugin.getConfig().getBoolean("hologram-patch", false);
}
@Override
public boolean isBossbarPatch() {
return plugin.getConfig().getBoolean("bossbar-patch", true);
}
@Override
public boolean isBossbarAntiflicker() {
return plugin.getConfig().getBoolean("bossbar-anti-flicker", false);
}
@Override
public boolean isUnknownEntitiesSuppressed() {
return false;
}
@Override
public double getHologramYOffset() {
return plugin.getConfig().getDouble("hologram-y", -0.96D);
}
@Override
public boolean isBlockBreakPatch() {
return false;
}
@Override
public int getMaxPPS() {
return plugin.getConfig().getInt("max-pps", 140);
}
@Override
public String getMaxPPSKickMessage() {
return plugin.getConfig().getString("max-pps-kick-msg", "Sending packets too fast? lag?");
}
@Override
public int getTrackingPeriod() {
return plugin.getConfig().getInt("tracking-period", 6);
}
@Override
public int getWarningPPS() {
return plugin.getConfig().getInt("tracking-warning-pps", 120);
}
@Override
public int getMaxWarnings() {
return plugin.getConfig().getInt("tracking-max-warnings", 3);
}
@Override
public String getMaxWarningsKickMessage() {
return plugin.getConfig().getString("tracking-max-kick-msg", "You are sending too many packets, :(");
}
@Override
public boolean isAntiXRay() {
return plugin.getConfig().getBoolean("anti-xray-patch", true);
}
@Override
public boolean isSendSupportedVersions() {
return plugin.getConfig().getBoolean("send-supported-versions", false);
}
@Override
public boolean isStimulatePlayerTick() {
return plugin.getConfig().getBoolean("simulate-pt", true);
}
@Override
public boolean isItemCache() {
return plugin.getConfig().getBoolean("item-cache", true);
}
@Override
public boolean isNMSPlayerTicking() {
return plugin.getConfig().getBoolean("nms-player-ticking", true);
}
@Override
public boolean isReplacePistons() {
return plugin.getConfig().getBoolean("replace-pistons", false);
}
@Override
public int getPistonReplacementId() {
return plugin.getConfig().getInt("replacement-piston-id", 0);
}
public boolean isAutoTeam() {
// Collision has to be enabled first
return isPreventCollision() && plugin.getConfig().getBoolean("auto-team", true);
}
@Override
public boolean isForceJsonTransform() {
return plugin.getConfig().getBoolean("force-json-transform", false);
}
@Override
public List<Integer> getBlockedProtocols() {
return plugin.getConfig().getIntegerList("block-protocols");
}
@Override
public String getBlockedDisconnectMsg() {
return plugin.getConfig().getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
}
@Override
public String getReloadDisconnectMsg() {
return plugin.getConfig().getString("reload-disconnect-msg", "Server reload, please rejoin!");
}
}
@@ -1,106 +1,529 @@
package us.myles.ViaVersion;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import lombok.Getter;
import lombok.NonNull;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionAPI;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.boss.ViaBossBar;
import us.myles.ViaVersion.classgenerator.ClassGenerator;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.update.UpdateListener;
import us.myles.ViaVersion.update.UpdateUtil;
import us.myles.ViaVersion.util.ConcurrentList;
import us.myles.ViaVersion.util.ListWrapper;
import us.myles.ViaVersion.util.ProtocolSupportUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
private final Set<UUID> portedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
private final Map<UUID, UserConnection> portedPlayers = new ConcurrentHashMap<>();
private List<ChannelFuture> injectedFutures = new ArrayList<>();
private List<Pair<Field, Object>> injectedLists = new ArrayList<>();
private ViaCommandHandler commandHandler;
private boolean debug = false;
private boolean compatSpigotBuild = false;
private boolean spigot = true;
private boolean lateBind = false;
private boolean protocolSupport = false;
@Getter
private ViaConfig conf;
public ViaVersionPlugin() {
// Check if we're using protocol support too
protocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
if (protocolSupport) {
getLogger().info("Patching to prevent concurrency issues...");
try {
patchLists();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onLoad() {
// Config magic
conf = new ViaConfig(this);
ViaVersion.setInstance(this);
// Handle reloads
if (System.getProperty("ViaVersion") != null) {
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib.");
for (Player player : Bukkit.getOnlinePlayers()) {
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', getConf().getReloadDisconnectMsg()));
}
} else {
getLogger().severe("ViaVersion is already loaded, this should work fine... Otherwise reboot the server!!!");
}
}
// Spigot detector
try {
Class.forName("org.spigotmc.SpigotConfig");
} catch (ClassNotFoundException e) {
spigot = false;
}
// Check if it's a spigot build with a protocol mod
try {
compatSpigotBuild = ReflectionUtil.nms("PacketEncoder").getDeclaredField("version") != null;
} catch (Exception e) {
compatSpigotBuild = false;
}
// Generate classes needed (only works if it's compat or ps)
ClassGenerator.generate();
lateBind = !isBinded();
getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!"));
if (!lateBind)
injectPacketHandler();
}
@Override
public void onEnable() {
ViaVersion.setInstance(this);
if(System.getProperty("ViaVersion") != null){
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
return;
}
getLogger().info("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
try {
if (lateBind)
injectPacketHandler();
if (conf.isCheckForUpdates())
UpdateUtil.sendUpdateMessage(this);
// Gather version :)
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
gatherProtocolVersion();
// Check if there are any pipes to this version
if (ProtocolRegistry.SERVER_PROTOCOL != -1) {
getLogger().info("ViaVersion detected protocol version: " + ProtocolRegistry.SERVER_PROTOCOL);
if (!ProtocolRegistry.isWorkingPipe()) {
getLogger().warning("ViaVersion will not function on the current protocol.");
}
}
ProtocolRegistry.refreshVersions();
}
});
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
getCommand("viaversion").setExecutor(commandHandler = new ViaCommandHandler());
getCommand("viaversion").setTabCompleter(commandHandler);
// Register Protocol Listeners
ProtocolRegistry.registerListeners();
// Warn them if they have anti-xray on and they aren't using spigot
if (conf.isAntiXRay() && !spigot) {
getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!");
}
}
@Override
public void onDisable() {
getLogger().info("ViaVersion is disabling, if this is a reload it may not work.");
uninject();
}
public void gatherProtocolVersion() {
try {
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
Class<?> pingClazz = ReflectionUtil.nms("ServerPing");
Object ping = null;
// Search for ping method
for (Field f : serverClazz.getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType().getSimpleName().equals("ServerPing")) {
f.setAccessible(true);
ping = f.get(server);
}
}
}
if (ping != null) {
Object serverData = null;
for (Field f : pingClazz.getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType().getSimpleName().endsWith("ServerData")) {
f.setAccessible(true);
serverData = f.get(ping);
}
}
}
if (serverData != null) {
int protocolVersion = -1;
for (Field f : serverData.getClass().getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType() == int.class) {
f.setAccessible(true);
protocolVersion = (int) f.get(serverData);
}
}
}
if (protocolVersion != -1) {
ProtocolRegistry.SERVER_PROTOCOL = protocolVersion;
return;
}
}
}
} catch (Exception e) {
e.printStackTrace();
// We couldn't work it out... We'll just use ping and hope for the best...
}
}
public Object getServerConnection() throws Exception {
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
Object connection = null;
for (Method m : serverClazz.getDeclaredMethods()) {
if (m.getReturnType() != null) {
if (m.getReturnType().getSimpleName().equals("ServerConnection")) {
if (m.getParameterTypes().length == 0) {
connection = m.invoke(server);
}
}
}
}
return connection;
}
public void injectPacketHandler() {
try {
Object connection = getServerConnection();
if (connection == null) {
getLogger().warning("We failed to find the ServerConnection? :( What server are you running?");
return;
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
// Inject the list
List wrapper = new ListWrapper((List) value) {
@Override
public synchronized void handleAdd(Object o) {
synchronized (this) {
if (o instanceof ChannelFuture) {
inject((ChannelFuture) o);
}
}
}
};
injectedLists.add(new Pair<>(field, connection));
field.set(connection, wrapper);
// Iterate through current list
synchronized (wrapper) {
for (Object o : (List) value) {
if (o instanceof ChannelFuture) {
inject((ChannelFuture) o);
} else {
break; // not the right list.
}
}
}
}
}
System.setProperty("ViaVersion", getDescription().getVersion());
} catch (Exception e) {
getLogger().severe("Unable to inject handlers, are you on 1.8? ");
e.printStackTrace();
}
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
setPorted(e.getPlayer().getUniqueId(), false);
}
}, this);
}
public void injectPacketHandler() throws Exception {
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
Object connection = serverClazz.getDeclaredMethod("getServerConnection").invoke(server);
List<ChannelFuture> futures = ReflectionUtil.get(connection, "g", List.class);
if (futures.size() == 0) {
throw new Exception("Could not find server to inject (Please ensure late-bind in your spigot.yml is false)");
public void patchLists() throws Exception {
Object connection = getServerConnection();
if (connection == null) {
getLogger().warning("We failed to find the ServerConnection? :( What server are you running?");
return;
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
if (!(value instanceof ConcurrentList)) {
ConcurrentList list = new ConcurrentList();
list.addAll((List) value);
field.set(connection, list);
}
}
}
}
public boolean isBinded() {
try {
Object connection = getServerConnection();
if (connection == null) {
return false;
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
// Inject the list
synchronized (value) {
for (Object o : (List) value) {
if (o instanceof ChannelFuture) {
return true;
} else {
break; // not the right list.
}
}
}
}
}
} catch (Exception e) {
}
return false;
}
private void inject(ChannelFuture future) {
try {
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
injectedFutures.add(future);
} catch (NoSuchFieldException e) {
// let's find who to blame!
ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader();
if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) {
PluginDescriptionFile yaml = ReflectionUtil.get(cl, "description", PluginDescriptionFile.class);
throw new Exception("Unable to inject, due to " + bootstrapAcceptor.getClass().getName() + ", try without the plugin " + yaml.getName() + "?");
} else {
throw new Exception("Unable to find childHandler, weird server version? " + bootstrapAcceptor.getClass().getName());
}
}
} catch (Exception e) {
getLogger().severe("Have you got late-bind enabled with something else?");
e.printStackTrace();
}
}
private void uninject() {
// TODO: Uninject from players currently online to prevent protocol lib issues.
for (ChannelFuture future : injectedFutures) {
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
if (oldInit instanceof ViaVersionInitializer) {
ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((ViaVersionInitializer) oldInit).getOriginal());
}
} catch (Exception e) {
System.out.println("Failed to remove injection... reload won't work with connections sorry");
}
}
injectedFutures.clear();
for (Pair<Field, Object> pair : injectedLists) {
try {
Object o = pair.getKey().get(pair.getValue());
if (o instanceof ListWrapper) {
pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList());
}
} catch (IllegalAccessException e) {
System.out.println("Failed to remove injection... reload might not work with connections sorry");
}
}
for (ChannelFuture future : futures) {
ChannelPipeline pipeline = future.channel().pipeline();
ChannelHandler bootstrapAcceptor = pipeline.first();
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
}
injectedLists.clear();
}
@Override
public boolean isPorted(Player player) {
return portedPlayers.contains(player.getUniqueId());
return isPorted(player.getUniqueId());
}
public void setPorted(UUID id, boolean value) {
if (value) {
portedPlayers.add(id);
@Override
public int getPlayerVersion(@NonNull Player player) {
if (!isPorted(player))
return getExternalVersion(player);
return portedPlayers.get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
}
@Override
public int getPlayerVersion(@NonNull UUID uuid) {
if (!isPorted(uuid))
return getExternalVersion(Bukkit.getPlayer(uuid));
return portedPlayers.get(uuid).get(ProtocolInfo.class).getProtocolVersion();
}
private int getExternalVersion(Player player) {
if (!isProtocolSupport()) {
return ProtocolRegistry.SERVER_PROTOCOL;
} else {
portedPlayers.remove(id);
return ProtocolSupportUtil.getProtocolVersion(player);
}
}
public static ItemStack getHandItem(final ConnectionInfo info) {
@Override
public boolean isPorted(UUID playerUUID) {
return portedPlayers.containsKey(playerUUID);
}
@Override
public String getVersion() {
return getDescription().getVersion();
}
public UserConnection getConnection(UUID playerUUID) {
return portedPlayers.get(playerUUID);
}
public UserConnection getConnection(Player player) {
return portedPlayers.get(player.getUniqueId());
}
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
sendRawPacket(player.getUniqueId(), packet);
}
@Override
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!");
UserConnection ci = portedPlayers.get(uuid);
ci.sendRawPacket(packet);
}
@Override
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
return new ViaBossBar(title, 1F, color, style);
}
@Override
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
return new ViaBossBar(title, health, color, style);
}
@Override
public boolean isDebug() {
return this.debug;
}
public void setDebug(boolean value) {
this.debug = value;
}
@Override
public ViaVersionCommand getCommandHandler() {
return commandHandler;
}
@Override
public boolean isCompatSpigotBuild() {
return compatSpigotBuild;
}
@Override
public SortedSet<Integer> getSupportedVersions() {
SortedSet<Integer> outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions());
outputSet.removeAll(getConf().getBlockedProtocols());
return outputSet;
}
@Override
public boolean isSpigot() {
return this.spigot;
}
public void addPortedClient(UserConnection info) {
portedPlayers.put(info.get(ProtocolInfo.class).getUuid(), info);
}
public void removePortedClient(UUID clientID) {
portedPlayers.remove(clientID);
}
public void run(final Runnable runnable, boolean wait) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(ViaVersionPlugin.class), new Callable<ItemStack>() {
Future f = Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Boolean>() {
@Override
public ItemStack call() throws Exception {
if (info.getPlayer() != null) {
return info.getPlayer().getItemInHand();
}
return null;
public Boolean call() throws Exception {
runnable.run();
return true;
}
}).get(10, TimeUnit.SECONDS);
});
if (wait) {
f.get(10, TimeUnit.SECONDS);
}
} catch (Exception e) {
System.out.println("Error fetching hand item ");
e.printStackTrace();
return null;
System.out.println("Failed to run task: " + e.getClass().getName());
if (ViaVersion.getInstance().isDebug())
e.printStackTrace();
}
}
public boolean isProtocolSupport() {
return protocolSupport;
}
public Map<UUID, UserConnection> getPortedPlayers() {
return portedPlayers;
}
public boolean handlePPS(UserConnection info) {
// Max PPS Checker
if (conf.getMaxPPS() > 0) {
if (info.getPacketsPerSecond() >= conf.getMaxPPS()) {
info.disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + ""));
return true; // don't send current packet
}
}
// Tracking PPS Checker
if (conf.getMaxWarnings() > 0 && conf.getTrackingPeriod() > 0) {
if (info.getSecondsObserved() > conf.getTrackingPeriod()) {
// Reset
info.setWarnings(0);
info.setSecondsObserved(1);
} else {
info.setSecondsObserved(info.getSecondsObserved() + 1);
if (info.getPacketsPerSecond() >= conf.getWarningPPS()) {
info.setWarnings(info.getWarnings() + 1);
}
if (info.getWarnings() >= conf.getMaxWarnings()) {
info.disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) info.getPacketsPerSecond()).intValue() + ""));
return true; // don't send current packet
}
}
}
return false;
}
}
@@ -0,0 +1,480 @@
package us.myles.ViaVersion.api;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.remapper.ValueCreator;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
import us.myles.ViaVersion.exception.InformativeException;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class PacketWrapper {
private final ByteBuf inputBuffer;
private final UserConnection userConnection;
private boolean send = true;
@Setter
@Getter
private int id = -1;
private LinkedList<Pair<Type, Object>> readableObjects = new LinkedList<>();
private List<Pair<Type, Object>> packetValues = new ArrayList<>();
public PacketWrapper(int packetID, ByteBuf inputBuffer, UserConnection userConnection) {
this.id = packetID;
this.inputBuffer = inputBuffer;
this.userConnection = userConnection;
}
/**
* Get a part from the output
*
* @param type The type of the part you wish to get.
* @param <T> The return type of the type you wish to get.
* @param index The index of the part (relative to the type)
* @return The requested type or throws ArrayIndexOutOfBounds
* @throws Exception If it fails to find it, an exception will be thrown.
*/
public <T> T get(Type<T> type, int index) throws Exception {
int currentIndex = 0;
for (Pair<Type, Object> packetValue : packetValues) {
if (packetValue.getKey() == type) { // Ref check
if (currentIndex == index) {
return (T) packetValue.getValue();
}
currentIndex++;
}
}
Exception e = new ArrayIndexOutOfBoundsException("Could not find type " + type.getTypeName() + " at " + index);
throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId()).set("Data", packetValues);
}
/**
* Check if a type is at an index
*
* @param type The type of the part you wish to get.
* @param index The index of the part (relative to the type)
* @return True if the type is at the index
*/
public boolean is(Type type, int index) {
int currentIndex = 0;
for (Pair<Type, Object> packetValue : packetValues) {
if (packetValue.getKey() == type) { // Ref check
if (currentIndex == index) {
return true;
}
currentIndex++;
}
}
return false;
}
/**
* Check if a type is at an index
*
* @param type The type of the part you wish to get.
* @param index The index of the part (relative to the type)
* @return True if the type is at the index
*/
public boolean isReadable(Type type, int index) {
int currentIndex = 0;
for (Pair<Type, Object> packetValue : readableObjects) {
if (packetValue.getKey().getBaseClass() == type.getBaseClass()) { // Ref check
if (currentIndex == index) {
return true;
}
currentIndex++;
}
}
return false;
}
/**
* Set a currently existing part in the output
*
* @param type The type of the part you wish to set.
* @param <T> The return type of the type you wish to set.
* @param index The index of the part (relative to the type)
* @param value The value of the part you wish to set it to.
* @throws Exception If it fails to set it, an exception will be thrown.
*/
public <T> void set(Type<T> type, int index, T value) throws Exception {
int currentIndex = 0;
for (Pair<Type, Object> packetValue : packetValues) {
if (packetValue.getKey() == type) { // Ref check
if (currentIndex == index) {
packetValue.setValue(value);
return;
}
currentIndex++;
}
}
Exception e = new ArrayIndexOutOfBoundsException("Could not find type " + type.getTypeName() + " at " + index);
throw new InformativeException(e).set("Type", type.getTypeName()).set("Index", index).set("Packet ID", getId());
}
/**
* Read a type from the input.
*
* @param type The type you wish to read
* @param <T> The return type of the type you wish to read.
* @return The requested type
* @throws Exception If it fails to read
*/
public <T> T read(Type<T> type) throws Exception {
if (type == Type.NOTHING) return null;
if (readableObjects.isEmpty()) {
Preconditions.checkNotNull(inputBuffer, "This packet does not have an input buffer.");
// We could in the future log input read values, but honestly for things like bulk maps, mem waste D:
try {
return type.read(inputBuffer);
} catch (Exception e) {
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
} else {
Pair<Type, Object> read = readableObjects.poll();
if (read.getKey().equals(type) || (type.getBaseClass().equals(read.getKey().getBaseClass()) && type.getOutputClass().equals(read.getKey().getOutputClass()))) {
return (T) read.getValue();
} else {
if (type == Type.NOTHING) {
return read(type); // retry
} else {
Exception e = new IOException("Unable to read type " + type.getTypeName() + ", found " + read.getKey().getTypeName());
throw new InformativeException(e).set("Type", type.getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
}
}
}
/**
* Write a type to the output.
*
* @param type The type to write.
* @param <T> The return type of the type you wish to write.
* @param value The value of the type to write.
*/
public <T> void write(Type<T> type, T value) {
if (value != null) {
if (!type.getOutputClass().isAssignableFrom(value.getClass())) {
// attempt conversion
if (type instanceof TypeConverter) {
value = (T) ((TypeConverter) type).from(value);
} else {
System.out.println("Possible type mismatch: " + value.getClass().getName() + " -> " + type.getOutputClass());
}
}
}
packetValues.add(new Pair<Type, Object>(type, value));
}
/**
* Take a value from the input and write to the output.
*
* @param type The type to read and write.
* @param <T> The return type of the type you wish to pass through.
* @return The type which was read/written.
* @throws Exception If it failed to read or write
*/
public <T> T passthrough(Type<T> type) throws Exception {
T value = read(type);
write(type, value);
return value;
}
/**
* Take all the inputs and write them to the output.
*
* @throws Exception If it failed to read or write
*/
public void passthroughAll() throws Exception {
// Copy previous objects
packetValues.addAll(readableObjects);
readableObjects.clear();
// If the buffer has readable bytes, copy them.
if (inputBuffer.readableBytes() > 0) {
passthrough(Type.REMAINING_BYTES);
}
}
/**
* Write the current output to a buffer.
*
* @param buffer The buffer to write to.
* @throws Exception Throws an exception if it fails to write a value.
*/
public void writeToBuffer(ByteBuf buffer) throws Exception {
if (id != -1) {
Type.VAR_INT.write(buffer, id);
}
if (readableObjects.size() > 0) {
packetValues.addAll(readableObjects);
readableObjects.clear();
}
int index = 0;
for (Pair<Type, Object> packetValue : packetValues) {
try {
Object value = packetValue.getValue();
if (value != null) {
if (!packetValue.getKey().getOutputClass().isAssignableFrom(value.getClass())) {
// attempt conversion
if (packetValue.getKey() instanceof TypeConverter) {
value = ((TypeConverter) packetValue.getKey()).from(value);
} else {
System.out.println("Possible type mismatch: " + value.getClass().getName() + " -> " + packetValue.getKey().getOutputClass());
}
}
}
packetValue.getKey().write(buffer, value);
} catch (Exception e) {
throw new InformativeException(e).set("Index", index).set("Type", packetValue.getKey().getTypeName()).set("Packet ID", getId()).set("Data", packetValues);
}
index++;
}
writeRemaining(buffer);
}
/**
* Clear the input buffer / readable objects
*/
public void clearInputBuffer() {
if (inputBuffer != null)
inputBuffer.clear();
readableObjects.clear(); // :(
}
/**
* Clear the packet, used if you have to change the packet completely
*/
public void clearPacket() {
clearInputBuffer();
packetValues.clear();
}
private void writeRemaining(ByteBuf output) {
if (inputBuffer != null) {
output.writeBytes(inputBuffer, inputBuffer.readableBytes());
}
}
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
*
* @param packetProtocol - The protocol version of the packet.
* @param skipCurrentPipeline - Skip the current pipeline
* @throws Exception if it fails to write
*/
public void send(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline) throws Exception {
if (!isCancelled()) {
ByteBuf output = constructPacket(packetProtocol, skipCurrentPipeline);
user().sendRawPacket(output);
}
}
/**
* Let the packet go through the protocol pipes and write it to ByteBuf
*
* @param packetProtocol - The protocol version of the packet.
* @param skipCurrentPipeline - Skip the current pipeline
* @return Packet buffer
* @throws Exception if it fails to write
*/
private ByteBuf constructPacket(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline) throws Exception {
// Apply current pipeline
List<Protocol> protocols = new ArrayList<>(user().get(ProtocolInfo.class).getPipeline().pipes());
// Other way if outgoing
Collections.reverse(protocols);
int index = 0;
for (int i = 0; i < protocols.size(); i++) {
if (protocols.get(i).getClass().equals(packetProtocol)) {
index = skipCurrentPipeline ? (i + 1) : (i);
break;
}
}
// Reset reader before we start
resetReader();
// Apply other protocols
apply(Direction.OUTGOING, user().get(ProtocolInfo.class).getState(), index, protocols);
// Send
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
writeToBuffer(output);
return output;
}
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
*
* @param packetProtocol - The protocol version of the packet.
* @throws Exception if it fails to write
*/
public void send(Class<? extends Protocol> packetProtocol) throws Exception {
send(packetProtocol, true);
}
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
* Also returns the packets ChannelFuture
*
* @param packetProtocol - The protocol version of the packet.
* @return The packets ChannelFuture
* @throws Exception if it fails to write
*/
public ChannelFuture sendFuture(Class<? extends Protocol> packetProtocol) throws Exception {
if (!isCancelled()) {
ByteBuf output = constructPacket(packetProtocol, true);
return user().sendRawPacketFuture(output);
}
return user().getChannel().newFailedFuture(new Exception("Cancelled packet"));
}
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
* <br />
* <b>This method is no longer used, it's favoured to use send(Protocol) as it will handle the pipeline properly.</b>
*
* @throws Exception if it fails to write
*/
@Deprecated
public void send() throws Exception {
if (!isCancelled()) {
// Send
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
writeToBuffer(output);
user().sendRawPacket(output);
}
}
/**
* Create a new packet for the target of this packet.
*
* @param packetID The ID of the new packet
* @return The newly created packet wrapper
*/
public PacketWrapper create(int packetID) {
return new PacketWrapper(packetID, null, user());
}
/**
* Create a new packet with values.
*
* @param packetID The ID of the new packet
* @param init A ValueCreator to write to the packet.
* @return The newly created packet wrapper
* @throws Exception If it failed to write the values from the ValueCreator.
*/
public PacketWrapper create(int packetID, ValueCreator init) throws Exception {
PacketWrapper wrapper = create(packetID);
init.write(wrapper);
return wrapper;
}
/**
* Applies a pipeline from an index to the wrapper
*
* @param direction The direction
* @param state The state
* @param index The index to start from
* @param pipeline The pipeline
* @return The current packetwrapper
* @throws Exception
*/
public PacketWrapper apply(Direction direction, State state, int index, List<Protocol> pipeline) throws Exception {
for (int i = index; i < pipeline.size(); i++) { // Copy to prevent from removal.
pipeline.get(i).transform(direction, state, this);
// Reset the reader for the packetWrapper (So it can be recycled across packets)
resetReader();
}
return this;
}
/**
* Cancel this packet from sending
*/
public void cancel() {
this.send = false;
}
/**
* Check if this packet is cancelled.
*
* @return True if the packet won't be sent.
*/
public boolean isCancelled() {
return !this.send;
}
/**
* Get the user associated with this Packet
*
* @return The user
*/
public UserConnection user() {
return this.userConnection;
}
/**
* Reset the reader, so that it can be read again.
*/
public void resetReader() {
// Move readable objects are packet values
this.packetValues.addAll(readableObjects);
this.readableObjects.clear();
// Move all packet values to the readable for next packet.
this.readableObjects.addAll(packetValues);
this.packetValues.clear();
}
/**
* Send the current packet to the server.
* (Ensure the ID is suitable for the server version)
*
* @throws Exception If it failed to write
*/
public void sendToServer() throws Exception {
if (!isCancelled()) {
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
Type.VAR_INT.write(output, ViaDecodeHandler.PASSTHROUGH_ID); // Pass through
writeToBuffer(output);
PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output);
}
}
@Override
public String toString() {
return "PacketWrapper{" +
"packetValues=" + packetValues +
", readableObjects=" + readableObjects +
", id=" + id +
'}';
}
}
@@ -0,0 +1,23 @@
package us.myles.ViaVersion.api;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@EqualsAndHashCode
public class Pair<X, Y> {
private X key;
private Y value;
public Pair(X key, Y value) {
this.key = key;
this.value = value;
}
@Override
public String toString() {
return "Pair{" + key + ", " + value + '}';
}
}
@@ -0,0 +1,75 @@
package us.myles.ViaVersion.api;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.UUID;
@Getter(AccessLevel.PROTECTED)
@RequiredArgsConstructor
public abstract class ViaListener implements Listener {
private final ViaVersionPlugin plugin;
private final Class<? extends Protocol> requiredPipeline;
private boolean registered = false;
/**
* Get the UserConnection from a player
*
* @param player Player object
* @return The UserConnection
*/
protected UserConnection getUserConnection(@NonNull Player player) {
return getUserConnection(player.getUniqueId());
}
/**
* Get the UserConnection from an UUID
*
* @param uuid UUID object
* @return The UserConnection
*/
protected UserConnection getUserConnection(@NonNull UUID uuid) {
if (!plugin.isPorted(uuid)) return null;
return plugin.getConnection(uuid);
}
/**
* Checks if the player is on the selected pipe
*
* @param player Player Object
* @return True if on pipe
*/
protected boolean isOnPipe(Player player) {
return isOnPipe(player.getUniqueId());
}
/**
* Checks if the UUID is on the selected pipe
*
* @param uuid UUID Object
* @return True if on pipe
*/
protected boolean isOnPipe(UUID uuid) {
UserConnection userConnection = getUserConnection(uuid);
return userConnection != null &&
userConnection.get(ProtocolInfo.class).getPipeline().contains(requiredPipeline);
}
/**
* Register as Bukkit event
*/
public void register() {
if (registered) return;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
registered = true;
}
}
@@ -1,17 +1,19 @@
package us.myles.ViaVersion.api;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import us.myles.ViaVersion.ViaVersionPlugin;
public class ViaVersion {
private static ViaVersionAPI INSTANCE;
@Getter
private static ViaVersionAPI instance;
@Getter
private static ViaVersionConfig config;
public static void setInstance(ViaVersionAPI api) {
if (INSTANCE != null) {
throw new IllegalStateException("Instance already set.");
}
INSTANCE = api;
}
public static ViaVersionAPI getInstance() {
return INSTANCE;
public static void setInstance(ViaVersionPlugin plugin) {
Validate.isTrue(instance == null, "Instance is already set");
ViaVersion.instance = plugin;
ViaVersion.config = plugin.getConf();
}
}
@@ -1,8 +1,140 @@
package us.myles.ViaVersion.api;
import io.netty.buffer.ByteBuf;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.util.SortedSet;
import java.util.UUID;
public interface ViaVersionAPI {
/**
* Is the player connection modified by ViaVersion?
*
* @param player Bukkit player object
* @return True if the client is modified (At the moment it also means version 1.9 and higher)
*/
boolean isPorted(Player player);
/**
* Get protocol number from a player
* Will also retrieve version from ProtocolSupport if it's being used.
*
* @param player Bukkit player object
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
*/
int getPlayerVersion(Player player);
/**
* Get protocol number from a player
*
* @param uuid UUID of a player
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
*/
int getPlayerVersion(UUID uuid);
/**
* Is player using 1.9?
*
* @param playerUUID UUID of a player
* @return True if the client is on 1.9
*/
boolean isPorted(UUID playerUUID);
/**
* Get the version of the plugin
*
* @return Plugin version
*/
String getVersion();
/**
* Send a raw packet to the player (Use new IDs)
*
* @param player The player to send packet
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException;
/**
* Send a raw packet to the player (Use new IDs)
*
* @param uuid The uuid from the player to send packet
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
/**
* Create a new bossbar instance
*
* @param title The title
* @param color The color
* @param style The style
* @return Bossbar instance
*/
BossBar createBossBar(String title, BossColor color, BossStyle style);
/**
* Create a new bossbar instance
*
* @param title The title
* @param health Number between 0 and 1
* @param color The color
* @param style The style
* @return Bossbar instance
*/
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
/**
* Get if global debug is enabled
*
* @return true if debug is enabled
*/
boolean isDebug();
/**
* Get ViaVersions command handler
*
* @return command handler
*/
ViaVersionCommand getCommandHandler();
/**
* Get if this version is a compatibility build for spigot.
* Eg. 1.9.1 / 1.9.2 allow certain versions to connect
*
* @return True if it is
*/
boolean isCompatSpigotBuild();
/**
* Get the supported protocol versions
* This method removes any blocked protocol versions.
* @see ProtocolRegistry#getSupportedVersions() for full list.
*
* @return a list of protocol versions
*/
SortedSet<Integer> getSupportedVersions();
/**
* Gets if the server uses spigot
* <p>
* Note: Will only work after ViaVersion load
*
* @return True if spigot
*/
boolean isSpigot();
/**
* Gets if protocol support is also being used.
*
* @return True if it is being used.
*/
boolean isProtocolSupport();
}
@@ -0,0 +1,220 @@
package us.myles.ViaVersion.api;
import java.util.List;
public interface ViaVersionConfig {
/**
* Get if the plugin should check for updates
*
* @return true if update checking is enabled
*/
boolean isCheckForUpdates();
/**
* Get if collision preventing for players is enabled
*
* @return true if collision preventing is enabled
*/
boolean isPreventCollision();
/**
* Get if 1.9 & 1.10 clients are shown the new effect indicator in the top-right corner
*
* @return true if the using of the new effect indicator is enabled
*/
boolean isNewEffectIndicator();
/**
* Get if 1.9 & 1.10 clients are shown the new death message on the death screen
*
* @return true if enabled
*/
boolean isShowNewDeathMessages();
/**
* Get if metadata errors will be suppressed
*
* @return true if metadata errors suppression is enabled
*/
boolean isSuppressMetadataErrors();
/**
* Get if blocking in 1.9 & 1.10 appears as a player holding a shield
*
* @return true if shield blocking is enabled
*/
boolean isShieldBlocking();
/**
* Get if armor stand positions are fixed so holograms show up at the correct height in 1.9 & 1.10
*
* @return true if hologram patching is enabled
*/
boolean isHologramPatch();
/**
* Get if boss bars are fixed for 1.9 & 1.10 clients
*
* @return true if boss bar patching is enabled
*/
boolean isBossbarPatch();
/**
* Get if the boss bars for 1.9 & 1.10 clients are being stopped from flickering
* This will keep all boss bars on 100% (not recommended)
*
* @return true if boss bar anti flickering is enabled
*/
boolean isBossbarAntiflicker();
/**
* Get if unknown entity errors will be suppressed
*
* @return true if boss bar patching is enabled
*/
@Deprecated
boolean isUnknownEntitiesSuppressed();
/**
* Get the vertical offset armor stands are being moved with when the hologram patch is enabled
*
* @return the vertical offset holograms will be moved with
*/
double getHologramYOffset();
/**
* Get if players will be automatically put in the same team when collision preventing is enabled
*
* @return true if automatic teaming is enabled
*/
boolean isAutoTeam();
/**
* Get if our block break patch is enabled to prevent weird ghost glitches.
*
* @return true if it is enabled.
*/
@Deprecated
boolean isBlockBreakPatch();
/**
* Get the maximum number of packets a client can send per second.
*
* @return The number of packets a client can send per second.
*/
int getMaxPPS();
/**
* Get the kick message sent if the user hits the max packets per second.
*
* @return Kick message, with colour codes using '&amp;'
*/
String getMaxPPSKickMessage();
/**
* The time in seconds that should be tracked for warnings
*
* @return Time in seconds that should be tracked for warnings
*/
int getTrackingPeriod();
/**
* The number of packets per second to count as a warning
*
* @return The number of packets per second to count as a warning.
*/
int getWarningPPS();
/**
* Get the maximum number of warnings the client can have in the interval
*
* @return The number of packets a client can send per second.
*/
int getMaxWarnings();
/**
* Get the kick message sent if the user goes over the warnings in the interval
*
* @return Kick message, with colour codes using '&amp;'
*/
String getMaxWarningsKickMessage();
/**
* Is anti-xray enabled?
*
* @return A boolean
*/
boolean isAntiXRay();
/**
* Send supported versions in the status response packet
*
* @return If true, enabled
*/
boolean isSendSupportedVersions();
/**
* Stimulate the player tick
*
* @return if true, enabled
*/
boolean isStimulatePlayerTick();
/**
* Use the item cache to prevent high resource usage
*
* @return if true, enabled
*/
boolean isItemCache();
/**
* Use the NMS player ticking
*
* @return if true, enabled
*/
boolean isNMSPlayerTicking();
/**
* Replace extended pistons on 1.10 chunk loading.
*
* @return True if to replace them
*/
boolean isReplacePistons();
/**
* Get the id for replacing extended pistons.
*
* @return The integer id
*/
int getPistonReplacementId();
/**
* Force json transform
*
* @return True if enabled
*/
boolean isForceJsonTransform();
/**
* Get the blocked protocols
*
* @return An Integer list
*/
List<Integer> getBlockedProtocols();
/**
* Get the custom disconnect message
*
* @return Disconnect message
*/
String getBlockedDisconnectMsg();
/**
* Get the message sent to players being kicked on reload.
* Players are kicked to stop the server crashing
*
* @return Disconnect message
*/
String getReloadDisconnectMsg();
}
@@ -0,0 +1,150 @@
package us.myles.ViaVersion.api.boss;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.UUID;
public interface BossBar {
/**
* Get the current title
*
* @return the title
*/
String getTitle();
/**
* Change the title
*
* @param title Title can be in either JSON or just text
* @return The BossBar object
*/
BossBar setTitle(String title);
/**
* Get the health
*
* @return float between 0F - 1F
*/
float getHealth();
/**
* Change the health
*
* @param health this float has to be between 0F - 1F
* @return The BossBar object
*/
BossBar setHealth(float health);
/**
* Get the bossbar color
*
* @return The colour
*/
BossColor getColor();
/**
* Yay colors!
*
* @param color Whatever color you want!
* @return The BossBar object
*/
BossBar setColor(BossColor color);
/**
* Get the bosbar style
*
* @return BossStyle
*/
BossStyle getStyle();
/**
* Change the bosbar style
*
* @param style BossStyle
* @return The BossBar object
*/
BossBar setStyle(BossStyle style);
/**
* Show the bossbar to a player.
*
* @param player The player
* @return The BossBar object
*/
BossBar addPlayer(Player player);
/**
* Show the bossbar to a player (uuid)
*
* @param player uuid of the player
* @return The BossBar object
*/
BossBar addPlayer(UUID player);
/**
* add multiple players
*
* @param players list of players
* @return The BossBar object
*/
BossBar addPlayers(Player... players);
/**
* Remove the bossbar from a player
*
* @param player The player
* @return The BossBar object
*/
BossBar removePlayer(Player player);
/**
* Add flags
*
* @param flag The flag to add
* @return The BossBar object
*/
BossBar addFlag(BossFlag flag);
/**
* Remove flags.
*
* @param flag The flag to remove
* @return The BossBar object
*/
BossBar removeFlag(BossFlag flag);
/**
* @param flag The flag to check against
* @return True if it has the flag
*/
boolean hasFlag(BossFlag flag);
/**
* Get players
*
* @return UUIDS from players (sorry I lied)
*/
Set<UUID> getPlayers();
/**
* Show the bossbar to everyone (In the getPlayer set)
*
* @return The BossBar object
*/
BossBar show();
/**
* Hide the bossbar from everyone (In the getPlayer set)
*
* @return The BossBar object
*/
BossBar hide();
/**
* Is it visible?
*
* @return visibility changable with show() and hide()
*/
boolean isVisible();
}
@@ -0,0 +1,18 @@
package us.myles.ViaVersion.api.boss;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum BossColor {
PINK(0),
BLUE(1),
RED(2),
GREEN(3),
YELLOW(4),
PURPLE(5),
WHITE(6);
private final int id;
}
@@ -0,0 +1,13 @@
package us.myles.ViaVersion.api.boss;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum BossFlag {
DARKEN_SKY(1),
PLAY_BOSS_MUSIC(2);
private final int id;
}
@@ -0,0 +1,16 @@
package us.myles.ViaVersion.api.boss;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum BossStyle {
SOLID(0),
SEGMENTED_6(1),
SEGMENTED_10(2),
SEGMENTED_12(3),
SEGMENTED_20(4);
private final int id;
}
@@ -0,0 +1,77 @@
package us.myles.ViaVersion.api.command;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import java.util.Collections;
import java.util.List;
public abstract class ViaSubCommand {
/**
* Subcommand name
*
* @return The command name
*/
public abstract String name();
/**
* subcommand description, this'll show in /viaversion list
*
* @return The command description
*/
public abstract String description();
/**
* Usage example:
* "playerversion [name]"
*
* @return The command usage
*/
public String usage() {
return name();
}
/**
* Permission, null for everyone
*
* @return The permission required to use the command
*/
public String permission() {
return "viaversion.admin";
}
/**
* Gets triggered on execution
*
* @param sender Command sender
* @param args Arguments
* @return command executed succesfully if false, show usage
*/
public abstract boolean execute(CommandSender sender, String[] args);
/**
* Yay, possibility to implement tab-completion
*
* @param sender Command sender
* @param args args
* @return tab complete possibilities
*/
public List<String> onTabComplete(CommandSender sender, String[] args) {
return Collections.emptyList();
}
public String color(String s) {
return ViaCommandHandler.color(s);
}
/**
* Send message formatted / colored
*
* @param sender command sender
* @param message string message
* @param args optional objects
*/
public void sendMessage(CommandSender sender, String message, Object... args) {
ViaCommandHandler.sendMessage(sender, message, args);
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.api.command;
public interface ViaVersionCommand {
/**
* Register your own subcommand inside ViaVersion
*
* @param command Your own SubCommand instance to handle it.
* @throws Exception throws an exception when the subcommand already exists or if it's not valid, example: spacee
*/
void registerSubCommand(ViaSubCommand command) throws Exception;
/**
* Check if a subcommand is registered.
*
* @param name Subcommand name
* @return true if it exists
*/
boolean hasSubCommand(String name);
/**
* Get subcommand instance by name
*
* @param name subcommand name
* @return ViaSubCommand instance
*/
ViaSubCommand getSubCommand(String name);
}
@@ -0,0 +1,10 @@
package us.myles.ViaVersion.api.data;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class StoredObject {
private UserConnection user;
}
@@ -0,0 +1,162 @@
package us.myles.ViaVersion.api.data;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.SocketChannel;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@Data
public class UserConnection {
private final SocketChannel channel;
Map<Class, StoredObject> storedObjects = new ConcurrentHashMap<>();
private boolean active = true;
private boolean pendingDisconnect = false;
private Object lastPacket;
private long sentPackets = 0L;
private long receivedPackets = 0L;
// Used for tracking pps
private long startTime = 0L;
private long intervalPackets = 0L;
private long packetsPerSecond = -1L;
// Used for handling warnings (over time)
private int secondsObserved = 0;
private int warnings = 0;
public UserConnection(SocketChannel socketChannel) {
this.channel = socketChannel;
}
/**
* Get an object from the storage
*
* @param objectClass The class of the object to get
* @param <T> The type of the class you want to get.
* @return The requested object
*/
public <T extends StoredObject> T get(Class<T> objectClass) {
return (T) storedObjects.get(objectClass);
}
/**
* Check if the storage has an object
*
* @param objectClass The object class to check
* @return True if the object is in the storage
*/
public boolean has(Class<? extends StoredObject> objectClass) {
return storedObjects.containsKey(objectClass);
}
/**
* Put an object into the stored objects based on class
*
* @param object The object to store.
*/
public void put(StoredObject object) {
storedObjects.put(object.getClass(), object);
}
/**
* Send a raw packet to the player
*
* @param packet The raw packet to send
* @param currentThread Should it run in the same thread
*/
public void sendRawPacket(final ByteBuf packet, boolean currentThread) {
final ChannelHandler handler = channel.pipeline().get("encoder");
if (currentThread) {
channel.pipeline().context(handler).writeAndFlush(packet);
} else {
channel.eventLoop().submit(new Runnable() {
@Override
public void run() {
channel.pipeline().context(handler).writeAndFlush(packet);
}
});
}
}
/**
* Send a raw packet to the player with returning the future
*
* @param packet The raw packet to send
* @return ChannelFuture of the packet being sent
*/
public ChannelFuture sendRawPacketFuture(final ByteBuf packet) {
final ChannelHandler handler = channel.pipeline().get("encoder");
return channel.pipeline().context(handler).writeAndFlush(packet);
}
/**
* Send a raw packet to the player (netty thread)
*
* @param packet The packet to send
*/
public void sendRawPacket(final ByteBuf packet) {
sendRawPacket(packet, false);
}
/**
* Used for incrementing the number of packets sent to the client
*/
public void incrementSent() {
this.sentPackets++;
}
/**
* Used for incrementing the number of packets received from the client
*
* @return True if the interval has reset
*/
public boolean incrementReceived() {
// handle stats
Long diff = System.currentTimeMillis() - startTime;
if (diff >= 1000) {
packetsPerSecond = intervalPackets;
startTime = System.currentTimeMillis();
intervalPackets = 1;
return true;
} else {
intervalPackets++;
}
// increase total
this.receivedPackets++;
return false;
}
/**
* Disconnect a connection
*
* @param reason The reason to use, not used if player is not active.
*/
public void disconnect(final String reason) {
if (!getChannel().isOpen()) return;
if (pendingDisconnect) return;
pendingDisconnect = true;
if (get(ProtocolInfo.class).getUuid() != null) {
final UUID uuid = get(ProtocolInfo.class).getUuid();
if (Bukkit.getPlayer(uuid) != null) {
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Runnable() {
@Override
public void run() {
Player player = Bukkit.getPlayer(uuid);
if (player != null)
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason));
}
});
return;
}
}
getChannel().close(); // =)
}
}
@@ -0,0 +1,16 @@
package us.myles.ViaVersion.api.minecraft;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@AllArgsConstructor
@Getter
@ToString
@EqualsAndHashCode
public class Position {
private Long x;
private Long y;
private Long z;
}
@@ -0,0 +1,17 @@
package us.myles.ViaVersion.api.minecraft.chunks;
public interface Chunk {
int getX();
int getZ();
ChunkSection[] getSections();
boolean isGroundUp();
boolean isBiomeData();
byte[] getBiomeData();
int getBitmask();
}
@@ -0,0 +1,15 @@
package us.myles.ViaVersion.api.minecraft.chunks;
import io.netty.buffer.ByteBuf;
public interface ChunkSection {
int getBlockId(int x, int y, int z);
void writeBlocks(ByteBuf output) throws Exception;
void writeBlockLight(ByteBuf output) throws Exception;
boolean hasSkyLight();
void writeSkyLight(ByteBuf output) throws Exception;
}
@@ -0,0 +1,127 @@
package us.myles.ViaVersion.api.minecraft.chunks;
import java.util.Arrays;
public class NibbleArray {
private final byte[] handle;
public NibbleArray(int length) {
if (length == 0 || length % 2 != 0) {
throw new IllegalArgumentException("Length of nibble array must be a positive number dividable by 2!");
}
this.handle = new byte[length / 2];
}
public NibbleArray(byte[] handle) {
if (handle.length == 0 || handle.length % 2 != 0) {
throw new IllegalArgumentException("Length of nibble array must be a positive number dividable by 2!");
}
this.handle = handle;
}
/**
* Get the value at a desired X, Y, Z
*
* @param x Block X
* @param y Block Y
* @param z Block Z
* @return The value at the given XYZ
*/
public byte get(int x, int y, int z) {
return get(y << 8 | z << 4 | x);
}
/**
* Get the value at an index
*
* @param index The index to lookup
* @return The value at that index.
*/
public byte get(int index) {
byte value = handle[index / 2];
if (index % 2 == 0) {
return (byte) (value & 0xF);
} else {
return (byte) ((value >> 4) & 0xF);
}
}
/**
* Set the value based on an x, y, z
*
* @param x Block X
* @param y Block Y
* @param z Block Z
* @param value Desired Value
*/
public void set(int x, int y, int z, int value) {
set(y << 8 | z << 4 | x, value);
}
/**
* Set a value at an index
*
* @param index The index to set the value at.
* @param value The desired value
*/
public void set(int index, int value) {
index /= 2;
if (index % 2 == 0) {
handle[index] = (byte) (handle[index] & 0xF0 | value & 0xF);
} else {
handle[index] = (byte) (handle[index] & 0xF | (value & 0xF) << 4);
}
}
/**
* The size of this nibble
*
* @return The size as an int of the nibble
*/
public int size() {
return handle.length * 2;
}
/**
* Get the actual number of bytes
*
* @return The number of bytes based on the handle.
*/
public int actualSize() {
return handle.length;
}
/**
* Fill the array with a value
*
* @param value Value to fill with
*/
public void fill(byte value) {
value &= 0xF; // Max nibble size (= 16)
Arrays.fill(handle, (byte) ((value << 4) | value));
}
/**
* Get the byte array behind this nibble
*
* @return The byte array
*/
public byte[] getHandle() {
return handle;
}
/**
* Copy a byte array into this nibble
*
* @param handle The byte array to copy in.
*/
public void setHandle(byte[] handle) {
if (handle.length != this.handle.length) {
throw new IllegalArgumentException("Length of handle must equal to size of nibble array!");
}
System.arraycopy(handle, 0, this.handle, 0, handle.length);
}
}
@@ -0,0 +1,28 @@
package us.myles.ViaVersion.api.minecraft.item;
import lombok.*;
import org.bukkit.inventory.ItemStack;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Item {
private short id;
private byte amount;
private short data;
private CompoundTag tag;
/**
* Create an item from a bukkit stack (doesn't save NBT)
*
* @param stack The stack to convert from
* @return The output stack
*/
public static Item getItem(ItemStack stack) {
if (stack == null) return null;
return new Item((short) stack.getTypeId(), (byte) stack.getAmount(), stack.getDurability(), null);
}
}
@@ -0,0 +1,26 @@
package us.myles.ViaVersion.api.minecraft.metadata;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion.api.type.Type;
@AllArgsConstructor
@Getter
@Setter
public class Metadata {
private int id;
private int typeID;
private Type type;
private Object value;
@Override
public String toString() {
return "Metadata{" +
"id=" + id +
", typeID=" + typeID +
", type=" + type +
", value=" + value +
'}';
}
}
@@ -0,0 +1,156 @@
package us.myles.ViaVersion.api.protocol;
import lombok.AllArgsConstructor;
import lombok.Getter;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.exception.CancelException;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.State;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class Protocol {
private Map<Pair<State, Integer>, ProtocolPacket> incoming = new HashMap<>();
private Map<Pair<State, Integer>, ProtocolPacket> outgoing = new HashMap<>();
public Protocol() {
registerPackets();
}
/**
* Should this protocol filter an object packet from this class.
* Default: false
*
* @param packetClass The class of the current input
* @return True if it should handle the filtering
*/
public boolean isFiltered(Class packetClass) {
return false;
}
/**
* Filter a packet into the output
*
* @param info The current user connection
* @param packet The input packet as an object (NMS)
* @param output The list to put the object into.
* @throws Exception Throws exception if cancelled / error.
*/
protected void filterPacket(UserConnection info, Object packet, List output) throws Exception {
output.add(packet);
}
/**
* Register listeners for this protocol
*/
protected void registerListeners() {
}
/**
* Register the packets for this protocol
*/
protected abstract void registerPackets();
/**
* Initialise a user for this protocol setting up objects.
*
* @param userConnection The user to initialise
*/
public abstract void init(UserConnection userConnection);
/**
* Register an incoming packet, with simple id transformation.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
*/
public void registerIncoming(State state, int oldPacketID, int newPacketID) {
registerIncoming(state, oldPacketID, newPacketID, null);
}
/**
* Register an incoming packet, with id transformation and remapper.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
* @param packetRemapper The remapper to use for the packet
*/
public void registerIncoming(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper) {
ProtocolPacket protocolPacket = new ProtocolPacket(state, oldPacketID, newPacketID, packetRemapper);
incoming.put(new Pair<>(state, newPacketID), protocolPacket);
}
/**
* Register an outgoing packet, with simple id transformation.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
*/
public void registerOutgoing(State state, int oldPacketID, int newPacketID) {
registerOutgoing(state, oldPacketID, newPacketID, null);
}
/**
* Register an outgoing packet, with id transformation and remapper.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
* @param packetRemapper The remapper to use for the packet
*/
public void registerOutgoing(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper) {
ProtocolPacket protocolPacket = new ProtocolPacket(state, oldPacketID, newPacketID, packetRemapper);
outgoing.put(new Pair<>(state, oldPacketID), protocolPacket);
}
/**
* Transform a packet using this protocol
*
* @param direction The direction the packet is going in
* @param state The current protocol state
* @param packetWrapper The packet wrapper to transform
* @throws Exception Throws exception if it fails to transform
*/
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Pair<State, Integer> statePacket = new Pair<>(state, packetWrapper.getId());
Map<Pair<State, Integer>, ProtocolPacket> packetMap = (direction == Direction.OUTGOING ? outgoing : incoming);
ProtocolPacket protocolPacket;
if (packetMap.containsKey(statePacket)) {
protocolPacket = packetMap.get(statePacket);
} else {
return;
}
// write packet id
int newID = direction == Direction.OUTGOING ? protocolPacket.getNewID() : protocolPacket.getOldID();
packetWrapper.setId(newID);
// remap
if (protocolPacket.getRemapper() != null) {
protocolPacket.getRemapper().remap(packetWrapper);
if (packetWrapper.isCancelled())
throw new CancelException();
}
}
@Override
public String toString() {
return "Protocol:" + getClass().getSimpleName();
}
@AllArgsConstructor
@Getter
class ProtocolPacket {
State state;
int oldID;
int newID;
PacketRemapper remapper;
}
}
@@ -0,0 +1,165 @@
package us.myles.ViaVersion.api.protocol;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
public class ProtocolPipeline extends Protocol {
List<Protocol> protocolList;
private UserConnection userConnection;
public ProtocolPipeline(UserConnection userConnection) {
super();
init(userConnection);
}
@Override
protected void registerPackets() {
protocolList = new CopyOnWriteArrayList<>();
// This is a pipeline so we register basic pipes
protocolList.add(ProtocolRegistry.BASE_PROTOCOL);
}
@Override
public void init(UserConnection userConnection) {
this.userConnection = userConnection;
ProtocolInfo protocolInfo = new ProtocolInfo(userConnection);
protocolInfo.setPipeline(this);
userConnection.put(protocolInfo);
/* Init through all our pipes */
for (Protocol protocol : protocolList) {
protocol.init(userConnection);
}
}
/**
* Add a protocol to the current pipeline
* This will call the .init method.
*
* @param protocol The protocol to add to the end
*/
public void add(Protocol protocol) {
if (protocolList != null) {
protocolList.add(protocol);
protocol.init(userConnection);
} else {
throw new NullPointerException("Tried to add protocol to early");
}
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
int originalID = packetWrapper.getId();
List<Protocol> protocols = new ArrayList<>(protocolList);
// Other way if outgoing
if (direction == Direction.OUTGOING)
Collections.reverse(protocols);
// Apply protocols
packetWrapper.apply(direction, state, 0, protocols);
super.transform(direction, state, packetWrapper);
if (ViaVersion.getInstance().isDebug()) {
// Debug packet
String packet = "UNKNOWN";
// For 1.8/1.9 server version, eventually we'll probably get an API for this...
if (ProtocolRegistry.SERVER_PROTOCOL >= ProtocolVersion.v1_8.getId() &&
ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_9_3.getId()) {
PacketType type;
if (ProtocolRegistry.SERVER_PROTOCOL <= ProtocolVersion.v1_8.getId()) {
if (direction == Direction.INCOMING) {
type = PacketType.findNewPacket(state, direction, originalID);
} else {
type = PacketType.findOldPacket(state, direction, originalID);
}
} else {
type = PacketType.findNewPacket(state, direction, originalID);
}
if (type != null) {
// Filter :) This would be not hard coded too, sorry :(
if (type == PacketType.PLAY_CHUNK_DATA) return;
if (type == PacketType.PLAY_TIME_UPDATE) return;
if (type == PacketType.PLAY_KEEP_ALIVE) return;
if (type == PacketType.PLAY_KEEP_ALIVE_REQUEST) return;
if (type == PacketType.PLAY_ENTITY_LOOK_MOVE) return;
if (type == PacketType.PLAY_ENTITY_LOOK) return;
if (type == PacketType.PLAY_ENTITY_RELATIVE_MOVE) return;
if (type == PacketType.PLAY_PLAYER_POSITION_LOOK_REQUEST) return;
if (type == PacketType.PLAY_PLAYER_LOOK_REQUEST) return;
if (type == PacketType.PLAY_PLAYER_POSITION_REQUEST) return;
packet = type.name();
}
}
String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]";
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
String actualUsername = packetWrapper.user().get(ProtocolInfo.class).getUsername();
String username = actualUsername != null ? actualUsername + " " : "";
plugin.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}",
new Object[]{
username,
direction,
state,
originalID,
packetWrapper.getId(),
name,
packetWrapper
});
}
}
/**
* Check if the pipeline contains a protocol
*
* @param pipeClass The class to check
* @return True if the protocol class is in the pipeline
*/
public boolean contains(Class<? extends Protocol> pipeClass) {
for (Protocol protocol : protocolList) {
if (protocol.getClass().equals(pipeClass)) return true;
}
return false;
}
/**
* Use the pipeline to filter a NMS packet
*
* @param o The NMS packet object
* @param list The output list to write to
* @return If it should not write the input object to te list.
* @throws Exception If it failed to convert / packet cancelld.
*/
public boolean filter(Object o, List list) throws Exception {
for (Protocol protocol : protocolList) {
if (protocol.isFiltered(o.getClass())) {
protocol.filterPacket(userConnection, o, list);
return true;
}
}
return false;
}
public List<Protocol> pipes() {
return protocolList;
}
}
@@ -0,0 +1,183 @@
package us.myles.ViaVersion.api.protocol;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.protocols.base.BaseProtocol;
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2TO1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1to1_9.Protocol1_9_1TO1_9;
import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.Protocol1_9_3TO1_9_1_2;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion.protocols.protocol1_9to1_9_1.Protocol1_9TO1_9_1;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class ProtocolRegistry {
public static final Protocol BASE_PROTOCOL = new BaseProtocol();
public static int SERVER_PROTOCOL = -1;
// Input Version -> Output Version & Protocol (Allows fast lookup)
private static Map<Integer, Map<Integer, Protocol>> registryMap = new ConcurrentHashMap<>();
private static Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>();
private static List<Protocol> registerList = Lists.newCopyOnWriteArrayList();
private static Set<Integer> supportedVersions = Sets.newConcurrentHashSet();
static {
// Base Protocol
registerProtocol(BASE_PROTOCOL, Arrays.<Integer>asList(), -1);
// Register built in protocols
registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_8.getId());
registerProtocol(new Protocol1_9_1TO1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9.getId());
registerProtocol(new Protocol1_9_3TO1_9_1_2(), Arrays.asList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId());
// Only supported for 1.9.4 server to 1.9 (nothing else)
registerProtocol(new Protocol1_9TO1_9_1(), Arrays.asList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId());
registerProtocol(new Protocol1_9_1_2TO1_9_3_4(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9_3.getId());
registerProtocol(new Protocol1_10To1_9_3_4(), Collections.singletonList(ProtocolVersion.v1_10.getId()), ProtocolVersion.v1_9_3.getId());
}
/**
* Register a protocol
*
* @param protocol The protocol to register.
* @param supported Supported client versions.
* @param output The output server version it converts to.
*/
public static void registerProtocol(Protocol protocol, List<Integer> supported, Integer output) {
// Clear cache as this may make new routes.
if (pathCache.size() > 0)
pathCache.clear();
for (Integer version : supported) {
if (!registryMap.containsKey(version)) {
registryMap.put(version, new HashMap<Integer, Protocol>());
}
registryMap.get(version).put(output, protocol);
}
if (Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled()) {
protocol.registerListeners();
refreshVersions();
} else {
registerList.add(protocol);
}
}
public static void refreshVersions() {
supportedVersions.clear();
supportedVersions.add(ProtocolRegistry.SERVER_PROTOCOL);
for (ProtocolVersion versions : ProtocolVersion.getProtocols()) {
List<Pair<Integer, Protocol>> paths = getProtocolPath(versions.getId(), ProtocolRegistry.SERVER_PROTOCOL);
if (paths == null) continue;
supportedVersions.add(versions.getId());
for (Pair<Integer, Protocol> path : paths)
supportedVersions.add(path.getKey());
}
}
/**
* Get the versions compatible with the server.
*
* @return Read-only set of the versions.
*/
public static SortedSet<Integer> getSupportedVersions() {
return Collections.unmodifiableSortedSet(new TreeSet<>(supportedVersions));
}
/**
* Check if this plugin is useful to the server.
*
* @return True if there is a useful pipe
*/
public static boolean isWorkingPipe() {
for (Map<Integer, Protocol> maps : registryMap.values()) {
if (maps.containsKey(SERVER_PROTOCOL)) return true;
}
return false; // No destination for protocol
}
/**
* Called when the server is enabled, to register any non registered listeners.
*/
public static void registerListeners() {
for (Protocol protocol : registerList) {
protocol.registerListeners();
}
registerList.clear();
}
/**
* Calculate a path to get from an input protocol to the servers protocol.
*
* @param current The current items in the path
* @param clientVersion The current input version
* @param serverVersion The desired output version
* @return The path which has been generated, null if failed.
*/
private static List<Pair<Integer, Protocol>> getProtocolPath(List<Pair<Integer, Protocol>> current, int clientVersion, int serverVersion) {
if (clientVersion == serverVersion) return null; // We're already there
if (current.size() > 50) return null; // Fail safe, protocol too complicated.
// First check if there is any protocols for this
if (!registryMap.containsKey(clientVersion)) {
return null; // Not supported
}
// Next check there isn't an obvious path
Map<Integer, Protocol> inputMap = registryMap.get(clientVersion);
if (inputMap.containsKey(serverVersion)) {
current.add(new Pair<>(serverVersion, inputMap.get(serverVersion)));
return current; // Easy solution
}
// There might be a more advanced solution... So we'll see if any of the others can get us there
List<Pair<Integer, Protocol>> shortest = null;
for (Map.Entry<Integer, Protocol> entry : inputMap.entrySet()) {
// Ensure it wasn't caught by the other loop
if (!entry.getKey().equals(serverVersion)) {
Pair<Integer, Protocol> pair = new Pair<>(entry.getKey(), entry.getValue());
// Ensure no recursion
if (!current.contains(pair)) {
// Create a copy
List<Pair<Integer, Protocol>> newCurrent = new ArrayList<>(current);
newCurrent.add(pair);
// Calculate the rest of the protocol using the current
newCurrent = getProtocolPath(newCurrent, entry.getKey(), serverVersion);
if (newCurrent != null) {
// If it's shorter then choose it
if (shortest == null || shortest.size() > newCurrent.size()) {
shortest = newCurrent;
}
}
}
}
}
return shortest; // null if none found
}
/**
* Calculate a path from a client version to server version
*
* @param clientVersion The input client version
* @param serverVersion The desired output server version
* @return The path it generated, null if it failed.
*/
public static List<Pair<Integer, Protocol>> getProtocolPath(int clientVersion, int serverVersion) {
Pair<Integer, Integer> protocolKey = new Pair<>(clientVersion, serverVersion);
// Check cache
if (pathCache.containsKey(protocolKey)) {
return pathCache.get(protocolKey);
}
// Generate path
List<Pair<Integer, Protocol>> outputPath = getProtocolPath(new ArrayList<Pair<Integer, Protocol>>(), clientVersion, serverVersion);
// If it found a path, cache it.
if (outputPath != null) {
pathCache.put(protocolKey, outputPath);
}
return outputPath;
}
}
@@ -0,0 +1,94 @@
package us.myles.ViaVersion.api.protocol;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import java.util.*;
@AllArgsConstructor
@Getter
public class ProtocolVersion {
private static final Map<Integer, ProtocolVersion> versions = new HashMap<>();
private static final List<ProtocolVersion> versionList = new ArrayList<>();
public static final ProtocolVersion v1_4_6;
public static final ProtocolVersion v1_5_1;
public static final ProtocolVersion v1_5_2;
public static final ProtocolVersion v_1_6_1;
public static final ProtocolVersion v_1_6_2;
public static final ProtocolVersion v_1_6_3;
public static final ProtocolVersion v_1_6_4;
public static final ProtocolVersion v1_7_1;
public static final ProtocolVersion v1_7_6;
public static final ProtocolVersion v1_8;
public static final ProtocolVersion v1_9;
public static final ProtocolVersion v1_9_1;
public static final ProtocolVersion v1_9_2;
public static final ProtocolVersion v1_9_3;
public static final ProtocolVersion v1_10;
public static final ProtocolVersion unknown;
private final int id;
private final String name;
static {
// Before netty rewrite
register(v1_4_6 = new ProtocolVersion(51, "1.4.6"));
register(v1_5_1 = new ProtocolVersion(60, "1.5.1"));
register(v1_5_2 = new ProtocolVersion(61, "1.5.2"));
register(v_1_6_1 = new ProtocolVersion(73, "1.6.1"));
register(v_1_6_2 = new ProtocolVersion(74, "1.6.2"));
register(v_1_6_3 = new ProtocolVersion(77, "1.6.3"));
register(v_1_6_4 = new ProtocolVersion(78, "1.6.4"));
// After netty rewrite
register(v1_7_1 = new ProtocolVersion(4, "1.7-1.7.5"));
register(v1_7_6 = new ProtocolVersion(5, "1.7.6-1.7.10"));
register(v1_8 = new ProtocolVersion(47, "1.8.x"));
register(v1_9 = new ProtocolVersion(107, "1.9"));
register(v1_9_1 = new ProtocolVersion(108, "1.9.1"));
register(v1_9_2 = new ProtocolVersion(109, "1.9.2"));
register(v1_9_3 = new ProtocolVersion(110, "1.9.3/4"));
register(v1_10 = new ProtocolVersion(210, "1.10"));
register(unknown = new ProtocolVersion(-1, "UNKNOWN"));
}
public static void register(@NonNull ProtocolVersion protocol) {
versions.put(protocol.getId(), protocol);
versionList.add(protocol);
}
public static boolean isRegistered(int id) {
return versions.containsKey(id);
}
public static ProtocolVersion getProtocol(int id) {
if (versions.containsKey(id)) {
return versions.get(id);
} else {
return new ProtocolVersion(id, "Unknown (" + id + ")");
}
}
public static int getIndex(ProtocolVersion version) {
return versionList.indexOf(version);
}
public static List<ProtocolVersion> getProtocols() {
return Collections.unmodifiableList(new ArrayList<>(versions.values()));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProtocolVersion that = (ProtocolVersion) o;
return id == that.id;
}
@Override
public int hashCode() {
return id;
}
}
@@ -0,0 +1,24 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.exception.InformativeException;
public abstract class PacketHandler implements ValueWriter {
/**
* Handle a packet
*
* @param wrapper The associated wrapper
* @throws Exception Throws exception if it failed to handle the packet
*/
public abstract void handle(PacketWrapper wrapper) throws Exception;
@Override
public void write(PacketWrapper writer, Object inputValue) throws Exception {
try {
handle(writer);
} catch (InformativeException e) {
e.addSource(this.getClass());
throw e;
}
}
}
@@ -0,0 +1,104 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.exception.InformativeException;
import java.util.ArrayList;
import java.util.List;
public abstract class PacketRemapper {
private List<Pair<ValueReader, ValueWriter>> valueRemappers = new ArrayList<>();
public PacketRemapper() {
registerMap();
}
/**
* Map a type to the same type.
*
* @param type Type to map
*/
public void map(Type type) {
TypeRemapper remapper = new TypeRemapper(type);
map(remapper, remapper);
}
/**
* Map a type from an old type to a new type
*
* @param oldType The old type
* @param newType The new type
*/
public void map(Type oldType, Type newType) {
map(new TypeRemapper(oldType), new TypeRemapper(newType));
}
/**
* Map a type from an old type to a transformed new type.
*
* @param oldType The old type
* @param <T1> The old return type.
* @param transformer The transformer to use to produce the new type.
* @param <T2> The new return type.
*/
public <T1, T2> void map(Type<T1> oldType, ValueTransformer<T1, T2> transformer) {
map(new TypeRemapper(oldType), transformer);
}
/**
* Map a type using a basic ValueReader to a ValueWriter
*
* @param inputReader The reader to read with.
* @param outputWriter The writer to write with
* @param <T> The return type
*/
public <T> void map(ValueReader<T> inputReader, ValueWriter<T> outputWriter) {
valueRemappers.add(new Pair<ValueReader, ValueWriter>(inputReader, outputWriter));
}
/**
* Create a value
*
* @param creator The creator to used to make the value(s).
*/
public void create(ValueCreator creator) {
map(new TypeRemapper(Type.NOTHING), creator);
}
/**
* Create a handler
*
* @param handler The handler to use to handle the current packet.
*/
public void handler(PacketHandler handler) {
map(new TypeRemapper(Type.NOTHING), handler);
}
/**
* Register the mappings for this packet
*/
public abstract void registerMap();
/**
* Remap a packet wrapper
*
* @param packetWrapper The wrapper to remap
* @throws Exception Throws if it fails to write / read to the packet.
*/
public void remap(PacketWrapper packetWrapper) throws Exception {
try {
// Read all the current values
for (Pair<ValueReader, ValueWriter> valueRemapper : valueRemappers) {
Object object = valueRemapper.getKey().read(packetWrapper);
// Convert object to write type :O!!!
valueRemapper.getValue().write(packetWrapper, object);
}
// If we had handlers we'd put them here
} catch (InformativeException e) {
e.addSource(this.getClass());
throw e;
}
}
}
@@ -0,0 +1,22 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.type.Type;
public class TypeRemapper<T> implements ValueReader<T>, ValueWriter<T> {
private final Type<T> type;
public TypeRemapper(Type<T> type) {
this.type = type;
}
@Override
public T read(PacketWrapper wrapper) throws Exception {
return wrapper.read(type);
}
@Override
public void write(PacketWrapper output, T inputValue) {
output.write(type, inputValue);
}
}
@@ -0,0 +1,24 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.exception.InformativeException;
public abstract class ValueCreator implements ValueWriter {
/**
* Write new values to a Packet.
*
* @param wrapper The packet to write to
* @throws Exception Throws exception if it fails to write.
*/
public abstract void write(PacketWrapper wrapper) throws Exception;
@Override
public void write(PacketWrapper writer, Object inputValue) throws Exception {
try {
write(writer);
} catch (InformativeException e) {
e.addSource(this.getClass());
throw e;
}
}
}
@@ -0,0 +1,14 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
public interface ValueReader<T> {
/**
* Reads value from a PacketWrapper
*
* @param wrapper The wrapper to read from
* @return Returns the desired type
* @throws Exception Throws exception if it fails to read
*/
T read(PacketWrapper wrapper) throws Exception;
}
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.exception.InformativeException;
public abstract class ValueTransformer<T1, T2> implements ValueWriter<T1> {
private final Type<T2> outputType;
public ValueTransformer(Type<T2> outputType) {
this.outputType = outputType;
}
/**
* Transform a value from one type to another
*
* @param wrapper The current packet
* @param inputValue The input value
* @return The value to write to the wrapper
* @throws Exception Throws exception if it fails to transform a value
*/
public abstract T2 transform(PacketWrapper wrapper, T1 inputValue) throws Exception;
@Override
public void write(PacketWrapper writer, T1 inputValue) throws Exception {
try {
writer.write(outputType, transform(writer, inputValue));
} catch (InformativeException e) {
e.addSource(this.getClass());
throw e;
}
}
}
@@ -0,0 +1,14 @@
package us.myles.ViaVersion.api.remapper;
import us.myles.ViaVersion.api.PacketWrapper;
public interface ValueWriter<T> {
/**
* Write a value to a packet
*
* @param writer The packet wrapper to write to
* @param inputValue The value to write
* @throws Exception Throws exception if it fails to write
*/
void write(PacketWrapper writer, T inputValue) throws Exception;
}
@@ -0,0 +1,14 @@
package us.myles.ViaVersion.api.type;
import io.netty.buffer.ByteBuf;
public interface ByteBufReader<T> {
/**
* Read a value from a ByteBuf
*
* @param buffer The buffer to read from.
* @return The type based on the class type.
* @throws Exception Throws exception if it failed reading.
*/
T read(ByteBuf buffer) throws Exception;
}
@@ -0,0 +1,14 @@
package us.myles.ViaVersion.api.type;
import io.netty.buffer.ByteBuf;
public interface ByteBufWriter<T> {
/**
* Write an object to a type to a ByteBuf
*
* @param buffer The buffer to write to
* @param object The object to write
* @throws Exception Throws if it failed to write
*/
void write(ByteBuf buffer, T object) throws Exception;
}
@@ -0,0 +1,26 @@
package us.myles.ViaVersion.api.type;
import io.netty.buffer.ByteBuf;
public abstract class PartialType<T, X> extends Type<T> {
private final X param;
public PartialType(X param, Class<T> type) {
super(type);
this.param = param;
}
public abstract T read(ByteBuf buffer, X param) throws Exception;
public abstract void write(ByteBuf buffer, X param, T object) throws Exception;
@Override
public T read(ByteBuf buffer) throws Exception {
return read(buffer, this.param);
}
@Override
public void write(ByteBuf buffer, T object) throws Exception {
write(buffer, this.param, object);
}
}
@@ -0,0 +1,91 @@
package us.myles.ViaVersion.api.type;
import lombok.Getter;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.type.types.*;
import us.myles.ViaVersion.api.type.types.minecraft.*;
import java.util.UUID;
@Getter
public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
/* Defined Types */
public static final Type<Byte> BYTE = new ByteType();
public static final Type<Byte[]> BYTE_ARRAY = new ArrayType<>(Type.BYTE);
public static final Type<byte[]> REMAINING_BYTES = new RemainingBytesType();
public static final Type<Short> UNSIGNED_BYTE = new UnsignedByteType();
public static final Type<Short[]> UNSIGNED_BYTE_ARRAY = new ArrayType<>(Type.UNSIGNED_BYTE);
public static final Type<Boolean> BOOLEAN = new BooleanType();
public static final Type<Boolean[]> BOOLEAN_ARRAY = new ArrayType<>(Type.BOOLEAN);
/* Number Types */
public static final Type<Integer> INT = new IntType();
public static final Type<Integer[]> INT_ARRAY = new ArrayType<>(Type.INT);
public static final Type<Double> DOUBLE = new DoubleType();
public static final Type<Double[]> DOUBLE_ARRAY = new ArrayType<>(Type.DOUBLE);
public static final Type<Long> LONG = new LongType();
public static final Type<Long[]> LONG_ARRAY = new ArrayType<>(Type.LONG);
public static final Type<Float> FLOAT = new FloatType();
public static final Type<Float[]> FLOAT_ARRAY = new ArrayType<>(Type.FLOAT);
public static final Type<Short> SHORT = new ShortType();
public static final Type<Short[]> SHORT_ARRAY = new ArrayType<>(Type.SHORT);
public static final Type<Integer> UNSIGNED_SHORT = new UnsignedShortType();
public static final Type<Integer[]> UNSIGNED_SHORT_ARRAY = new ArrayType<>(Type.UNSIGNED_SHORT);
/* Other Types */
public static final Type<String> STRING = new StringType();
public static final Type<String[]> STRING_ARRAY = new ArrayType<>(Type.STRING);
public static final Type<UUID> UUID = new UUIDType();
public static final Type<UUID[]> UUID_ARRAY = new ArrayType<>(Type.UUID);
/* Variable Types */
public static final Type<Integer> VAR_INT = new VarIntType();
public static final Type<Integer[]> VAR_INT_ARRAY = new ArrayType<>(Type.VAR_INT);
/* Special Types */
public static final Type<Void> NOTHING = new VoidType(); // This is purely used for remapping.
/* MC Types */
public static final Type<Position> POSITION = new PositionType();
public static final Type<EulerAngle> ROTATION = new EulerAngleType();
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<CompoundTag> NBT = new NBTType();
public static final Type<CompoundTag[]> NBT_ARRAY = new ArrayType<>(Type.NBT);
public static final Type<UUID> OPTIONAL_UUID = new OptUUIDType();
public static final Type<Position> OPTIONAL_POSITION = new OptPositionType();
public static final Type<Item> ITEM = new ItemType();
public static final Type<Item[]> ITEM_ARRAY = new ItemArrayType();
/* Actual Class */
private final Class<? super T> outputClass;
private final String typeName;
public Type(Class<? super T> outputClass) {
this(outputClass.getSimpleName(), outputClass);
}
public Type(String typeName, Class<? super T> outputClass) {
this.outputClass = outputClass;
this.typeName = typeName;
}
public Class<? extends Type> getBaseClass() {
return this.getClass();
}
@Override
public String toString() {
return "Type|" + getTypeName();
}
}
@@ -0,0 +1,11 @@
package us.myles.ViaVersion.api.type;
public interface TypeConverter<T> {
/**
* Convert from a type to the current type
*
* @param o The input object
* @return The converted type as an object
*/
T from(Object o);
}
@@ -0,0 +1,39 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import java.lang.reflect.Array;
public class ArrayType<T> extends Type<T[]> {
private final Type<T> elementType;
public ArrayType(Type<T> type) {
super(type.getTypeName() + " Array", (Class<T[]>) getArrayClass(type.getOutputClass()));
this.elementType = type;
}
public static Class<?> getArrayClass(Class<?> componentType) {
// Should only happen once per class init.
return Array.newInstance(componentType, 0).getClass();
}
@Override
public T[] read(ByteBuf buffer) throws Exception {
int amount = Type.VAR_INT.read(buffer);
T[] array = (T[]) Array.newInstance(elementType.getOutputClass(), amount);
for (int i = 0; i < amount; i++) {
array[i] = elementType.read(buffer);
}
return array;
}
@Override
public void write(ByteBuf buffer, T[] object) throws Exception {
Type.VAR_INT.write(buffer, object.length);
for (T o : object) {
elementType.write(buffer, o);
}
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class BooleanType extends Type<Boolean> implements TypeConverter<Boolean> {
public BooleanType() {
super(Boolean.class);
}
@Override
public Boolean read(ByteBuf buffer) {
return buffer.readBoolean();
}
@Override
public void write(ByteBuf buffer, Boolean object) {
buffer.writeBoolean(object);
}
@Override
public Boolean from(Object o) {
if (o instanceof Number) {
return ((Number) o).intValue() == 1;
}
return (Boolean) o;
}
}
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class ByteType extends Type<Byte> implements TypeConverter<Byte> {
public ByteType() {
super(Byte.class);
}
@Override
public Byte read(ByteBuf buffer) {
return buffer.readByte();
}
@Override
public void write(ByteBuf buffer, Byte object) {
buffer.writeByte(object);
}
@Override
public Byte from(Object o) {
if (o instanceof Number) {
return ((Number) o).byteValue();
}
if (o instanceof Boolean) {
return (Boolean) o ? (byte) 1 : 0;
}
return (Byte) o;
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class DoubleType extends Type<Double> implements TypeConverter<Double> {
public DoubleType() {
super(Double.class);
}
@Override
public Double read(ByteBuf buffer) {
return buffer.readDouble();
}
@Override
public void write(ByteBuf buffer, Double object) {
buffer.writeDouble(object);
}
@Override
public Double from(Object o) {
if (o instanceof Number) {
return ((Number) o).doubleValue();
}
if (o instanceof Boolean) {
return (Boolean) o ? (byte) 1D : 0D;
}
return (Double) o;
}
}
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class FloatType extends Type<Float> implements TypeConverter<Float> {
public FloatType() {
super(Float.class);
}
@Override
public Float read(ByteBuf buffer) {
return buffer.readFloat();
}
@Override
public void write(ByteBuf buffer, Float object) {
buffer.writeFloat(object);
}
@Override
public Float from(Object o) {
if (o instanceof Number) {
return ((Number) o).floatValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? 1F : 0;
}
return (Float) o;
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class IntType extends Type<Integer> implements TypeConverter<Integer> {
public IntType() {
super(Integer.class);
}
@Override
public Integer read(ByteBuf buffer) {
return buffer.readInt();
}
@Override
public void write(ByteBuf buffer, Integer object) {
buffer.writeInt(object);
}
@Override
public Integer from(Object o) {
if (o instanceof Number) {
return ((Number) o).intValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? 1 : 0;
}
return (Integer) o;
}
}
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class LongType extends Type<Long> implements TypeConverter<Long> {
public LongType() {
super(Long.class);
}
@Override
public Long read(ByteBuf buffer) {
return buffer.readLong();
}
@Override
public void write(ByteBuf buffer, Long object) {
buffer.writeLong(object);
}
@Override
public Long from(Object o) {
if (o instanceof Number) {
return ((Number) o).longValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? 1L : 0;
}
return (Long) o;
}
}
@@ -0,0 +1,22 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
public class RemainingBytesType extends Type<byte[]> {
public RemainingBytesType() {
super(byte[].class);
}
@Override
public byte[] read(ByteBuf buffer) {
byte[] array = new byte[buffer.readableBytes()];
buffer.readBytes(array);
return array;
}
@Override
public void write(ByteBuf buffer, byte[] object) {
buffer.writeBytes(object);
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class ShortType extends Type<Short> implements TypeConverter<Short> {
public ShortType() {
super(Short.class);
}
@Override
public Short read(ByteBuf buffer) {
return buffer.readShort();
}
@Override
public void write(ByteBuf buffer, Short object) {
buffer.writeShort(object);
}
@Override
public Short from(Object o) {
if (o instanceof Number) {
return ((Number) o).shortValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? (short) 1 : 0;
}
return (short) o;
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
public class StringType extends Type<String> {
public StringType() {
super(String.class);
}
@Override
public String read(ByteBuf buffer) throws Exception {
int len = Type.VAR_INT.read(buffer);
Preconditions.checkArgument(len <= Short.MAX_VALUE, "Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len);
byte[] b = new byte[len];
buffer.readBytes(b);
return new String(b, Charsets.UTF_8);
}
@Override
public void write(ByteBuf buffer, String object) throws Exception {
Preconditions.checkArgument(object.length() <= Short.MAX_VALUE, "Cannot send string longer than Short.MAX_VALUE (got %s characters)", object.length());
byte[] b = object.getBytes(Charsets.UTF_8);
Type.VAR_INT.write(buffer, b.length);
buffer.writeBytes(b);
}
}
@@ -0,0 +1,23 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import java.util.UUID;
public class UUIDType extends Type<UUID> {
public UUIDType() {
super(UUID.class);
}
@Override
public UUID read(ByteBuf buffer) {
return new UUID(buffer.readLong(), buffer.readLong());
}
@Override
public void write(ByteBuf buffer, UUID object) {
buffer.writeLong(object.getMostSignificantBits());
buffer.writeLong(object.getLeastSignificantBits());
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class UnsignedByteType extends Type<Short> implements TypeConverter<Short> {
public UnsignedByteType() {
super("Unsigned Byte", Short.class);
}
@Override
public Short read(ByteBuf buffer) {
return buffer.readUnsignedByte();
}
@Override
public void write(ByteBuf buffer, Short object) {
buffer.writeByte(object);
}
@Override
public Short from(Object o) {
if (o instanceof Number) {
return ((Number) o).shortValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? (short) 1 : 0;
}
return (short) o;
}
}
@@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class UnsignedShortType extends Type<Integer> implements TypeConverter<Integer> {
public UnsignedShortType() {
super(Integer.class);
}
@Override
public Integer read(ByteBuf buffer) {
return buffer.readUnsignedShort();
}
@Override
public void write(ByteBuf buffer, Integer object) {
buffer.writeShort(object);
}
@Override
public Integer from(Object o) {
if (o instanceof Number) {
return ((Number) o).intValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? 1 : 0;
}
return (Integer) o;
}
}
@@ -0,0 +1,65 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class VarIntType extends Type<Integer> implements TypeConverter<Integer> {
public VarIntType() {
super("VarInt", Integer.class);
}
@Override
public void write(ByteBuf buffer, Integer object) {
int part;
while (true) {
part = object & 0x7F;
object >>>= 7;
if (object != 0) {
part |= 0x80;
}
buffer.writeByte(part);
if (object == 0) {
break;
}
}
}
@Override
public Integer read(ByteBuf buffer) {
int out = 0;
int bytes = 0;
byte in;
while (true) {
in = buffer.readByte();
out |= (in & 0x7F) << (bytes++ * 7);
if (bytes > 5) { // 5 is maxBytes
throw new RuntimeException("VarInt too big");
}
if ((in & 0x80) != 0x80) {
break;
}
}
return out;
}
@Override
public Integer from(Object o) {
if (o instanceof Number) {
return ((Number) o).intValue();
}
if (o instanceof Boolean) {
return ((Boolean) o) ? 1 : 0;
}
return (Integer) o;
}
}
@@ -0,0 +1,26 @@
package us.myles.ViaVersion.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
public class VoidType extends Type<Void> implements TypeConverter<Void> {
public VoidType() {
super(Void.class);
}
@Override
public Void read(ByteBuf buffer) {
return null;
}
@Override
public void write(ByteBuf buffer, Void object) {
}
@Override
public Void from(Object o) {
return null;
}
}
@@ -0,0 +1,19 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import us.myles.ViaVersion.api.minecraft.chunks.Chunk;
import us.myles.ViaVersion.api.type.Type;
public abstract class BaseChunkType extends Type<Chunk> {
public BaseChunkType() {
super(Chunk.class);
}
public BaseChunkType(String typeName) {
super(typeName, Chunk.class);
}
@Override
public Class<? extends Type> getBaseClass() {
return BaseChunkType.class;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import org.bukkit.util.EulerAngle;
import us.myles.ViaVersion.api.type.Type;
public class EulerAngleType extends Type<EulerAngle> {
public EulerAngleType() {
super(EulerAngle.class);
}
@Override
public EulerAngle read(ByteBuf buffer) throws Exception {
float x = Type.FLOAT.read(buffer);
float y = Type.FLOAT.read(buffer);
float z = Type.FLOAT.read(buffer);
return new EulerAngle(x, y, z);
}
@Override
public void write(ByteBuf buffer, EulerAngle object) throws Exception {
Type.FLOAT.write(buffer, (float) object.getX());
Type.FLOAT.write(buffer, (float) object.getY());
Type.FLOAT.write(buffer, (float) object.getZ());
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.type.Type;
public class ItemArrayType extends Type<Item[]> {
public ItemArrayType() {
super("Item Array", Item[].class);
}
@Override
public Item[] read(ByteBuf buffer) throws Exception {
int amount = Type.SHORT.read(buffer);
Item[] array = new Item[amount];
for (int i = 0; i < amount; i++) {
array[i] = Type.ITEM.read(buffer);
}
return array;
}
@Override
public void write(ByteBuf buffer, Item[] object) throws Exception {
Type.SHORT.write(buffer, (short) object.length);
for (Item o : object) {
Type.ITEM.write(buffer, o);
}
}
}
@@ -0,0 +1,38 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.type.Type;
public class ItemType extends Type<Item> {
public ItemType() {
super(Item.class);
}
@Override
public Item read(ByteBuf buffer) throws Exception {
short id = buffer.readShort();
if (id < 0) {
return null;
} else {
Item item = new Item();
item.setId(id);
item.setAmount(buffer.readByte());
item.setData(buffer.readShort());
item.setTag(Type.NBT.read(buffer));
return item;
}
}
@Override
public void write(ByteBuf buffer, Item object) throws Exception {
if (object == null) {
buffer.writeShort(-1);
} else {
buffer.writeShort(object.getId());
buffer.writeByte(object.getAmount());
buffer.writeShort(object.getData());
Type.NBT.write(buffer, object.getTag());
}
}
}
@@ -0,0 +1,17 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.Type;
import java.util.List;
public abstract class MetaListTypeTemplate extends Type<List<Metadata>> {
public MetaListTypeTemplate() {
super("MetaData List", List.class);
}
@Override
public Class<? extends Type> getBaseClass() {
return MetaListTypeTemplate.class;
}
}
@@ -0,0 +1,15 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.Type;
public abstract class MetaTypeTemplate extends Type<Metadata> {
public MetaTypeTemplate() {
super("Metadata type", Metadata.class);
}
@Override
public Class<? extends Type> getBaseClass() {
return MetaTypeTemplate.class;
}
}
@@ -0,0 +1,49 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import org.spacehq.opennbt.NBTIO;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import us.myles.ViaVersion.api.type.Type;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class NBTType extends Type<CompoundTag> {
public NBTType() {
super(CompoundTag.class);
}
@Override
public CompoundTag read(ByteBuf buffer) throws Exception {
Preconditions.checkArgument(buffer.readableBytes() <= 2097152, "Cannot read NBT (got %s bytes)", buffer.readableBytes());
int readerIndex = buffer.readerIndex();
byte b = buffer.readByte();
if (b == 0) {
return null;
} else {
buffer.readerIndex(readerIndex);
ByteBufInputStream bytebufStream = new ByteBufInputStream(buffer);
try (DataInputStream dataInputStream = new DataInputStream(bytebufStream)) {
return (CompoundTag) NBTIO.readTag(dataInputStream);
}
}
}
@Override
public void write(ByteBuf buffer, CompoundTag object) throws Exception {
if (object == null) {
buffer.writeByte(0);
} else {
ByteBufOutputStream bytebufStream = new ByteBufOutputStream(buffer);
DataOutputStream dataOutputStream = new DataOutputStream(bytebufStream);
NBTIO.writeTag(dataOutputStream, object);
dataOutputStream.close();
}
}
}
@@ -0,0 +1,25 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.type.Type;
public class OptPositionType extends Type<Position> {
public OptPositionType() {
super(Position.class);
}
@Override
public Position read(ByteBuf buffer) throws Exception {
boolean present = buffer.readBoolean();
if (!present) return null;
return Type.POSITION.read(buffer);
}
@Override
public void write(ByteBuf buffer, Position object) throws Exception {
buffer.writeBoolean(object != null);
if (object != null)
Type.POSITION.write(buffer, object);
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.type.Type;
import java.util.UUID;
public class OptUUIDType extends Type<UUID> {
public OptUUIDType() {
super(UUID.class);
}
@Override
public UUID read(ByteBuf buffer) {
boolean present = buffer.readBoolean();
if (!present) return null;
return new UUID(buffer.readLong(), buffer.readLong());
}
@Override
public void write(ByteBuf buffer, UUID object) {
if (object == null) {
buffer.writeBoolean(false);
} else {
buffer.writeBoolean(true);
buffer.writeLong(object.getMostSignificantBits());
buffer.writeLong(object.getLeastSignificantBits());
}
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.type.Type;
public class PositionType extends Type<Position> {
public PositionType() {
super(Position.class);
}
@Override
public Position read(ByteBuf buffer) {
long val = buffer.readLong();
long x = (val >> 38); // signed
long y = (val >> 26) & 0xfff; // unsigned
// this shifting madness is used to preserve sign
long z = (val << 38) >> 38; // signed
return new Position(x, y, z);
}
@Override
public void write(ByteBuf buffer, Position object) {
buffer.writeLong(((object.getX() & 0x3ffffff) << 38) | ((object.getY() & 0xfff) << 26) | (object.getZ() & 0x3ffffff));
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import org.bukkit.util.Vector;
import us.myles.ViaVersion.api.type.Type;
public class VectorType extends Type<Vector> {
public VectorType() {
super(Vector.class);
}
@Override
public Vector read(ByteBuf buffer) throws Exception {
int x = Type.INT.read(buffer);
int y = Type.INT.read(buffer);
int z = Type.INT.read(buffer);
return new Vector(x, y, z);
}
@Override
public void write(ByteBuf buffer, Vector object) throws Exception {
Type.INT.write(buffer, object.getBlockX());
Type.INT.write(buffer, object.getBlockY());
Type.INT.write(buffer, object.getBlockZ());
}
}
@@ -0,0 +1,25 @@
package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataTypes;
public class Metadata1_8Type extends MetaTypeTemplate {
@Override
public Metadata read(ByteBuf buffer) throws Exception {
byte item = buffer.readByte();
if (item == 127) return null; // end of metadata
int typeID = (item & 0xE0) >> 5;
MetadataTypes type = MetadataTypes.byId(typeID);
int id = item & 0x1F;
return new Metadata(id, typeID, type.getType(), type.getType().read(buffer));
}
@Override
public void write(ByteBuf buffer, Metadata object) throws Exception {
throw new UnsupportedOperationException("1.8 Metadata writing is not implemented!");
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.types.minecraft.MetaTypeTemplate;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType;
public class Metadata1_9Type extends MetaTypeTemplate {
@Override
public Metadata read(ByteBuf buffer) throws Exception {
short index = buffer.readUnsignedByte();
if (index == 0xff) return null; //End of metadata
NewType type = NewType.byId(buffer.readByte());
return new Metadata(index, type.getTypeID(), type.getType(), type.getType().read(buffer));
}
@Override
public void write(ByteBuf buffer, Metadata object) throws Exception {
if (object == null) {
buffer.writeByte(255);
} else {
buffer.writeByte(object.getId());
buffer.writeByte(object.getTypeID());
object.getType().write(buffer, object.getValue());
}
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.types.minecraft.MetaListTypeTemplate;
import java.util.ArrayList;
import java.util.List;
public class MetadataList1_8Type extends MetaListTypeTemplate {
@Override
public List<Metadata> read(ByteBuf buffer) throws Exception {
List<Metadata> list = new ArrayList<>();
Metadata m;
do {
m = Types1_8.METADATA.read(buffer);
if (m != null) {
list.add(m);
}
} while (m != null);
return list;
}
@Override
public void write(ByteBuf buffer, List<Metadata> object) throws Exception {
throw new UnsupportedOperationException("1.8 MetadataList writing is not implemented");
}
}
@@ -0,0 +1,33 @@
package us.myles.ViaVersion.api.type.types.version;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.types.minecraft.MetaListTypeTemplate;
import java.util.ArrayList;
import java.util.List;
public class MetadataList1_9Type extends MetaListTypeTemplate {
@Override
public List<Metadata> read(ByteBuf buffer) throws Exception {
List<Metadata> list = new ArrayList<>();
Metadata meta;
do {
meta = Types1_9.METADATA.read(buffer);
if (meta != null)
list.add(meta);
} while (meta != null);
return list;
}
@Override
public void write(ByteBuf buffer, List<Metadata> object) throws Exception {
for (Metadata m : object)
Types1_9.METADATA.write(buffer, m);
// Write end of list
Types1_9.METADATA.write(buffer, null);
}
}
@@ -0,0 +1,18 @@
package us.myles.ViaVersion.api.type.types.version;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.Type;
import java.util.List;
public class Types1_8 {
/**
* Metadata list type for 1.8
*/
public static Type<List<Metadata>> METADATA_LIST = new MetadataList1_8Type();
/**
* Metadata type for 1.8
*/
public static Type<Metadata> METADATA = new Metadata1_8Type();
}
@@ -0,0 +1,18 @@
package us.myles.ViaVersion.api.type.types.version;
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
import us.myles.ViaVersion.api.type.Type;
import java.util.List;
public class Types1_9 {
/**
* Metadata list type for 1.9
*/
public static final Type<List<Metadata>> METADATA_LIST = new MetadataList1_9Type();
/**
* Metadata type for 1.9
*/
public static final Type<Metadata> METADATA = new Metadata1_9Type();
}
@@ -0,0 +1,237 @@
package us.myles.ViaVersion.boss;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossFlag;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import java.util.*;
@Getter
public class ViaBossBar implements BossBar {
private UUID uuid;
private String title;
private float health;
private BossColor color;
private BossStyle style;
private Set<UUID> players;
private boolean visible;
private Set<BossFlag> flags;
public ViaBossBar(String title, float health, BossColor color, BossStyle style) {
Validate.notNull(title, "Title cannot be null");
Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1");
this.uuid = UUID.randomUUID();
this.title = title;
this.health = health;
this.color = color == null ? BossColor.PURPLE : color;
this.style = style == null ? BossStyle.SOLID : style;
this.players = new HashSet<>();
this.flags = new HashSet<>();
visible = true;
}
@Override
public BossBar setTitle(@NonNull String title) {
this.title = title;
sendPacket(UpdateAction.UPDATE_TITLE);
return this;
}
@Override
public BossBar setHealth(float health) {
Validate.isTrue((health >= 0 && health <= 1), "Health must be between 0 and 1");
this.health = health;
sendPacket(UpdateAction.UPDATE_HEALTH);
return this;
}
@Override
public BossColor getColor() {
return color;
}
@Override
public BossBar setColor(@NonNull BossColor color) {
this.color = color;
sendPacket(UpdateAction.UPDATE_STYLE);
return this;
}
@Override
public BossBar setStyle(@NonNull BossStyle style) {
this.style = style;
sendPacket(UpdateAction.UPDATE_STYLE);
return this;
}
@Override
public BossBar addPlayer(@NonNull Player player) {
return addPlayer(player.getUniqueId());
}
@Override
public BossBar addPlayer(UUID player) {
if (!players.contains(player)) {
players.add(player);
if (visible)
sendPacket(player, getPacket(UpdateAction.ADD));
}
return this;
}
@Override
public BossBar removePlayer(@NonNull Player player) {
if (players.contains(player.getUniqueId())) {
players.remove(player.getUniqueId());
sendPacket(player.getUniqueId(), getPacket(UpdateAction.REMOVE));
}
return this;
}
@Override
public BossBar addPlayers(@NonNull Player... players) {
for (Player p : players)
addPlayer(p);
return this;
}
@Override
public BossBar addFlag(@NonNull BossFlag flag) {
if (!hasFlag(flag))
flags.add(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
return this;
}
@Override
public BossBar removeFlag(@NonNull BossFlag flag) {
if (hasFlag(flag))
flags.remove(flag);
sendPacket(UpdateAction.UPDATE_FLAGS);
return this;
}
@Override
public boolean hasFlag(@NonNull BossFlag flag) {
return flags.contains(flag);
}
@Override
public Set<UUID> getPlayers() {
return Collections.unmodifiableSet(players);
}
@Override
public BossBar show() {
setVisible(true);
return this;
}
@Override
public BossBar hide() {
setVisible(false);
return this;
}
@Override
public boolean isVisible() {
return visible;
}
private void setVisible(boolean value) {
if (visible != value) {
visible = value;
sendPacket(value ? UpdateAction.ADD : UpdateAction.REMOVE);
}
}
private void sendPacket(UpdateAction action) {
for (UUID uuid : new ArrayList<>(players)) {
ByteBuf buf = getPacket(action);
sendPacket(uuid, buf);
}
}
private void sendPacket(UUID uuid, ByteBuf buf) {
if (!ViaVersion.getInstance().isPorted(uuid) || !(ViaVersion.getInstance().getPlayerVersion(uuid) >= ProtocolVersion.v1_9.getId())) {
players.remove(uuid);
buf.release();
return;
}
ViaVersion.getInstance().sendRawPacket(uuid, buf);
}
private ByteBuf getPacket(UpdateAction action) {
try {
ByteBuf buf = Unpooled.buffer();
Type.VAR_INT.write(buf, 0x0C); // Boss bar packet
Type.UUID.write(buf, uuid);
Type.VAR_INT.write(buf, action.getId());
switch (action) {
case ADD:
Type.STRING.write(buf, fixJson(title));
buf.writeFloat(health);
Type.VAR_INT.write(buf, color.getId());
Type.VAR_INT.write(buf, style.getId());
buf.writeByte(flagToBytes());
break;
case REMOVE:
break;
case UPDATE_HEALTH:
buf.writeFloat(health);
break;
case UPDATE_TITLE:
Type.STRING.write(buf, fixJson(title));
break;
case UPDATE_STYLE:
Type.VAR_INT.write(buf, color.getId());
Type.VAR_INT.write(buf, style.getId());
break;
case UPDATE_FLAGS:
buf.writeByte(flagToBytes());
break;
}
return buf;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private int flagToBytes() {
int bitmask = 0;
for (BossFlag flag : flags)
bitmask |= flag.getId();
return bitmask;
}
private String fixJson(String text) {
return Protocol1_9TO1_8.fixJson(text);
}
@RequiredArgsConstructor
@Getter
private enum UpdateAction {
ADD(0),
REMOVE(1),
UPDATE_HEALTH(2),
UPDATE_TITLE(3),
UPDATE_STYLE(4),
UPDATE_FLAGS(5);
private final int id;
}
}
@@ -1,52 +0,0 @@
package us.myles.ViaVersion.chunks;
public class ByteWriter {
private final byte[] bytes;
private int byteIndex;
private int bitIndex;
public ByteWriter(int size) {
this.bytes = new byte[size];
this.byteIndex = 0;
this.bitIndex = 0;
}
public byte[] getOutput() {
return this.bytes;
}
public void writeFullByte(int b){
writeByte(b, 8);
}
public void writeByte(int b, int length) {
byte current = getCurrentByte();
byte byteB = (byte)(int)((b) & 0xff);
System.out.println("Input: " + byteB);
System.out.println(Integer.toBinaryString(byteB));
int space = (8 - bitIndex);
int written = space > length ? length : space;
System.out.println("Written is " + written);
bytes[byteIndex] = (byte) (current | (extractRange(byteB, 0, written) >> (bitIndex - 1)));
System.out.println("output value: " + bytes[byteIndex]);
this.bitIndex += length;
if(this.bitIndex >= 8) {
this.byteIndex += 1;
this.bitIndex = bitIndex - 8;
// write remaining into this
System.out.println("Writing from " + written + " to " + (written + bitIndex));
System.out.println("Value: " + extractRange(byteB, written, written + bitIndex));
bytes[byteIndex] = (byte) (extractRange(byteB, written, written + bitIndex) << written);
}
}
private byte extractRange(int in, int begin, int end){
return (byte) ((in >> begin) & ((1 << (end - begin)) - 1));
}
public byte getCurrentByte() {
if(byteIndex == bytes.length) throw new RuntimeException("ByteWriter overflow!");
return bytes[byteIndex];
}
}
@@ -1,16 +0,0 @@
package us.myles.ViaVersion.chunks;
import java.util.BitSet;
public class MagicBitSet extends BitSet{
private final int initLength;
public MagicBitSet(int nbits) {
super(nbits);
this.initLength = nbits;
}
public int getTrueLength() {
return length() == 0 ? initLength : length();
}
}
@@ -1,19 +0,0 @@
package us.myles.ViaVersion.chunks;
public class PacketChunk {
private PacketChunkData[] chunkData;
private byte[] biomeData;
public PacketChunk(PacketChunkData[] chunkData, byte[] biomeData) {
this.chunkData = chunkData;
this.biomeData = biomeData;
}
public PacketChunkData[] getChunkData() {
return chunkData;
}
public byte[] getBiomeData() {
return biomeData;
}
}
@@ -1,25 +0,0 @@
package us.myles.ViaVersion.chunks;
public class PacketChunkData {
private short[] blocks = new short[4096];
private byte[] blockLight = new byte[2048];
private byte[] skyLight;
public PacketChunkData(boolean isSkyLightData) {
if(isSkyLightData){
skyLight = new byte[2048];
}
}
public short[] getBlocks() {
return this.blocks;
}
public byte[] getBlockLight() {
return this.blockLight;
}
public byte[] getSkyLight() {
return this.skyLight;
}
}
@@ -0,0 +1,19 @@
package us.myles.ViaVersion.classgenerator;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
public class BasicHandlerConstructor implements HandlerConstructor {
@Override
public ViaEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
return new ViaEncodeHandler(info, minecraftEncoder);
}
@Override
public ViaDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
return new ViaDecodeHandler(info, minecraftDecoder);
}
}
@@ -0,0 +1,165 @@
package us.myles.ViaVersion.classgenerator;
import javassist.*;
import javassist.expr.ConstructorCall;
import javassist.expr.ExprEditor;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
import us.myles.ViaVersion.util.ReflectionUtil;
public class ClassGenerator {
private static HandlerConstructor constructor = new BasicHandlerConstructor();
private static String psPackage = null;
public static HandlerConstructor getConstructor() {
return constructor;
}
public static void generate() {
if (ViaVersion.getInstance().isCompatSpigotBuild() || ViaVersion.getInstance().isProtocolSupport()) {
try {
ClassPool pool = ClassPool.getDefault();
for (Plugin p : Bukkit.getPluginManager().getPlugins()) {
pool.insertClassPath(new LoaderClassPath(p.getClass().getClassLoader()));
}
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
// Generate the classes
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
} else {
Class decodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedDecoder");
Class encodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedEncoder");
// Generate the classes
addPSCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
addPSCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
}
// Implement Constructor
CtClass generated = pool.makeClass("us.myles.ViaVersion.classgenerator.generated.GeneratedConstructor");
CtClass handlerInterface = pool.get(HandlerConstructor.class.getName());
generated.setInterfaces(new CtClass[]{handlerInterface});
// Import required classes
pool.importPackage("us.myles.ViaVersion.classgenerator.generated");
pool.importPackage("us.myles.ViaVersion.classgenerator");
pool.importPackage("us.myles.ViaVersion.api.data");
pool.importPackage("io.netty.handler.codec");
// Implement Methods
generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" +
" return new ViaEncodeHandler(info, minecraftEncoder);\n" +
" }", generated));
generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" +
" return new ViaDecodeHandler(info, minecraftDecoder);\n" +
" }", generated));
constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private static Class addSpigotCompatibility(ClassPool pool, Class input, Class superclass) {
String newName = "us.myles.ViaVersion.classgenerator.generated." + input.getSimpleName();
try {
CtClass generated = pool.getAndRename(input.getName(), newName);
if (superclass != null) {
CtClass toExtend = pool.get(superclass.getName());
generated.setSuperclass(toExtend);
// If it's NMS satisfy constructor.
if (superclass.getName().startsWith("net.minecraft")) {
// Modify constructor to call super
if (generated.getConstructors().length != 0) {
generated.getConstructors()[0].instrument(new ExprEditor() {
@Override
public void edit(ConstructorCall c) throws CannotCompileException {
if (c.isSuper()) {
// Constructor for both has a stats thing.
c.replace("super(null);");
}
super.edit(c);
}
});
}
}
}
return generated.toClass(HandlerConstructor.class.getClassLoader());
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}
return null;
}
private static Class addPSCompatibility(ClassPool pool, Class input, Class superclass) {
String newName = "us.myles.ViaVersion.classgenerator.generated." + input.getSimpleName();
try {
CtClass generated = pool.getAndRename(input.getName(), newName);
if (superclass != null) {
CtClass toExtend = pool.get(superclass.getName());
generated.setSuperclass(toExtend);
// Override setRealEncoder / setRealDecoder
pool.importPackage(getPSPackage());
pool.importPackage(getPSPackage() + ".wrapped");
if (superclass.getName().endsWith("Decoder")) {
// Decoder
generated.addMethod(CtMethod.make("public void setRealDecoder(IPacketDecoder dec) {\n" +
" WrappedDecoder decoder = new WrappedDecoder();" +
" decoder.setRealDecoder(dec);\n" +
" this.minecraftDecoder = decoder;\n" +
" }", generated));
} else {
// Encoder
generated.addMethod(CtMethod.make("public void setRealEncoder(IPacketEncoder enc) {\n" +
" WrappedEncoder encoder = new WrappedEncoder();" +
" encoder.setRealEncoder(enc);\n" +
" this.minecraftEncoder = encoder;\n" +
" }", generated));
}
}
return generated.toClass(HandlerConstructor.class.getClassLoader());
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}
return null;
}
public static String getPSPackage() {
if (psPackage == null) {
try {
Class.forName("protocolsupport.protocol.core.IPacketDecoder");
psPackage = "protocolsupport.protocol.core";
} catch (ClassNotFoundException e) {
try {
Class.forName("protocolsupport.protocol.pipeline.IPacketDecoder");
psPackage = "protocolsupport.protocol.pipeline";
} catch (ClassNotFoundException e1) {
psPackage = "unknown";
}
}
}
return psPackage;
}
}
@@ -0,0 +1,11 @@
package us.myles.ViaVersion.classgenerator;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.api.data.UserConnection;
public interface HandlerConstructor {
public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder);
public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder);
}
@@ -0,0 +1,153 @@
package us.myles.ViaVersion.commands;
import lombok.NonNull;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import us.myles.ViaVersion.commands.defaultsubs.*;
import java.util.*;
public class ViaCommandHandler implements ViaVersionCommand, CommandExecutor, TabCompleter {
private Map<String, ViaSubCommand> commandMap;
public ViaCommandHandler() {
commandMap = new HashMap<>();
try {
registerDefaults();
} catch (Exception e) {
//ignore never throws exception because it doesn't exists
}
}
@Override
public void registerSubCommand(@NonNull ViaSubCommand command) throws Exception {
Validate.isTrue(command.name().matches("^[a-z0-9_-]{3,15}$"), command.name() + " is not a valid subcommand name");
if (hasSubCommand(command.name()))
throw new Exception("ViaSubCommand " + command.name() + " does already exists!"); //Maybe another exception later.
commandMap.put(command.name().toLowerCase(), command);
}
@Override
public boolean hasSubCommand(String name) {
return commandMap.containsKey(name.toLowerCase());
}
@Override
public ViaSubCommand getSubCommand(String name) {
return commandMap.get(name.toLowerCase());
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String arg, String[] args) {
if (args.length == 0) {
showHelp(sender);
return false;
}
if (!hasSubCommand(args[0])) {
sender.sendMessage(color("&cThis command is not found"));
showHelp(sender);
return false;
}
ViaSubCommand handler = getSubCommand(args[0]);
if (!hasPermission(sender, handler.permission())) {
sender.sendMessage(color("&cYou are not allowed to use this command!"));
return false;
}
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
boolean result = handler.execute(sender, subArgs);
if (!result)
sender.sendMessage("Usage: /viaversion " + handler.usage());
return result;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String arg, String[] args) {
Set<ViaSubCommand> allowed = calculateAllowedCommands(sender);
List<String> output = new ArrayList<>();
//SubCommands tabcomplete
if (args.length == 1) {
if (!args[0].equals("")) {
for (ViaSubCommand sub : allowed)
if (sub.name().toLowerCase().startsWith(args[0].toLowerCase()))
output.add(sub.name());
} else {
for (ViaSubCommand sub : allowed)
output.add(sub.name());
}
}
//Let the SubCommand handle it
else if (args.length >= 2) {
if (getSubCommand(args[0]) != null) {
ViaSubCommand sub = getSubCommand(args[0]);
if (!allowed.contains(sub))
return output;
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
List<String> tab = sub.onTabComplete(sender, subArgs);
Collections.sort(tab);
return tab;
}
}
return output;
}
public void showHelp(CommandSender sender) {
Set<ViaSubCommand> allowed = calculateAllowedCommands(sender);
if (allowed.size() == 0) {
sender.sendMessage(color("&cYou are not allowed to use this command!"));
return;
}
sender.sendMessage(color("&aViaVersion &c" + ViaVersion.getInstance().getVersion()));
sender.sendMessage(color("&6Commands:"));
for (ViaSubCommand cmd : allowed)
sender.sendMessage(color(String.format("&2/viaversion %s &7- &6%s", cmd.usage(), cmd.description())));
allowed.clear();
}
private Set<ViaSubCommand> calculateAllowedCommands(CommandSender sender) {
Set<ViaSubCommand> cmds = new HashSet<>();
for (ViaSubCommand sub : commandMap.values())
if (hasPermission(sender, sub.permission()))
cmds.add(sub);
return cmds;
}
private boolean hasPermission(CommandSender sender, String permission) {
return permission == null || sender.hasPermission(permission);
}
private void registerDefaults() throws Exception {
registerSubCommand(new ListSubCmd());
registerSubCommand(new PPSSubCmd());
registerSubCommand(new DebugSubCmd());
registerSubCommand(new DisplayLeaksSubCmd());
registerSubCommand(new DontBugMeSubCmd());
registerSubCommand(new AutoTeamSubCmd());
registerSubCommand(new HelpSubCmd());
registerSubCommand(new ReloadSubCmd());
}
public static String color(String string) {
try {
string = ChatColor.translateAlternateColorCodes('&', string); //Dont replace all & with $ like we did before.
} catch (Exception ignored) {
}
return string;
}
public static void sendMessage(@NonNull CommandSender sender, String message, Object... args) {
sender.sendMessage(color(args == null ? message : String.format(message, args)));
}
}
@@ -0,0 +1,31 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class AutoTeamSubCmd extends ViaSubCommand {
@Override
public String name() {
return "autoteam";
}
@Override
public String description() {
return "Toggle automatically teaming to prevent colliding.";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
boolean newValue = !ViaVersion.getConfig().isAutoTeam();
plugin.getConfig().set("auto-team", newValue);
plugin.saveConfig();
sendMessage(sender, "&6We will %s", (newValue ? "&aautomatically team players" : "&cno longer auto team players"));
sendMessage(sender, "&6All players will need to re-login for the change to take place.");
return true;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DebugSubCmd extends ViaSubCommand {
@Override
public String name() {
return "debug";
}
@Override
public String description() {
return "Toggle debug mode";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
plugin.setDebug(!plugin.isDebug());
sendMessage(sender, "&6Debug mode is now %s", (plugin.isDebug() ? "&aenabled" : "&cdisabled"));
return true;
}
}
@@ -0,0 +1,28 @@
package us.myles.ViaVersion.commands.defaultsubs;
import io.netty.util.ResourceLeakDetector;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DisplayLeaksSubCmd extends ViaSubCommand {
@Override
public String name() {
return "displayleaks";
}
@Override
public String description() {
return "Try to hunt memory leaks!";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
if (ResourceLeakDetector.getLevel() != ResourceLeakDetector.Level.ADVANCED)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
else
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
sendMessage(sender, "&6Leak detector is now %s", (ResourceLeakDetector.getLevel() == ResourceLeakDetector.Level.ADVANCED ? "&aenabled" : "&cdisabled"));
return true;
}
}
@@ -0,0 +1,30 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
public class DontBugMeSubCmd extends ViaSubCommand {
@Override
public String name() {
return "dontbugme";
}
@Override
public String description() {
return "Toggle checking for updates";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
boolean newValue = !ViaVersion.getConfig().isCheckForUpdates();
plugin.getConfig().set("checkforupdates", newValue);
plugin.saveConfig();
sendMessage(sender, "&6We will %snotify you about updates.", (newValue ? "&a" : "&cnot "));
return true;
}
}
@@ -0,0 +1,27 @@
package us.myles.ViaVersion.commands.defaultsubs;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.commands.ViaCommandHandler;
public class HelpSubCmd extends ViaSubCommand {
@Override
public String name() {
return "help";
}
@Override
public String description() {
return "You are looking at it right now!";
}
@Override
public boolean execute(CommandSender sender, String[] args) {
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
((ViaCommandHandler) plugin.getCommandHandler()).showHelp(sender);
return true;
}
}
Loaded 100 of 179 files, more files were not shown because too many files have changed in this diff. Show more