Compare commits

..

640 Commits

Author SHA1 Message Date
d12bdcfda4 Fix NPE on VehicleMoveEvent. Fixes #2195. 2018-12-26 19:25:20 +01:00
f1cf541606 Merge remote-tracking branch 'origin/breaking' into breaking 2018-12-26 19:16:42 +01:00
2b9fe5afda Fix plot music (and plot inventories) 2018-12-26 19:16:34 +01:00
ba47a21971 - Update code style to format annotations nicely
- Reformat code
2018-12-26 17:21:06 +00:00
8cb2bdc846 Nice code to handle schematic loading and remove the ability to debugroadregen a specific chunk, as it uses a completely different method to actual road generation. 2018-12-26 16:44:39 +00:00
5bdc5a0fcc Fix road schematics but for real this time 2018-12-26 17:24:35 +01:00
2ebb7d11a8 Fix road schematics 2018-12-26 17:05:37 +01:00
1d08f4d4ff Include a rationale like Spottedleaf was kind enough to suggest 2018-12-26 15:38:31 +01:00
b05316c000 Recommend paper just like FAWE. I want to be like the cool kids.
Oh, and fix an issue with `/plot music`. Still broken. Just not
the same kind of broken.
2018-12-26 15:29:39 +01:00
f1378013c1 Fix plot home 2018-12-26 01:39:49 +01:00
edc758334c Actually copy over the files as well... 2018-12-25 18:30:42 +01:00
beb0f5708f Whoops... 2018-12-25 18:28:07 +01:00
71baee063c Update maven info for Core 2018-12-25 18:27:07 +01:00
1ca50cdbd2 Merge remote-tracking branch 'origin/breaking' into breaking 2018-12-25 12:05:12 +01:00
afb0a9f17f Forcefully load WorldEdit on startup 2018-12-25 12:05:01 +01:00
c14b76b324 Fix rotational blocks in road generation 2018-12-24 23:14:13 +00:00
af23d3d98e Fix schematic pasting to paste tile entities and blocks with BlockData (e.g. stairs) properly 2018-12-24 17:56:13 +00:00
9fe9c2662b Fix legacy conversion of block lists 2018-12-24 08:57:17 +01:00
9e0c226632 Fix schematic pasting 2018-12-24 08:13:15 +01:00
4f43788307 Merge remote-tracking branch 'origin/breaking' into breaking 2018-12-24 01:50:45 +01:00
8dae2555db Make mv create work again 2018-12-24 01:50:17 +01:00
1bf621fb4b Fix schematic saving (and improve performance slightly) 2018-12-23 22:49:43 +00:00
2ede77318a Add dordsor21 to author list 2018-12-23 20:32:48 +01:00
5c678e86bb Fix configuration loading issues 2018-12-23 20:31:29 +01:00
02937cc543 Add configuration conversion and fix BukkitLegacyMappings 2018-12-23 19:43:36 +01:00
165cac8b13 Fix bStats problem and commit Setup progress 2018-12-23 17:38:27 +01:00
25b34b419f Merge remote-tracking branch 'origin/breaking' into breaking 2018-12-21 23:48:18 -05:00
c1fa6c842d Removing old Metrics class
We don't need any fancy metrics at the moment. They can be added later if needed.
2018-12-21 23:38:01 -05:00
7900a95b25 Implement LegacyConverter 2018-12-21 22:55:47 +01:00
fe12d03916 Remove unused classes. 2018-12-21 21:28:33 +01:00
23b9eca4ab Add bStats support, seeing as mcstats has been down for ages 2018-12-21 21:10:37 +01:00
3c48488c61 Merge remote-tracking branch 'origin/breaking' into breaking 2018-12-21 17:49:15 +01:00
dff64c5c68 Add support for 1.13 blocks 2018-12-21 17:49:04 +01:00
886081e27f The local build was a fluke, and I couldn't work it out in the last 3 hours, so here are some basic updates/cleanup to a few things, and an updated bui;d command in README.md 2018-12-21 16:26:19 +00:00
e757c3e13c Merge branch 'breaking' of https://github.com/IntellectualSites/PlotSquared into breaking 2018-12-21 13:39:27 +00:00
5fdb60f85d Default plot height is at sea level (62) 2018-12-21 13:39:20 +00:00
aaed3f622a Fix build for gradlew clean assemble build 2018-12-21 13:38:28 +00:00
130274de86 Fix multiverse setup and don't allow unsafe blocks in setup 2018-12-21 03:31:08 +01:00
8bc0bcd9e6 Update BukkitUtil#isBlockSolid to 1.13 2018-12-21 01:04:37 +00:00
28f3be56b3 Fix schematic creation
Seems fairly ugly, but only because the format requires the blocks be inputted in that exact order, and it prevents us from having to cache the blocks per chunk to then insert into the relevant tags.
2018-12-21 00:49:15 +00:00
c53cd1ec91 oops 2018-12-20 23:34:55 +00:00
90682e9f8b Various:
- Some minor cleanup
 - Test for null id, not for null PlotBlock
 - Small fixes to schematic saving (still broken)
2018-12-20 23:33:24 +00:00
341e386df8 Delete Collection getBlocks to Array getBlocks 2018-12-20 21:46:00 +01:00
f4140ae728 Add getBlockArray() method 2018-12-20 21:40:50 +01:00
1021c6f2b0 Use Math.min and Math.max 2018-12-20 20:25:21 +00:00
780d3d7703 *Don't set the the cuboid block by block if we've already technically done that 2018-12-20 20:23:11 +00:00
6ac7948f72 Pretty basic fix for chunk generation 2018-12-20 20:20:31 +00:00
4e10682748 A few minor fixes 2018-12-20 18:46:52 +00:00
096ad1febe Make sure that blocks are actually compiled. Whoopsie 🐮 2018-12-20 19:35:02 +01:00
1543ac50cd Various:
- Empty StringPlotBlocks are air
 - Update signs to 1.13
 - Fix getting material in BukktiLocalQueue#setMaterial
2018-12-20 17:20:13 +00:00
442473368d This slipped through 2018-12-20 12:26:51 +00:00
b35221bf4f Fix crashing on chunk load (chunks are still empty though) 2018-12-20 12:23:49 +00:00
568b4c8e85 Merge remote-tracking branch 'origin/breaking' into breaking
# Conflicts:
#	Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/generator/BukkitPlotGenerator.java
#	Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/listeners/PlayerEvents.java
2018-12-20 02:25:55 +01:00
e939b8237e Changelist:
- Added aliases for custom configuration types
- Removed numerical ID based methods in Block Queues
- Fixed sign removal in Plot.java
- (Hopefully) fixed dividing by 0 errors in BlockBucket
- Removed random from some methods, as blockbucket has it's own random
- Temporarily removed chunk analysis
- Changed a lot in GenChunk and BukkitPlotGenerator
2018-12-20 02:23:48 +01:00
ffe5cddead 1.13.2 spigot dependancy 2018-12-20 01:05:10 +00:00
821e828f07 Merge pull request #2190 from IntellectualSites/master
Merge
2018-12-20 00:58:44 +00:00
2596f37f66 Merge branch 'breaking' into master 2018-12-20 00:58:28 +00:00
cbc2b70336 Merge commit 'be485075993f8dc807595c524f58c3bb58156a0c' into breaking
# Conflicts:
#	README.md
2018-12-20 00:55:44 +00:00
5aac7d07d2 Remove abstraction of BukkitSchematicHandler 2018-12-20 00:47:04 +00:00
ee6d52efa3 Update all legacy IDs 2018-12-20 00:43:47 +00:00
adc2d980f4 Clean up listeners for legacy versions 2018-12-19 23:49:35 +00:00
11ccfe7ac4 Reformat code 2018-12-19 23:26:20 +00:00
fa2dbb2b89 Update to WorldEdit 7 (and WE7-compatible schematics, *hopefully keeping legacy*) 2018-12-19 23:18:57 +00:00
e7b25d3fc8 Update BukkitLocalQueue to new LegacyMappings 2018-12-19 18:46:30 +00:00
444222c7f9 Improve PlotBlock name matching 2018-12-19 18:36:50 +01:00
e724aa8caf Fix PlotItem. 2018-12-19 18:24:35 +01:00
8f23299e7d Use BlockBuckets everywhere. 2018-12-19 17:19:54 +01:00
361cc9e9f7 Remove old LegacyMappings class from Bukkit
Add "fromAny" method
2018-12-19 15:08:49 +00:00
865de73a83 Merge pull request #2189 from dordsor21/breaking
Refactor legacy mappings to use PlotBlocks
2018-12-19 14:54:55 +00:00
531d8cc706 Merge branch 'breaking' into breaking 2018-12-19 14:54:32 +00:00
4b02bb1df8 Refactor legacy mappings to use PlotBlocks 2018-12-19 14:52:15 +00:00
1d3270d869 BlockBuckets r cool 🐮 2018-12-19 00:01:13 +01:00
3be23a3d37 Switching from IRC to Discord
To offer us a better possibility to help you regarding issues or bugs, join us on discord https://discord.gg/ngZCzbU
2018-12-18 21:27:30 +01:00
af9418552a Whoops. 2018-12-18 20:58:52 +01:00
10b87f5728 Add mappings for pre initialized items 2018-12-18 20:56:55 +01:00
ccad0bced9 Progress. 2018-12-18 20:54:20 +01:00
fb7bcef05f 1.13 shizzle 2018-12-17 20:57:21 +01:00
b9482fe5b4 Possible fix for FAWE build failures 2018-12-17 13:16:53 +00:00
be48507599 Merge pull request #2188 from N0tMyFaultOG/master
Adding French translation
2018-12-12 16:15:12 +01:00
8ad75efa0e Adding French translation 2018-12-12 16:12:40 +01:00
820710721e Schematic list command 2018-12-06 18:01:33 +01:00
152e9e0e90 Make it build. 2018-12-06 16:59:10 +01:00
3fc7fb0a7a Bump version (PlotSquared 4 will be new release) 2018-12-06 16:53:21 +01:00
18e969227c Update lombok version build. Disable Sponge and Nukkit builds. 2018-12-06 16:49:49 +01:00
0252cf724a Adding JavaDocs, Maven Repo and API Documentation 2018-11-15 14:02:31 +01:00
4395ca06b4 Add @SuppressWarnings("unused") to listeners. 2018-11-15 00:12:12 +01:00
a4a923c23c Extract duplicated switch statement in EntityUtil 2018-11-15 00:08:32 +01:00
06f64aeff0 Extract duplicated method declaration 2018-11-15 00:06:20 +01:00
a8b4729845 Rename DBFunc#everyone to DBFunc#EVERYONE, and create two string constants 🐱 2018-11-14 23:51:56 +01:00
3c64376abe Fix guest gamemode flag. 2018-11-14 23:40:27 +01:00
8cd54929e7 Merge branch 'master' into breaking
# Conflicts:
#	Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/events/PlotRateEvent.java
#	Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEventUtil.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Add.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Auto.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Delete.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Kick.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Load.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Music.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Owner.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Rate.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Reload.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/SchematicCmd.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/Trust.java
#	Core/src/main/java/com/github/intellectualsites/plotsquared/plot/flag/GameModeFlag.java
#	Core/src/main/java/com/intellectualcrafters/plot/commands/Clear.java
#	Core/src/main/java/com/intellectualcrafters/plot/commands/PluginCmd.java
#	Core/src/main/java/com/intellectualcrafters/plot/commands/Relight.java
#	Core/src/main/java/com/intellectualcrafters/plot/commands/SetHome.java
#	Core/src/main/java/com/intellectualcrafters/plot/config/C.java
#	Core/src/main/java/com/intellectualcrafters/plot/config/Configuration.java
#	Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java
#	Core/src/test/java/com/github/intellectualsites/plotsquared/plot/util/EventUtilTest.java
#	Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitEventUtil.java
#	README.md
#	Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/events/PlotRateEvent.java
#	Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/util/SpongeSchematicHandler.java
#	Sponge/src/main/java/com/github/intellectualsites/plotsquared/sponge/util/block/SpongeLocalQueue.java
#	Sponge/src/main/java/com/plotsquared/sponge/util/SpongeEventUtil.java
2018-11-14 14:44:07 +00:00
8df7f63931 Refactor PS (and rename to PlotSquared) 2018-11-14 14:19:57 +01:00
16dbbe5244 Refactoring of PS#getPlots:
Initialize to HashSet rather than ArrayList, because of add in HashSet
is O(1) vs. add in ArrayList which is O(n). Also make the wrapping
set immutable.
2018-11-14 13:52:09 +01:00
ae2869a29b Translation update and fixing wrong lines 2018-11-05 16:00:44 +01:00
40e7df8d69 Merge pull request #2142 from dordsor21/master
Cancel plot chat if message event is cancelled to allow for swear block/etc
2018-10-25 12:11:46 +02:00
ea5ffbeb77 Cancel plot chat if message event is cancelled to allow for swear block/etc 2018-10-25 10:51:18 +01:00
302051a6ca Minor cleanup 2018-10-20 14:03:21 +02:00
b6d4872ca4 Merge pull request #2102 from dordsor21/master
Add PlotChangeOwner Event
2018-10-13 15:11:45 +11:00
4b7ca2ff37 Minor cleanup 2018-10-10 18:29:21 +02:00
e4e4694a1c Merge pull request #2127 from Leomixer17/patch-1
Delete chinese.yml
2018-10-10 18:07:07 +02:00
ba6818a5bd Delete chinese.yml 2018-10-10 17:27:29 +02:00
1734c0e357 Rename ko_KR.yml to ko-KR.yml 2018-10-10 16:52:35 +02:00
e2e34f24d6 Rename zh_CN.yml to zh-CN.yml 2018-10-10 16:51:43 +02:00
765db2df0c Added languages 'back' 2018-10-10 16:49:31 +02:00
e1e6d95f75 Merge pull request #2049 from f0rb1d/master
Updated Simplified Chinese translation and formalized language codes.
2018-10-10 16:40:52 +02:00
70584a338c Update PS.java 2018-10-10 16:38:01 +02:00
11e2777f60 Update PS.java 2018-10-10 16:36:14 +02:00
b6303a7615 Update PS.java 2018-10-10 16:33:03 +02:00
88e80f54f7 Updating locale names 2018-10-10 16:30:38 +02:00
c6f8a6ddc1 Merge pull request #2088 from N0tMyFaultOG/master
Minor translation and template changes
2018-10-10 15:13:55 +02:00
9e9b21779c Add PlotChangeOwner Event 2018-09-19 16:57:33 +01:00
eab918bcd4 minor sponge cleanup 2018-09-10 07:46:56 +10:00
2e7d95f5a6 Fix sponge schem save 2018-09-10 07:45:00 +10:00
906f16d075 Fixes #2092 2018-09-10 06:38:22 +10:00
979b3c0408 Added bridge template and korean translation 2018-09-03 00:04:32 +02:00
5b2428559a Bridge template from the spigot page 2018-09-03 00:02:07 +02:00
f001eebad4 Update Settings.java 2018-09-02 23:51:45 +02:00
f5a981fda7 Fix plot visit sorting 2018-08-24 06:47:16 +10:00
032484b0f5 Pull out duplicated method sub in BukkitPlayer 2018-08-20 12:15:03 +02:00
587c942d88 Suppress PlotAPI warnings 2018-08-20 11:36:59 +02:00
e98c648244 Move PlotAPI to Core and move bukkit specific methods to BukkitUtil. 2018-08-20 11:35:41 +02:00
be9fb3bd3a Remove deprecated methods without internal use. 2018-08-20 11:05:00 +02:00
01a927ccad Allow PlotRateEvent to be cancelled. Fixes #2017 2018-08-19 23:12:59 +02:00
3c86531b58 * ;) 2018-08-19 22:21:42 +02:00
847ce7f20d (W.I.P) TeleportEntityWrapper as alternative to replicating entity wrapper 2018-08-19 22:18:58 +02:00
4b8c434669 Fix compile (var must be final) 2018-08-12 21:36:04 +10:00
9105294965 Update auto-comment.yml 2018-08-11 15:48:33 +02:00
5378c9007c Create auto-comment.yml 2018-08-11 15:43:36 +02:00
40e91de111 Create stale.yml 2018-08-11 15:38:22 +02:00
b1246adac2 Update README.md 2018-08-11 15:29:31 +02:00
86e7f4e2b3 Update ISSUE_TEMPLATE.md 2018-08-11 15:28:41 +02:00
af461e1fc2 Add alternative maven link and re-enable gradle daemon 2018-08-10 23:41:31 +02:00
d9bc1fcfe7 Disable daemon (temporarily) to allow for CI builds to not run out of memory. 2018-08-10 23:38:28 +02:00
369ccb7c8d Prettify BukkitUtil 2018-08-10 20:54:17 +02:00
724fb34b1f Prettify BukkitMain 2018-08-10 20:46:38 +02:00
2898e9ae2b Fix error from refactoring 2018-08-10 20:30:05 +02:00
b551424ced Update gradle 2018-08-10 20:29:50 +02:00
b0348cfc34 Update packages. This will not be appreciated 🐱 2018-08-10 17:53:15 +02:00
1646cd0f5a Reformat code 2018-08-10 17:01:11 +02:00
02ee1e8fa1 Update README.md and commit code style 2018-08-10 16:52:35 +02:00
a2813a2427 Merge pull request #2057 from IntellectualSites/Sauilitired-patch-1
Remove unnecessary lines in Configuration javadoc
2018-08-10 16:05:06 +02:00
bbcd508bc3 Remove unnecessary lines in Configuration javadoc 2018-08-10 16:04:43 +02:00
a4f176fd07 Updated Simplified Chinese translation and formalized language codes. 2018-08-03 20:35:36 +08:00
3d8d75170d Check admin for setowner null 2018-07-31 14:28:22 +10:00
2c11a292f4 Prevent multiple uses of plot auto 2018-07-29 21:43:07 +10:00
cd9d22cb9b Fix augmented generator not clearing column 2018-07-27 14:02:40 +10:00
645c5fb529 Fix nukkit augmented generator 2018-07-27 13:25:46 +10:00
2d98da47cf Debug generator error 2018-07-27 10:57:34 +10:00
1b08d54be0 Merge pull request #2029 from Speentie8081/master
Add support for spigot 1.13 and spigot 1.13-pre7
2018-07-27 10:37:51 +10:00
be8172ce91 Assume spigot 1.13 if NumberFormatException is fired 2018-07-22 09:17:38 -05:00
768e21d1b5 Update NBTFactory to support spigot 1.13 2018-07-22 09:09:39 -05:00
bbee2debff Remove unneeded changes and add back support for 1.9 through 1.12 2018-07-21 10:32:38 -05:00
d5b01aced2 Use MaterialData instead of block id and data for chunk generation 2018-07-21 00:15:13 -05:00
f533efb2c8 Add support for spigot 1.13-pre7 2018-07-20 23:51:09 -05:00
aaa70888bd Merge pull request #2028 from PhanaticD/patch-3
fix dispensers
2018-07-21 12:40:54 +10:00
d673537026 fix dispensers
previously dispensers were not working at all, this change blocks lava and water and allows dispensers to function normally again on servers with plotsquared. if you were trying to block dispensers launching items into the road however that still is not blocked by this
2018-07-20 19:23:39 -04:00
ae1e58c0ac Add -f override for plot move 2018-07-07 09:22:24 +10:00
5d04c64d48 Fix typo 2018-07-07 09:11:23 +10:00
185fe39942 Fix check for UUID support 2018-07-07 08:50:43 +10:00
18c92bea38 Allow specifying area for move command 2018-07-05 19:33:17 +10:00
79e1ea9a8f * 2018-06-23 14:13:06 +10:00
1772fdab16 Fixes #1988 2018-06-23 14:12:21 +10:00
9020d740d1 Revert "possible fix for mob damage"
This reverts commit df6914fb1e.
2018-06-23 11:46:19 +10:00
df6914fb1e possible fix for mob damage 2018-06-21 07:48:45 +10:00
da5478f141 Only check int flag ranges 2018-06-20 07:48:51 +10:00
d454602888 Fixes #1961 2018-06-19 03:44:45 +10:00
3039331976 Add account age expiry filter 2018-06-19 03:29:14 +10:00
6ed6f607b5 Sort flag list alphabetically 2018-06-13 09:28:32 +10:00
37b0cdeace Revert "Don't cancel chat event"
This reverts commit dc5fc5af47.
2018-06-10 19:35:34 +10:00
9897890e6a *Add console sender to nukkit chat 2018-06-09 15:49:54 +10:00
ce3e3be59e Tweak nukkit plot chat 2018-06-09 15:37:49 +10:00
9ed5847c0a Fixes #1768 2018-06-09 06:20:31 +10:00
dc5fc5af47 Don't cancel chat event 2018-06-09 05:45:25 +10:00
eca67c7d84 Merge pull request #1986 from dualspiral/bugfix/null-suggestions
Fix errors with tab completion on Sponge.
2018-06-09 05:11:27 +10:00
c7a1526e12 Fix errors with tab completion on Sponge.
Fixes #1768
2018-06-08 11:17:02 +01:00
740de4932b Fix flag perm check 2018-06-07 12:30:39 +10:00
442513b592 Fixes #1970 2018-06-07 08:15:28 +10:00
40635255e3 Probably fixes #1953 2018-05-18 14:48:17 +10:00
550df7f232 Fixes #1952 2018-05-17 17:46:54 +10:00
4ffc4e67ab Fixes #1822 2018-05-17 16:30:31 +10:00
d6c472fcdf Fixes #1484 2018-05-17 16:23:27 +10:00
a83b51eb12 Fixes #1951 2018-05-17 15:21:53 +10:00
67a70d4ade Fixes #1928 2018-05-17 15:17:45 +10:00
f479a70594 Fixes #1729 2018-05-17 15:11:44 +10:00
9f9527d2e2 Fixes #1784 2018-05-17 14:53:34 +10:00
98b7a84119 Fixes #1483 2018-05-17 14:50:47 +10:00
5cb94f3e45 Fixes #1928 2018-05-17 14:43:51 +10:00
ecf94b8706 minor web tweaks 2018-05-13 10:32:48 +10:00
3006e941ba Merge pull request #1943 from N0tMyFaultOG/patch-3
Update, rework and redesign of the german.yml
2018-05-12 09:25:42 +10:00
244ccb71cf Update of german.yml
german.yml design has been reworked to the up-to-date PlotSquared language file design. Many lines were added and adjusted.
2018-05-11 20:37:50 +02:00
2d617fc05e Merge pull request #1942 from N0tMyFaultOG/patch-2
Typo fixes
2018-05-11 11:36:49 +10:00
e13785edfe Typo fixes
Had to write some custom messages for a server and fixed the typos in here
2018-05-11 00:03:35 +02:00
59e06c2319 Fixes #1929 2018-05-07 10:44:16 +10:00
9a7ce84e1c Potentially fixes #1769 2018-05-07 10:20:13 +10:00
ef54775ca7 wtf, this has its own spawn reason, thanks spigot
Fixes #1803
2018-05-07 10:15:21 +10:00
d49bfa612e Merge pull request #1933 from Leomixer17/patch-1
Update italian.yml
2018-05-02 00:52:53 +10:00
72f30d8aef usernames can be 2 characters 2018-05-02 00:43:27 +10:00
ef6b1cb932 Update italian.yml 2018-05-01 01:29:18 +02:00
154bad6188 * 2018-04-28 21:53:39 +10:00
613d79fb39 Fixes #1691 2018-04-28 21:51:26 +10:00
5f9bd853ec Fixes #1903 2018-04-28 09:41:09 +10:00
ef83b5a1b7 Fixes #1931 2018-04-28 09:28:55 +10:00
9fe1e53d9d Fix single generator biomes 2018-04-15 10:47:00 +10:00
4f63cdf560 Fixes #1920 2018-04-13 20:37:28 +10:00
7f257e2bf3 * 2018-04-12 00:20:13 +10:00
c5b332246e Fix setblock npe 1.8 2018-04-11 23:41:09 +10:00
0c7be7e11d Merge pull request #1915 from Foorack/master
Fix maven compilation
2018-04-09 17:05:27 +02:00
c5a30bd708 Filter Core resources 2018-04-07 20:52:31 +02:00
90c3fac4fa Fix PlotVersion when compiling with Maven 2018-04-07 20:52:19 +02:00
e4f6c39bb7 Fix Maven compiling 2018-04-07 12:05:37 +02:00
39084be791 Fix nukkit compile 2018-03-19 16:05:12 +11:00
ded33aa9be Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2018-03-18 09:28:36 +11:00
3565e67137 Prevent entity portal use from plotworld 2018-03-18 09:28:23 +11:00
0e5483c050 Merge pull request #1901 from bibo38/nlfix
Fixed wrong newlines in german language file
2018-03-17 15:24:39 +11:00
fb706e0d60 Fixed wrong newlines in german language file 2018-03-16 18:07:29 +01:00
368b9a0168 Fixes #1786 2018-03-15 16:34:28 +11:00
c208c530ff Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2018-03-12 17:27:00 +11:00
b36d42811a Fixes #1897 2018-03-12 17:26:40 +11:00
5921e1865b Merge pull request #1895 from BrainStone/master
using newer MySQL driver
2018-03-12 17:23:27 +11:00
515405aa9e using newer MySQL driver
- Newer driver doesn't need manual loading
- Fixes #1783
2018-03-10 21:34:11 +01:00
8f5e2eb439 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2018-03-08 08:37:36 +11:00
5b18b918a9 Ignore unsupported statement isClosed 2018-03-08 08:37:17 +11:00
7dcb85d5d4 Fix typo in database update error message 2018-03-07 21:02:19 +00:00
1cd30b84d5 check for closed connections 2018-02-15 23:12:42 +11:00
eb1c3263ec Fix deny-exit flag 2018-02-15 18:59:40 +11:00
c98f2b4261 update to latest nukkit 2018-02-13 02:16:13 +11:00
d9a17bd379 Fixes #1872 2018-02-08 19:48:40 +11:00
c5d5b52df4 Tweak item drop check 2018-02-08 19:42:36 +11:00
73d0068d07 Update to latest nukkit 2018-02-02 15:19:58 +11:00
4b50276ba0 Fixes #1844 2018-01-31 13:05:11 +11:00
8815c83ba1 Various minor
Teleport on login fixes
World unloading fixes
2018-01-27 16:26:09 +11:00
c5778137f6 Update asm 2018-01-25 17:46:41 +11:00
d22c0349f7 * 2018-01-25 15:32:25 +11:00
785ba10ca1 Update to latest sponge 2018-01-25 14:51:39 +11:00
0e183f5627 Fixes #1839 2018-01-13 12:47:02 +11:00
b239cb4a18 Fixes #1828 2018-01-10 17:50:38 +11:00
02b358133e Better idea, send the packet. Closes #1837 2018-01-10 17:39:12 +11:00
4f464439e5 * 2018-01-10 17:22:46 +11:00
4716104951 Revert broken changes to visit 2018-01-10 17:15:05 +11:00
bc8b2af164 Fixes #1774 (backwards compatibility) 2018-01-10 17:06:35 +11:00
03337fe080 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2018-01-10 16:58:42 +11:00
4ff02831f3 Fixes #1767 (performance issue) 2018-01-10 16:58:37 +11:00
09e83bcbf8 Merge pull request #1793 from Leomixer17/patch-3
Update italian.yml
2018-01-10 16:50:17 +11:00
57ae3945d7 Merge pull request #1836 from PhanaticD/patch-1
nukkit world height is 256
2018-01-10 16:45:52 +11:00
17e4c1ec60 Update NukkitMain.java 2018-01-10 16:45:41 +11:00
b9a4f2256e Update NukkitMain.java 2018-01-10 00:44:38 -05:00
5ddefcea22 when PlayerQuitEvent is never called 2018-01-04 19:24:00 +11:00
47314ce00d Update italian.yml 2017-12-10 15:28:35 +01:00
452bf593e0 Update italian.yml 2017-12-10 14:35:43 +01:00
a9bd6566b7 Update italian.yml 2017-12-10 12:53:22 +01:00
59557cf889 improvements: Message for visit Command to a players without plots (#1796)
We provide now a clear message if we are sure that the Visit command means a player but we dont found any claimed plots for this player.

This is helpful if we try teleport to  a numeric named player

See this related tickets: #1691, #1778
2017-12-09 11:08:15 +01:00
48bdfd75e5 Update italian.yml 2017-12-07 19:50:02 +01:00
6c06e48a1f Merge pull request #1792 from Opachl/PS-#1791
fix: p visit issue in latest builds
2017-12-07 08:54:36 +01:00
70a82d9fc6 fix: p visit issue in latest builds
p visit issue in latest builds #1791
2017-12-06 21:40:26 +01:00
61e045aa50 Update italian.yml (#1789) 2017-12-04 17:02:11 +01:00
d373a4dafa Merge pull request #1787 from Leomixer17/patch-1
Improved the italian translation
2017-12-03 22:47:16 +01:00
9daf13c897 Update italian.yml 2017-12-03 21:13:39 +01:00
7d39d09317 fix: remove plot-alias with "/p alias" (#1779)
* fix: remove plot-alias with "/p alias"

remove plot-alias with "/p alias" #1718

* Apply requested Review Changes

Restored the original Permisson to keep backwards compatibility
Clean unused imports.

* added some improvements after testing

added some improvements after testing
2017-12-03 17:59:36 +01:00
3779b17720 fix: shulker-teleport in a other plot (#1774)
- shulker-teleport in a other plot (Fixes #1762)
 - dropper can't drop lava_bucket and water_bucket  (Fixes #1775)
2017-12-03 17:21:15 +01:00
06208696db fix: numeric Playernames thows NumberFormatException on Teleport (#1778)
* fix: numeric Playernames thows NumberFormatException on Teleport

Refactoring of the Teleport Handling

Supports now:
     * p h xPlotPlayerGuy [PAGE] = Player  [numeric] [alphanumeric]
     * p h MyPlantage      [PAGE] = Alias    [numeric] [alphanumeric]
     * p h PlotworldLarge [PAGE] = World  [numeric] [alphanumeric]
     * p h 1:1		       [PAGE] = plotId  [numeric (1,1|1;2) ]
     * p h 4		                   = 4 th Plot of the Player if available  [numeric (1,1|1;2) ]
Check order: Player, Alias, World, PlotId, Page [PAGE]
[PAGE] is optional

* Apply suggested Code Style

Changes:
Collections now empty instead of null.
Property renaming
2017-12-03 17:15:09 +01:00
f27b12a211 Merge pull request #1767 from Opachl/master
fix: no wether update after "/p flag remove weather"
2017-11-18 14:15:29 +01:00
9413ce0880 fix: no wether update after "/p flag remove weather"
no wether update after "/p flag remove weather" #1723
2017-11-15 11:14:14 +01:00
734c4bb5fe Fix vehicle deletion 2017-11-14 17:24:02 +11:00
6b7adcdf34 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2017-11-14 17:10:05 +11:00
a752780eeb Minor fixes
Update message color
CME on plot action
Creative middle click banner/head
2017-11-14 17:09:51 +11:00
01fafc3be4 Merge pull request #1766 from Opachl/master
fix: Interaction flag with item_frame #1761
2017-11-13 16:13:19 +11:00
c281620d75 Update PlayerEvents.java
added missing import
2017-11-12 17:49:14 +01:00
c3f93a1960 fix: Interaction flag with item_frame
Interaction flag with item_frame #1761
2017-11-12 17:36:58 +01:00
b4e8d782a1 Revert "fix: nteraction flag with item_frame"
This reverts commit a2eb727e25.
2017-11-12 17:35:59 +01:00
a2eb727e25 fix: nteraction flag with item_frame
nteraction flag with item_frame #1761
2017-11-12 17:34:50 +01:00
6e9c103b55 Fix typo 2017-11-12 13:32:09 +11:00
cbf7956a32 Add gradle jar 2017-11-12 12:49:19 +11:00
6e841543b8 Closes #1731 2017-11-09 10:57:17 +11:00
585f1b75a1 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2017-11-09 10:18:58 +11:00
534d627b05 Fixes #1732 2017-11-09 10:18:52 +11:00
fe534bccbe Merge pull request #1753 from Leomixer17/patch-1
Improved italian translation
2017-11-09 10:16:37 +11:00
37f1da0715 Various minor
VehicleMoveEvent
- Move KillRoadVehicles code there
- Fix for pre-1.12
Fix auto merge being disabled
2017-11-09 10:15:16 +11:00
515aca5f06 Merge pull request #1757 from IntellectualSites/FixVehicles
Implement VehicleMoveEvent for Bukkit.
2017-11-08 11:59:46 +11:00
530803c738 Implement VehicleMoveEvent for Bukkit. This fixes #1754. It also makes sure that you cannot use
vehicles to enter plots that you're denied from.
2017-11-06 22:01:18 +01:00
faa24bbdf4 Update italian.yml 2017-11-04 21:36:03 +01:00
5b6d5664e4 Fix fireworks being spawnable in other plots 2017-11-03 06:58:57 +11:00
22429fc3e0 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2017-10-31 23:26:18 +11:00
7e2a911530 Closes #1750 2017-10-31 23:26:08 +11:00
7b04ec9ff3 Merge pull request #1746 from Gabscap/fix-location_equals
Fix Location.equals
2017-10-29 21:08:58 +11:00
097159d606 Fix wrong sign height 2017-10-23 18:23:37 +11:00
04bfe73c29 Fix Location.equals 2017-10-20 14:23:35 +02:00
d4614007ae Fixes #1743 2017-10-14 20:52:35 +11:00
9480c70655 Save world before download 2017-09-30 00:28:39 +10:00
8b6cc7a193 * 2017-09-29 23:23:40 +10:00
0d608245f5 Some tweaks / optimizations 2017-09-25 16:57:42 +10:00
92f94ecedc Tweaks
Use sign with plot schematic
Tweak world unloading
2017-09-24 00:13:05 +10:00
2360782234 * 2017-09-23 20:09:34 +10:00
1d20ae2777 allow air 2017-09-23 19:28:40 +10:00
6b55b8cd67 Allow configuring a separate nonmember home position 2017-09-23 19:10:57 +10:00
c645c4a6cb * 2017-09-23 18:20:27 +10:00
8e55860f77 Center plot schematic 2017-09-23 16:25:28 +10:00
abfbeffbb0 Skip y=255, block when finding a free spot 2017-09-23 15:09:03 +10:00
31908090b8 Buld height check 2017-09-23 14:07:52 +10:00
d97ff94465 Various minor
Fix download world spawnpoint
Fix regenallroads on augmented world
Ensure all chunks have unloaded before unloading a world
2017-09-20 00:33:29 +10:00
ce90b36d28 Wrap plot.schematic 2017-09-13 13:57:07 +10:00
20d7a0eea2 Don't overwrite online player names from uuid cache 2017-09-06 19:49:57 +10:00
24b3b60983 Might fix #1704 2017-09-01 23:11:37 +10:00
17154ef1d5 idk why that wasn't working 2017-08-18 23:34:27 +10:00
538e2a6002 Varios
Fixes #1697
Fixes #1689
2017-08-18 12:37:26 +10:00
84a6a6daf4 Closes #1643 2017-08-10 17:24:59 +10:00
a2324190bb Fixes #1619 2017-08-10 17:18:35 +10:00
af99c6a706 * 2017-08-10 17:15:03 +10:00
c9cee8a4a8 Fixes #1504 2017-08-10 17:12:27 +10:00
da51be20a3 Fix compile 2017-08-10 16:55:57 +10:00
c808257b7c Fixes #1668 2017-08-10 16:52:17 +10:00
c3759f8963 Fixes #1672 2017-08-10 16:46:51 +10:00
c36ef1d237 Fixes #1673
+ unrelated plotme conversion fix
2017-08-10 16:35:53 +10:00
f49d43d6a3 Notify player when using an invalid purge argument 2017-08-10 16:11:50 +10:00
cc1324f581 Fixes #1682 2017-08-09 15:45:27 +10:00
ac9042bbe4 Various minor
New plugin updater and versioning
In game changelog
fix login teleporting
2017-08-09 15:05:13 +10:00
b280644661 Delete build 2017-08-09 15:01:16 +10:00
b924809c91 Fixes #1608 2017-08-03 23:13:04 +10:00
a913983d99 Add plot leave 2017-07-25 06:39:59 +10:00
3633576e03 Fix teleport for single plot worlds 2017-07-08 23:22:05 +10:00
73318f23a1 Fixes #1660 2017-07-08 21:56:15 +10:00
248751378b Fixes #1661 2017-07-08 21:50:47 +10:00
1918000668 Merge pull request #1645 from dordsor21/master
Lower TPS threshold please
2017-07-07 16:12:26 +10:00
9037b74720 Closes #1659 2017-07-07 16:11:46 +10:00
f6540bbfcb bypass owner check for download 2017-06-29 15:38:37 +10:00
507d0f19e4 Lower TPS threshold please 2017-06-24 16:11:52 +01:00
355e16fe92 Ignore searching top block for teleportation 2017-06-09 17:43:46 +10:00
2b1905889c Minor sponge fix 2017-05-16 13:20:28 +10:00
7ee67c8b41 Merge pull request #1599 from Gabscap/fix-min_height
Fix world.min_height setting
2017-05-03 14:58:16 +10:00
f8ab36b67c Fix world.min_height setting 2017-05-01 21:23:21 +02:00
b5ef5df20d * 2017-04-28 01:47:05 +10:00
509b1f1c3d Fixes #1593 2017-04-28 00:59:59 +10:00
bfe98f3285 Some claiming fixes 2017-04-20 14:12:40 +10:00
47915b8b86 Read sign on main thread 2017-04-20 01:09:52 +10:00
3c110bb125 Fixes #1585 2017-04-18 22:55:04 +10:00
a87fee1224 Merge pull request #1583 from manuelgu/patch-3
Added useSSL=false to JDBC connection URL
2017-04-17 22:28:20 +10:00
757b9c695f Fix compile 2017-04-17 19:11:55 +10:00
193948d4fd Fix claim 2017-04-17 11:56:10 +10:00
b616951e23 Added useSSL=false to JDBC connection URL
This is required according to MySQL 5.5.45+, 5.6.26+ and 5.7.6+.
2017-04-16 22:17:17 +02:00
37977f1da4 Check database before claiming plot 2017-04-15 12:40:23 +10:00
7eb7cd9b53 Ensure world loading occurs on the main thread 2017-04-11 01:49:01 +10:00
ddfcc5b077 Player login tweaks 2017-04-10 09:06:44 +10:00
9f6bf14649 Log when a plot is created/deleted 2017-04-09 17:10:23 +10:00
f99994737c Print error when failing to close database 2017-04-09 17:09:06 +10:00
6e0ade4f63 Some sponge fixes 2017-04-07 08:25:08 +10:00
c1a6c75ebe * 2017-04-04 08:07:54 +10:00
022372e9b7 Fixes #1534 + various
Auto world loading/unloading
Auto player teleporting on login
2017-04-04 07:59:36 +10:00
3f54ba23c2 Fix world delete 2017-04-01 04:36:45 +11:00
e8672df760 Add Gitter badge (#1565) 2017-03-27 12:03:33 -04:00
5d6f4c6668 Some plot area restructuring 2017-03-23 11:10:29 +11:00
a07ed4eafd * 2017-03-18 00:50:43 +11:00
5262ff665a Fix door break 2017-03-18 00:49:41 +11:00
1129a80329 Fixes #1510 2017-03-17 17:41:58 +11:00
a628c5927f Fixes #1560 2017-03-17 16:40:29 +11:00
478ad9670b Fixes #1476 2017-03-16 14:15:00 +11:00
8e3407505a Recover on database error
Might resolve #1476
2017-03-15 02:10:57 +11:00
e208d7f72a Fix mass purge 2017-03-15 01:28:02 +11:00
b0df79bb80 Break up purge task 2017-03-15 00:16:27 +11:00
411c75b219 Fixes #1556 Close #1555 2017-03-14 01:56:14 +11:00
491cc50440 Fixes #1528 2017-03-13 18:45:37 +11:00
e9723f5be1 Fixes #1532 2017-03-13 18:38:58 +11:00
a015039dad Fixes #1535
Set `misc_spawn_unowned`
2017-03-13 18:36:40 +11:00
a0640a1e66 Fixes #1536 2017-03-13 18:12:38 +11:00
0b6d2d3dd6 Fixes #1538 2017-03-13 18:07:48 +11:00
ad11ad3472 Fixes #1517 2017-03-13 18:02:05 +11:00
93717e670c Use InteractBlockEvent
For some reason sponge was calling the event twice, the second with a
relative location, which makes no sense. Switching to a different event
works.
2017-03-13 17:34:44 +11:00
38a33248e7 Send message on perm check 2017-03-13 09:04:40 +11:00
52496af9a1 Fix road interact on sponge 2017-03-13 07:16:16 +11:00
4d4950090d Fix 1.7 block placer 2017-03-10 07:07:50 +11:00
c8c144b6da Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2017-03-08 16:51:29 +11:00
e94adb04ea Add maven repo
closes #1394
2017-03-08 16:51:01 +11:00
395c1c743f Merge pull request #1537 from HexagonMC/master
Fix plot teleport.
2017-03-06 15:40:28 +11:00
b1fb01303d Fix plot teleport.
Fixes https://github.com/IntellectualSites/PlotSquared/issues/1302
2017-02-20 20:29:43 +01:00
aa7b770c03 tweak highest block check 2017-01-31 16:45:02 +11:00
e7990a06e2 Check player name for invalid character first 2017-01-30 19:42:16 +11:00
88f5e5b0bc Sort player names 2017-01-15 22:51:54 +11:00
47db330764 Fix title global flag 2017-01-13 08:05:13 +11:00
35ebc8c830 Permission check fix 2017-01-13 07:22:28 +11:00
686a6c499f Fixes #1502 2017-01-11 07:53:53 +11:00
cb6d839214 Possible fix for #1476
Changes database load to prefer the latest entry over older ones.

Some previous changes may fix connections dropping, which resulted in
(incorrect) fixes being attempted by the plugin.
2017-01-11 07:21:36 +11:00
6af96f43d4 Optimize schematic paste 2016-12-31 17:23:46 +11:00
e3eccfd476 Fix debugpaste 2016-12-31 17:23:38 +11:00
15d4b6d34b Bump spigot version 2016-12-29 07:23:51 +11:00
c3e2421d51 Merge pull request #1492 from c7w/master
Update s_chinese.yml
2016-12-25 17:32:36 +11:00
c7w
f7793f027c Update s_chinese.yml 2016-12-25 14:30:32 +08:00
6ec96870c0 Fix SO 2016-12-23 15:33:19 +11:00
a843203ca3 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	Core/src/main/java/com/intellectualcrafters/plot/object/Plot.java
2016-12-15 17:42:51 +11:00
3240fc9559 Exit plot on unclaim
Fixes #1471
2016-12-15 17:37:26 +11:00
5fd1486cec Merge pull request #1478 from EvilOlaf/patch-2
Update ISSUE_TEMPLATE.md
2016-12-13 01:44:37 +11:00
d648148f51 Update ISSUE_TEMPLATE.md 2016-12-12 15:42:00 +01:00
d554dab8c8 Fix potential NPE with claiming 2016-12-10 14:33:48 -05:00
9ad45750ee Unclaiming a plot should call plotExit() 2016-12-09 20:58:05 -05:00
a554ae5633 Potential fix for commands 2016-12-09 16:58:32 -05:00
7b1c4a5042 Check border when claiming a plot
Also fixes #1467
2016-12-10 01:09:07 +11:00
9fc464e896 Shorter border teleportation 2016-12-10 00:44:42 +11:00
bec11b244e Use the correct plot id 2016-12-10 00:26:40 +11:00
dc94418b51 Only expand border to current plot. 2016-12-09 23:52:48 +11:00
72ab10c079 remove debug 2016-12-03 23:08:10 +11:00
f50d32f06b * 2016-12-02 17:17:16 +11:00
6cc744a2e6 Fixes #1444 2016-12-02 17:16:19 +11:00
e40dc37f89 Fix versioning messup. 2016-12-01 21:56:19 -05:00
7e34d9e20a Fix title logic 2016-11-30 21:26:52 +11:00
c891abce09 Allow added players to use frost walker
Properly fixes #1438
2016-11-30 20:46:48 +11:00
2b561f2efa Rename to ice-form 2016-11-30 19:06:03 +11:00
dea0a452df Add fading 1.11 titles 2016-11-30 16:28:50 +11:00
81418b07a8 Fixes #1438 (unless other things call this event) 2016-11-30 16:15:20 +11:00
a3c1ad3ec8 Fixes #1449 2016-11-30 16:10:08 +11:00
7c6c19ba63 Fixes #740 2016-11-30 16:07:16 +11:00
2e23ae0811 Fixes #1243 2016-11-30 16:00:47 +11:00
28e7f5bc08 Fixes #1349
Non standard plot managers/areas not supported
2016-11-30 15:57:24 +11:00
7a1417dc56 Fixes #1415 2016-11-30 15:45:28 +11:00
e7fa9e01be Fixes #1419 2016-11-30 15:43:23 +11:00
93414d54c1 Fixes #1453 2016-11-30 15:41:08 +11:00
5642fd3899 Fixes #1359
plots.chat.color
and
PLOT_CHAT_SPY_FORMAT
2016-11-30 15:36:13 +11:00
f3d950f6e1 Fix flame enchant damaging entities 2016-11-30 15:03:48 +11:00
95f8aaa2fe this could be here? 2016-11-30 13:10:36 +11:00
878010255c Java 9 2016-11-28 18:02:03 +11:00
8edc357d01 Fixed #1448 2016-11-27 01:26:06 -05:00
588639d9c2 3.5.1 Start 2016-11-27 01:08:35 -05:00
ff401b65c4 3.5.0 Release 2016-11-26 18:02:39 -05:00
11913bfbe5 Fix compile issue 2016-11-26 17:53:44 -05:00
62b353f82d Various Sponge changes
- many improvements
- inventory utilities broke when updating to Sponge API 6.0.0
2016-11-26 16:49:13 -05:00
8d442f58d4 Fixes #1445 2016-11-26 12:05:08 -05:00
5cbd2f44bd Update Sponge Gradle 2016-11-26 11:55:59 -05:00
dc673f9715 Fixed #1440 , Fixed #1446 2016-11-26 11:55:38 -05:00
deb5441bcf *Fix compile error 2016-11-24 11:05:28 +11:00
8ebf71c87f DB fix 2016-11-24 10:19:00 +11:00
9fd53af483 Add world argument 2016-11-23 15:47:18 +11:00
fb729df59e Setting to sort plots by area 2016-11-23 15:36:25 +11:00
ce6e1be13e Fix maven dependencies (#1439)
* Fixes

* Fix wrong version
2016-11-21 09:59:11 -05:00
e126054053 Fixes #1429 Removes duplicate aliases. 2016-11-20 22:29:14 -05:00
77281017d4 Fixes #1428 , Fixes #1431 2016-11-20 22:24:27 -05:00
e0208aa369 Fix plot help category pagination 2016-11-18 10:49:03 +11:00
fdc42a3d5c Seems the new spigot 1.11 sqlite driver has issues parsing timestamps, no idea why. 2016-11-18 09:08:41 +11:00
3070557a3a Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-11-13 22:18:11 +11:00
2ec0b55482 Fix database lock error 2016-11-13 22:17:17 +11:00
10dd9b6371 Merge pull request #1424 from c7w/master
translation
2016-11-13 06:41:25 +11:00
c7w
1ac0a7dad0 translation
translation of chinese
2016-11-12 12:52:43 +08:00
f8b1fcffa1 Fix worldedit mask area 2016-11-12 00:14:12 +11:00
17762f5ae7 Tweak delete message 2016-11-09 00:13:46 +11:00
1d7cdde84a Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-11-02 04:28:11 +11:00
c950b0021f Notify inbox permission 2016-11-02 04:27:52 +11:00
e4bc2b30b1 Update ISSUE_TEMPLATE.md (#1409) 2016-10-28 10:15:38 -04:00
e0c4c944bb Merge remote-tracking branch 'origin/master' 2016-10-26 23:01:01 -04:00
dd09ef18e6 Add missing gradle batch
Signed-off-by: MattBDev <mattbdev@outlook.com>
2016-10-26 23:00:43 -04:00
68011f43cd Fixes #1390 2016-10-21 03:51:27 +11:00
93c4854454 Add misc-interact flag 2016-10-18 05:03:14 +11:00
e594227d95 Fix some height issues 2016-10-14 16:56:28 +11:00
d6be5703ae Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-10-14 15:14:35 +11:00
c97544d083 Minor fixes 2016-10-14 15:14:08 +11:00
a05fd2dd11 Fix #1386
Signed-off-by: MattBDev <mattbdev@outlook.com>
2016-10-10 00:18:35 -04:00
5978c9c3c0 Fix center 2016-10-03 00:56:27 +11:00
5d3e096501 *Fix the toggle 2016-10-03 00:56:26 +11:00
39e99c0593 Merge pull request #1381 from filoghost/patch-1
Fix permission checks being ignored
2016-10-02 14:08:22 +11:00
cd33aaa1b6 Fix permission checks being ignored 2016-10-01 21:35:57 +02:00
0244c0241c Trim deletes expired plots 2016-10-01 20:17:50 +10:00
5ed2190cb3 Fixes #1369 2016-09-30 23:32:49 +10:00
c533f0bae9 Fix area removal 2016-09-30 17:05:18 +10:00
cd2b6c8ccc Fixes #1379 2016-09-30 17:04:06 +10:00
6f2c7de0ff Minor fix to conversion 2016-09-30 16:46:10 +10:00
62373c0737 * 2016-09-30 16:15:15 +10:00
499120963a Streamline PlotMe conversion
Use reflection to disable PlotMe and forward DefaultGenerator to
PlotSquared
Fix border material copying from plotme config
You no longer need to delete the PlotMe jar for conversion
Fix some outdated messages
2016-09-30 16:14:35 +10:00
f1d581a8d8 Fixes #1377 2016-09-30 15:29:50 +10:00
6074fc8033 Nukkit generator fixes 2016-09-30 14:26:20 +10:00
e4d7270c28 Fix some merged plot events 2016-09-30 03:30:34 +10:00
b6df07f723 Add snow-form flag 2016-09-27 01:38:59 +10:00
177b33154f Multiple
Fixes #1362
Fixes border id for PlotMe converter
2016-09-27 00:56:39 +10:00
6bf2fbcfcf Command tweaks 2016-09-26 18:33:27 +10:00
12f8861d07 Various
externalize strings
plotme conversion fixes
2016-09-26 18:31:08 +10:00
c99e23bd3c Fixes #1367 2016-09-25 18:48:38 +10:00
1b6d08b3fe Fixes #1365 2016-09-25 18:43:53 +10:00
3b4490c1c6 Fixes #1366 2016-09-25 18:42:05 +10:00
04c011164a Add near cmd 2016-09-25 18:06:20 +10:00
86b776f742 Nukkit perms 2016-09-25 16:49:51 +10:00
61022b717a Fixes #1360 2016-09-21 13:42:59 +10:00
9e5af7a642 Possible fix for redstone in merged plots 2016-09-20 23:49:22 +10:00
364b4347d1 Fix area id parsing 2016-09-19 14:18:47 +10:00
d89274ce09 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java
2016-09-17 16:03:57 +10:00
264114332b Let generator be up to the implementation 2016-09-17 16:02:05 +10:00
a4363bdb27 Fix #1355
There is the possibility this will cause issues with sponge

Signed-off-by: MattBDev <mattbdev@outlook.com>
2016-09-14 19:27:30 -04:00
8e7e5dcb25 Cleanup
Signed-off-by: MattBDev <mattbdev@outlook.com>
2016-09-14 12:16:22 -04:00
56227a6d7d Fixes #1351 2016-09-14 10:21:14 +10:00
63259ec269 Merge pull request #1352 from MisterErwin/master
A (possible) fix to #1351
2016-09-14 10:17:11 +10:00
0286a7b046 Fixes #1131 2016-09-14 10:12:53 +10:00
b6dac54677 Code cleaning and Gradle Update
Updated gradle wrapper to 3.0
Updated Gradle files for Nukkit
Added/cleaned minor Nukkit code
Removed duplicate TitleManagement code

Signed-off-by: MattBDev <mattbdev@outlook.com>
2016-09-13 18:10:01 -04:00
bf1d487508 A (possible) fix to #1351 2016-09-12 17:05:13 +02:00
a95b68b73c Add villager-interact flag 2016-09-09 15:17:37 +10:00
85ff8bf639 Minor tweaks 2016-09-07 00:28:01 +10:00
0557671b80 Recover from third party generator error 2016-09-04 14:22:01 +10:00
d75ab130da Sponge fixes 2016-09-02 15:58:24 +10:00
6a12a6ba64 print chat to console
Fixes #1339
2016-09-02 15:47:19 +10:00
22901bf9f2 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-09-01 16:57:52 +10:00
07ee19b4bb Fixes #1337 2016-08-31 19:09:17 +10:00
27c21b9ab6 Fix #1321 2016-08-30 21:50:52 -04:00
da7a12bc00 Fixes #1234 2016-08-29 16:21:14 +10:00
3b73b2e9d8 Fix grant check 2016-08-29 15:33:26 +10:00
970c80cb15 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-08-29 15:01:27 +10:00
dd665ed9ce Fence rotation 2016-08-29 15:01:19 +10:00
572da7d436 Merge pull request #1332 from manuelgu/patch-2
Might resolve #1331
2016-08-29 14:41:48 +10:00
ab05b026e9 Merge pull request #1335 from Herocraft/fix/vault-repo
Switch Vault repository to the real one
2016-08-29 12:19:48 +10:00
2fcb59f8cf Switch Vault repository to the real one 2016-08-28 18:26:11 -07:00
20250bc989 Might resolve #1331
Wasn't able to reproduce the issue
2016-08-28 20:14:58 +02:00
5e4798165b Merge pull request #1330 from MinelinkNetwork/fix-pom
Fix Spigot artifact in POM
2016-08-28 18:26:57 +10:00
7fc3fb097e Fix Spigot artifact in POM
Use the correct groupId, artifactId and version of Spigot dependency
installed by BuildTools
2016-08-28 01:13:21 -07:00
3a08e5c091 Merge pull request #1326 from SupremeMortal/SupremeMortal-patch-1
Update Non-existent Repo
2016-08-28 00:52:04 +10:00
50770a78d7 Fixed mistake 2016-08-27 14:09:03 +01:00
1266eed86a Add Replacement Repo For Vault 2016-08-27 14:08:35 +01:00
c0996299b4 Remove non-existent Repo
"nexus.theyeticave.net" does not exist anymore.
2016-08-27 14:03:41 +01:00
90d48b2cd0 Fixes #1289 2016-08-26 13:54:22 +10:00
a95d18499e Fixes #1285 2016-08-26 13:19:42 +10:00
61d00e51ef Fixes #1303 2016-08-26 03:02:50 +10:00
b5349e16f0 Fixes #1305
Just teleports the player further back
Combine move/tp since tp extends move
2016-08-26 02:31:50 +10:00
a801127036 Merge pull request #1301 from MisterErwin/master
Calling events when players are removed from plots & correct calling of Member & Trusted events
2016-08-26 02:02:40 +10:00
2806f8b20c Fixes #1307 2016-08-26 01:36:35 +10:00
7d11147836 Add Lazzy "Offline -> Offline Lowercase" conversion 2016-08-20 21:40:54 +10:00
74a6df1fa7 Update README.md 2016-08-20 00:26:53 -04:00
bc0c0abe7e Fix NPE 2016-08-19 12:16:13 +10:00
56907e4580 Version Bump
3.4.6-SNAPSHOT
2016-08-18 10:38:06 -04:00
005e13a216 Maybe #1239 2016-08-17 18:30:58 +10:00
3558105789 Fix default flags NPE 2016-08-17 15:08:01 +10:00
f651607d2f Might work? 2016-08-17 12:22:45 +10:00
6b95e57d9e Merge pull request #1313 from MinelinkNetwork/blocked-cmds
Only show blocked-cmds message when event is cancelled
2016-08-17 12:13:27 +10:00
98d0819383 Only show blocked-cmds message when event is cancelled 2016-08-16 19:09:02 -07:00
30da060f83 Potential fix for schematic placement on clear 2016-08-16 15:53:26 +10:00
e4408d56ec *And this 2016-08-16 14:32:31 +10:00
f07ac646f3 Possible fix for greeting spam 2016-08-15 09:31:03 +10:00
ef3380dc0a Merge remote-tracking branch 'origin/master' 2016-08-12 15:04:18 -04:00
749ab83e5d Move permission check out of loop
See #1307
2016-08-12 15:04:11 -04:00
daea9cf60d Allow teleportation for console 2016-08-10 12:33:18 +10:00
2f74368879 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-08-09 12:45:45 -04:00
63d4476d97 Fix #1181 2016-08-09 12:40:38 -04:00
db69da5b07 *Wrong runnable 2016-08-09 08:52:31 +10:00
634802ef98 Got rid of that auto-optimize-imports option 2016-08-08 23:20:31 +02:00
37e4a652dd Now calling the respective events when a user is removed from a plot.
And switched the event calling of adding Helpers and Trusted players. (Correct me if that was wrong)
2016-08-08 22:45:08 +02:00
d22f7b8781 Merge remote-tracking branch 'origin/master' 2016-08-08 14:03:17 -04:00
112da17614 Squashed commit of the following:
commit 91c78407cd
Author: Jesse Boyd <jessepaleg@gmail.com>
Date:   Sun Aug 7 11:29:59 2016 +1000

    Use a queue for expiry

commit 395d6364be
Author: Jesse Boyd <jessepaleg@gmail.com>
Date:   Sun Aug 7 04:43:41 2016 +1000

    Cache on fail as well

commit facd43700d
Author: Jesse Boyd <jessepaleg@gmail.com>
Date:   Sun Aug 7 04:00:50 2016 +1000

    Cache entity count every second

commit 1ae694ff5b
Author: Jesse Boyd <jessepaleg@gmail.com>
Date:   Sun Aug 7 03:52:37 2016 +1000

    Tweak entity counting

commit c99dd1e74a
Author: Jesse Boyd <jessepaleg@gmail.com>
Date:   Sat Aug 6 00:10:11 2016 +1000

    Needs sponge builds

commit f408ac82be
Author: Alexander Söderberg <Sauilitired@users.noreply.github.com>
Date:   Fri Aug 5 12:13:39 2016 +0200

    Update README.md

commit 9b95990ba6
Author: Alexander Söderberg <Sauilitired@users.noreply.github.com>
Date:   Thu Aug 4 16:50:37 2016 +0200

    Update this here as well
2016-08-08 14:02:25 -04:00
91c78407cd Use a queue for expiry 2016-08-07 11:29:59 +10:00
395d6364be Cache on fail as well 2016-08-07 04:43:41 +10:00
facd43700d Cache entity count every second 2016-08-07 04:00:50 +10:00
1ae694ff5b Tweak entity counting 2016-08-07 03:52:37 +10:00
c99dd1e74a Needs sponge builds 2016-08-06 00:10:11 +10:00
f408ac82be Update README.md 2016-08-05 12:13:39 +02:00
9b95990ba6 Update this here as well 2016-08-04 16:50:37 +02:00
77fb329c9e Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-07-31 21:26:18 -04:00
a13b9fb31b flag tix 2016-08-01 11:20:06 +10:00
ea3306d070 Fix #1034 2016-07-31 20:17:35 -04:00
bcbcd6d916 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-07-31 18:14:12 +10:00
415c6fb0d4 Fixes #1283 2016-07-31 18:14:06 +10:00
e801c6d7e8 Merge branch '3.4.5' 2016-07-31 00:16:37 -04:00
409456e895 Minor sponge fix 2016-07-31 09:16:58 +10:00
e8f4eae6f7 Merge remote-tracking branch 'origin/3.4.5' into 3.4.5
# Conflicts:
#	Sponge/build.gradle
#	Sponge/src/main/java/com/plotsquared/sponge/util/SpongeSetupUtils.java
2016-07-29 21:45:34 -04:00
c8419f4a4a Added more Java 8 warnings 2016-07-29 21:40:23 -04:00
09994724db Fix #1277 2016-07-29 21:40:02 -04:00
610e204d12 Fix #1281 , Fix #1282 , and Sponge gradle 2016-07-29 12:47:42 -04:00
1f341e6ba9 Merge remote-tracking branch 'origin/master' into 3.4.5
# Conflicts:
#	Sponge/src/main/java/com/plotsquared/sponge/SpongeMain.java
#	Sponge/src/main/java/com/plotsquared/sponge/generator/SpongeAugmentedGenerator.java
#	Sponge/src/main/java/com/plotsquared/sponge/util/SpongeSetupUtils.java
#	Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java
#	Sponge/src/main/java/com/plotsquared/sponge/util/block/GenChunk.java
#	build.gradle
2016-07-29 12:25:11 -04:00
ffddf5c187 Fix sponge generator cast 2016-07-29 12:12:28 +10:00
b5ec6232f9 Sponge Fixes and minor changes. 2016-07-25 22:25:15 -04:00
34c2da55ca Change Sponge method behavior 2016-07-25 22:25:15 -04:00
33ec80c2cb Fix Sponge generation casting 2016-07-25 22:25:15 -04:00
48064da1ee Fixed deny-teleport flag 2016-07-25 22:25:15 -04:00
adc021109f Added Polar Bear where missing 2016-07-25 22:25:15 -04:00
d23d8c2fd8 *should use this cause instead 2016-07-25 22:25:15 -04:00
3498f309e8 Minor sponge fixes 2016-07-25 22:24:31 -04:00
0b5177f192 Minor uuid cache changes 2016-07-25 22:23:49 -04:00
07dc6a46fb Remove metrics depend 2016-07-25 22:23:19 -04:00
0b19cc7d9d Possible fix + add guest-gamemode flag 2016-07-25 22:23:19 -04:00
4e019ab796 UUID cache changes 2016-07-25 22:23:19 -04:00
b2fdcad317 Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared into 3.4.5
# Conflicts:
#	Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java
#	Sponge/src/main/java/com/plotsquared/sponge/util/block/GenChunk.java
2016-07-25 22:08:54 -04:00
80ea3e9ce7 Sponge Fixes and minor changes. 2016-07-25 20:00:59 -04:00
5f8c77a6cd Change Sponge method behavior 2016-07-25 18:43:11 -04:00
290e5c68dc Fix Sponge generation casting 2016-07-25 18:42:31 -04:00
5d92701100 Fixed deny-teleport flag 2016-07-25 18:04:17 -04:00
1a86d5fb9e Added Polar Bear where missing 2016-07-25 01:19:29 -04:00
30d18c917d *should use this cause instead 2016-07-25 09:54:35 +10:00
b91eab2f0c Minor sponge fixes 2016-07-25 09:47:49 +10:00
770b9be160 Minor uuid cache changes 2016-07-25 09:23:20 +10:00
14b2b11bf3 Remove metrics depend 2016-07-25 08:09:57 +10:00
975a5765c1 Possible fix + add guest-gamemode flag 2016-07-25 08:02:17 +10:00
2b9c2959cf Merge branch '3.4.5' of https://github.com/IntellectualSites/PlotSquared into 3.5.0 2016-07-24 17:45:34 -04:00
07977ac2ce UUID cache changes 2016-07-25 07:44:47 +10:00
9e5ac80435 Merge remote-tracking branch 'origin/3.4.5' into 3.4.5 2016-07-24 17:42:21 -04:00
dda6849412 Fix sponge compile 2016-07-24 17:42:03 -04:00
85d6e42462 Merge branch '3.4.5' of https://github.com/IntellectualSites/PlotSquared into 3.5.0 2016-07-24 17:27:41 -04:00
b1ee223b0a Merge pull request #1271 from manuelgu/patch-1
Make debug output useful
2016-07-24 07:51:45 +02:00
98e865cdf0 Make debug output useful 2016-07-23 12:50:39 +02:00
8b084839fd Fix #1261 2016-07-19 10:22:50 -04:00
c1d4c481fb Fix #1244 2016-07-17 23:20:31 -04:00
269e409e3e Version Bump 2016-07-17 23:19:37 -04:00
8538170cba Metrics 2016-07-16 22:51:49 -04:00
76bce7c0ef Catch CommandException 2016-07-14 20:29:11 +10:00
ba568a3f60 Recover from invalid flag value 2016-07-14 00:28:46 +10:00
a43430b722 Fix NPE for null arg 2016-07-13 00:14:26 +10:00
e2c57cea52 . 2016-07-12 23:56:59 +10:00
ca776b2912 Fixes #1226 2016-07-12 22:12:14 +10:00
e859a7f56c Change to interact perm, not build 2016-07-11 20:27:25 +10:00
ad2db9b836 Merge pull request #1245 from manuelgu/fix/CentreCenterName
Add additional alias for /p middle
2016-07-10 22:58:54 +10:00
279084b043 Add additional alias for /p middle
http://grammarist.com/spelling/center-centre/
2016-07-09 09:18:55 +02:00
8b0e59209c Remove getServerName() 2016-07-05 23:43:08 -04:00
ca8b82dcbe Version Bump 2016-07-05 23:39:38 -04:00
cf5d2a5e86 Entity Fix and Gradle changes 2016-07-01 17:13:49 -04:00
b9ad75ad84 Add teleport flag 2016-06-29 21:22:55 +10:00
185352d3cf Fixes #1229 2016-06-29 15:23:10 +10:00
f4fe762135 * 2016-06-28 20:21:50 +10:00
06682b18a5 Fix compile
Recover on unknown command error
Fixes #1224
Close #1213 (fixed elsewhere)
Fixes #1212
2016-06-28 19:55:51 +10:00
f8e97f14d6 Fix end crystal spawn cap 2016-06-28 02:03:23 +10:00
a579df00db Merge remote-tracking branch 'origin/master' 2016-06-27 10:14:28 -04:00
29a0b68dcb Fix currently online for seen info. 2016-06-27 23:59:38 +10:00
d2581bf38b Merge branch 'master' of https://github.com/IntellectualSites/PlotSquared 2016-06-27 09:58:17 -04:00
817a5bc16e Various
Fix compatibility with bukkit 1.5
Recover on failed fancy message initialization
Fix /2 remove *
2016-06-27 18:38:14 +10:00
047f9a75b9 Fix #1222 2016-06-27 17:45:19 +10:00
96d0bb0e5e bump pom version 2016-06-26 17:08:54 +10:00
7da0b9877f Fixes #1221 (the NPE at least) 2016-06-26 17:07:46 +10:00
f20ef15774 Revert creature spawn message + change expire to seen 2016-06-26 04:30:12 +10:00
3a973342ae Merge remote-tracking branch 'origin/master' 2016-06-24 10:59:18 -04:00
6e25aab51f Cleanup some docs. 2016-06-24 10:56:38 -04:00
a49492aae3 Fix roadregen 2016-06-24 16:16:22 +10:00
dbe965e901 init script engine on get 2016-06-24 15:41:34 +10:00
2c82d1106a Fixed kick message 2016-06-23 23:19:02 -04:00
5b9dc59abf Updates to docs, code style tweaks, and some code optimizations 2016-06-23 20:12:17 -04:00
b587b430b8 #1211 2016-06-24 05:30:26 +10:00
8fd2599686 Fixes #1211 2016-06-24 02:20:21 +10:00
56000d60e7 Just in case 2016-06-23 13:14:29 +10:00
1643399fc6 Alternatives for setowner none if the username is taken 2016-06-23 13:11:26 +10:00
532fd09800 Merge remote-tracking branch 'origin/master' 2016-06-22 23:10:15 -04:00
e6387419f7 Potential fix for plot biome (untested) 2016-06-23 13:09:56 +10:00
30d49880b6 Fix #1208 NPE 2016-06-22 16:31:04 -04:00
16d191db2c Fixes /plot kick * 2016-06-23 04:08:06 +10:00
7dc7714261 Update Gradle to 2.14 2016-06-22 12:31:25 -04:00
9e1f6d8748 Closes #1209 2016-06-22 13:33:32 +10:00
7fb2631421 Cast to string if necessary 2016-06-21 14:23:04 +10:00
718831e8e0 * 2016-06-21 14:10:20 +10:00
df4585a847 Check args for grant 2016-06-21 13:38:08 +10:00
88d8339cfd fix other NPE 2016-06-21 13:32:28 +10:00
e08db3d12b Check teleportation on command location prefix 2016-06-21 03:02:41 +10:00
2ff4e07919 Setup border on world creation 2016-06-21 01:13:09 +10:00
f6fec56677 Potential fix for terrain 3 worlds. 2016-06-21 00:29:39 +10:00
3fabfa10d7 Add liquid-flow flag 2016-06-20 22:48:04 +10:00
a2ca9a52ea Merge pull request #1205 from manuelgu/fix/deadlink
Remove dead link
2016-06-20 18:52:35 +10:00
e5e3600206 Why were these restricted to players? 2016-06-20 18:52:00 +10:00
7ad50b6314 Remove dead link 2016-06-20 10:49:40 +02:00
01d508edf4 Fix remove * 2016-06-20 15:08:56 +10:00
630 changed files with 39650 additions and 34952 deletions

View File

@ -1,12 +1,22 @@
# Bug report template (Follow this template unless you are making a feature request.)
**Debug paste link**:
# Bug report template
<!--- In order to create a valid issue report you have to follow this template. -->
<!--- Incomplete reports might be marked as invalid. -->
<!-- Feature requests and enhancements may be suggested at https://github.com/IntellectualSites/PlotSquaredSuggestions. -->
**Debug paste link:**
<!--- Enter /plot debugpaste in game or in your console and copy the output here -->
**Description of the problem:**
**How to replicate:**
<!--- If you can reproduce the issue please tell us as detailed as possible step by step how to do that -->
**Checklist**:
<!-- Make sure you have completed the following steps (put an "X" between of brackets): -->
- [] I included a `/plot debugpaste` link
- [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue)
- [] I made sure I am using an up-to-date version of PlotSquared
- [] I Made sure the bug/error is not caused by any other plugin
**Description of the problem:**
**How to replicate**:
Make sure you've completed the following steps (put an X between of brackets):
- [] Include `/plot debugpaste`
- [] Made sure there aren't duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue)
- [] Made sure you're using an updated version of PlotSquared
- [] Made sure the bug/error isn't caused by any other plugin

15
.github/auto-comment.yml vendored Normal file
View File

@ -0,0 +1,15 @@
# Comment to a new issue.
issueOpened: >
Thank your for raising a issue. We will try and get back to you as soon as possible.
Please make sure that you followed the issue template, and provied all neccessary information.
Failure to do so will prevent us from resolving the issue in a timely manner.
Please note that suggestions are now to be submitted to https://git.io/fN5B4 rather than this issue tracker!
pullRequestOpened: >
Thank your for raising your pull request.
Please make sure you have followed our contributing guidelines and to take an extra look at the code to make sure that it is functional!
We will review it as soon as possible!

16
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,16 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- [‼] high priority
# Label to use when marking an issue as stale
staleLabel: Old
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

14
.gitignore vendored
View File

@ -1,13 +1,14 @@
### Others ###
*.bat
*.cmd
*.sh
*.prefs
Sponge/build
Core/build
Bukkit/build
Nukkit/build
### Maven ###
/mvn
/target/lib
/target/maven-archiver
/target/classes
@ -20,6 +21,7 @@ release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
out/
### Java ###
@ -29,7 +31,6 @@ buildNumber.properties
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
@ -131,4 +132,11 @@ local.properties
# STS (Spring Tool Suite)
.springBeans
/target/
/target/
Nukkit/build/classes/
Nukkit/build/dependency-cache/
checkstyle.xml
classes/
p2error.txt
*.bat
Nukkit/build/resources/main/plugin.yml

View File

@ -1,38 +1,51 @@
dependencies {
compile project(':Core')
compile 'org.bukkit:bukkit:1.10-R0.1-SNAPSHOT'
compile 'org.mcstats.bukkit:metrics:R7'
compile 'net.milkbowl.vault:VaultAPI:1.6'
repositories {
maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" }
maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "http://nexus.hc.to/content/repositories/pub_releases" }
maven { url = "https://repo.codemc.org/repository/maven-public" }
mavenLocal()
}
sourceCompatibility = 1.7
targetCompatibility = 1.7
dependencies {
compile project(':Core')
testCompile project(':Core')
compile 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT'
compile(group: 'com.sk89q.worldedit', name: 'worldedit-bukkit', version: '7.0.0-SNAPSHOT')
compile(group: 'org.bstats', name: 'bstats-bukkit', version: '1.4')
compile("net.milkbowl.vault:VaultAPI:1.7") {
exclude module: 'bukkit'
}
compileOnly 'org.projectlombok:lombok:1.18.4'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
processResources {
from('src/main/resources') {
include 'plugin.yml'
expand(
name: project.parent.name,
version: project.parent.version
name: project.parent.name,
version: project.parent.version
)
}
}
apply plugin: 'com.github.johnrengelman.shadow'
// We only want the shadow jar produced
jar.enabled = false
shadowJar {
dependencies {
include(dependency(':Core'))
include(dependency('org.mcstats.bukkit:metrics:R7'))
include(dependency('org.bstats:bstats-bukkit:1.4'))
}
relocate 'org.mcstats', 'com.plotsquared.stats'
// relocate('org.mcstats', 'com.plotsquared.stats')
archiveName = "${parent.name}-${project.name}-${parent.version}.jar"
destinationDir = file '../target'
}
shadowJar.doLast {
task ->
ant.checksum file: task.archivePath
ant.checksum file: task.archivePath
}
build.dependsOn(shadowJar);
build.dependsOn(shadowJar)

View File

@ -0,0 +1,871 @@
package com.github.intellectualsites.plotsquared.bukkit;
import com.github.intellectualsites.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector;
import com.github.intellectualsites.plotsquared.bukkit.database.plotme.LikePlotMeConverter;
import com.github.intellectualsites.plotsquared.bukkit.database.plotme.PlotMeConnector_017;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.github.intellectualsites.plotsquared.bukkit.listeners.*;
import com.github.intellectualsites.plotsquared.bukkit.titles.DefaultTitle_111;
import com.github.intellectualsites.plotsquared.bukkit.util.*;
import com.github.intellectualsites.plotsquared.bukkit.util.block.BukkitLocalQueue;
import com.github.intellectualsites.plotsquared.bukkit.uuid.*;
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
import com.github.intellectualsites.plotsquared.plot.IPlotMain;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.config.ConfigurationNode;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.generator.HybridGen;
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.object.chat.PlainChatManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator;
import com.github.intellectualsites.plotsquared.plot.util.*;
import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extension.platform.Capability;
import lombok.Getter;
import lombok.NonNull;
import org.bukkit.*;
import org.bukkit.Location;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass;
public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain {
@Getter private static WorldEdit worldEdit;
private static Map<String, Plugin> pluginMap;
static {
// Disable AWE as otherwise both fail to load
PluginManager manager = Bukkit.getPluginManager();
try {
Settings.load(new File("plugins/PlotSquared/config/settings.yml"));
if (Settings.Enabled_Components.PLOTME_CONVERTER) { // Only disable PlotMe if conversion is enabled
Field pluginsField = manager.getClass().getDeclaredField("plugins");
Field lookupNamesField = manager.getClass().getDeclaredField("lookupNames");
pluginsField.setAccessible(true);
lookupNamesField.setAccessible(true);
List<Plugin> plugins = (List<Plugin>) pluginsField.get(manager);
Iterator<Plugin> iter = plugins.iterator();
while (iter.hasNext()) {
if (iter.next().getName().startsWith("PlotMe")) {
iter.remove();
}
}
Map<String, Plugin> lookupNames =
(Map<String, Plugin>) lookupNamesField.get(manager);
lookupNames.remove("PlotMe");
lookupNames.remove("PlotMe-DefaultGenerator");
pluginsField.set(manager, new ArrayList<Plugin>(plugins) {
@Override public boolean add(Plugin plugin) {
if (plugin.getName().startsWith("PlotMe")) {
System.out.print("Disabling `" + plugin.getName()
+ "` for PlotMe conversion (configure in PlotSquared settings.yml)");
} else {
return super.add(plugin);
}
return false;
}
});
pluginMap = new ConcurrentHashMap<String, Plugin>(lookupNames) {
@Override public Plugin put(String key, Plugin plugin) {
if (!plugin.getName().startsWith("PlotMe")) {
return super.put(key, plugin);
}
return null;
}
};
lookupNamesField.set(manager, pluginMap);
}
} catch (Throwable ignore) {
}
// Force WorldEdit to load
try {
System.out.println("[P2] Force loading WorldEdit");
if (!manager.isPluginEnabled("WorldEdit")) {
manager.enablePlugin(WorldEditPlugin.getPlugin(WorldEditPlugin.class));
}
System.out.println("[P2] Testing platform capabilities");
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS);
} catch (final Throwable throwable) {
throw new IllegalStateException(
"Failed to force load WorldEdit." + " Road schematics will fail to generate",
throwable);
}
}
private final LegacyMappings legacyMappings = new BukkitLegacyMappings();
private final BlockRegistry<Material> blockRegistry =
new BukkitBlockRegistry(Material.values());
private int[] version;
@Getter private String pluginName;
@Getter private SingleWorldListener singleWorldListener;
private Method methodUnloadChunk0;
private boolean methodUnloadSetup = false;
private boolean metricsStarted;
@Override public int[] getServerVersion() {
if (this.version == null) {
try {
this.version = new int[3];
String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\.");
this.version[0] = Integer.parseInt(split[0]);
this.version[1] = Integer.parseInt(split[1]);
if (split.length == 3) {
this.version[2] = Integer.parseInt(split[2]);
}
} catch (NumberFormatException e) {
e.printStackTrace();
PlotSquared.debug(StringMan.getString(Bukkit.getBukkitVersion()));
PlotSquared.debug(
StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\.")));
return new int[] {1, 13, 0};
}
}
return this.version;
}
@Override public void onEnable() {
if (pluginMap != null) {
pluginMap.put("PlotMe-DefaultGenerator", this);
}
this.pluginName = getDescription().getName();
getServer().getName();
PlotPlayer.registerConverter(Player.class, BukkitUtil::getPlayer);
if (Bukkit.getVersion().contains("git-Spigot")) {
// Uses System.out.println because the logger isn't initialized yet
System.out
.println("[P2] ========================== USE PAPER ==========================");
System.out.println("[P2] Paper offers a more complete API for us to work with");
System.out.println("[P2] and we may come to rely on it in the future.");
System.out.println("[P2] It is also recommended out of a performance standpoint as");
System.out
.println("[P2] it contains many improvements missing from Spigot and Bukkit.");
System.out.println("[P2] DOWNLOAD: https://papermc.io/downloads");
System.out.println("[P2] GUIDE: https://www.spigotmc.org/threads/21726/");
System.out.println("[P2] NOTE: This is only a recommendation");
System.out.println("[P2] both Spigot and CraftBukkit are still supported.");
System.out
.println("[P2] ===============================================================");
}
new PlotSquared(this, "Bukkit");
if (Settings.Enabled_Components.METRICS) {
this.startMetrics();
} else {
PlotSquared.log(C.CONSOLE_PLEASE_ENABLE_METRICS.f(getPluginName()));
}
if (Settings.Enabled_Components.WORLDS) {
TaskManager.IMP.taskRepeat(this::unload, 20);
try {
singleWorldListener = new SingleWorldListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void unload() {
if (!this.methodUnloadSetup) {
this.methodUnloadSetup = true;
try {
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
this.methodUnloadChunk0 = classCraftWorld.getRealClass()
.getDeclaredMethod("unloadChunk0", int.class, int.class, boolean.class);
this.methodUnloadChunk0.setAccessible(true);
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
final PlotAreaManager manager = PlotSquared.get().getPlotAreaManager();
if (manager instanceof SinglePlotAreaManager) {
long start = System.currentTimeMillis();
final SinglePlotArea area = ((SinglePlotAreaManager) manager).getArea();
outer:
for (final World world : Bukkit.getWorlds()) {
final String name = world.getName();
final char char0 = name.charAt(0);
if (!Character.isDigit(char0) && char0 != '-') {
continue;
}
if (!world.getPlayers().isEmpty()) {
continue;
}
final PlotId id = PlotId.fromString(name);
if (id != null) {
final Plot plot = area.getOwnedPlot(id);
if (plot != null) {
if (PlotPlayer.wrap(plot.owner) == null) {
if (world.getKeepSpawnInMemory()) {
world.setKeepSpawnInMemory(false);
return;
}
final Chunk[] chunks = world.getLoadedChunks();
if (chunks.length == 0) {
if (!Bukkit.unloadWorld(world, true)) {
PlotSquared.debug("Failed to unload " + world.getName());
}
return;
} else {
int index = 0;
do {
final Chunk chunkI = chunks[index++];
boolean result;
if (methodUnloadChunk0 != null) {
try {
result = (boolean) methodUnloadChunk0
.invoke(world, chunkI.getX(), chunkI.getZ(), true);
} catch (Throwable e) {
methodUnloadChunk0 = null;
e.printStackTrace();
continue outer;
}
} else {
result = world
.unloadChunk(chunkI.getX(), chunkI.getZ(), true, false);
}
if (!result) {
continue outer;
}
} while (index < chunks.length
&& System.currentTimeMillis() - start < 5);
return;
}
}
}
}
}
}
}
@Override public void onDisable() {
PlotSquared.get().disable();
Bukkit.getScheduler().cancelTasks(this);
}
@Override public void log(@NonNull String message) {
try {
message = C.color(message);
if (!Settings.Chat.CONSOLE_COLOR) {
message = ChatColor.stripColor(message);
}
this.getServer().getConsoleSender().sendMessage(message);
} catch (final Throwable ignored) {
System.out.println(ConsoleColors.fromString(message));
}
}
@Override public void shutdown() {
this.getServer().getPluginManager().disablePlugin(this);
}
@Override public void disable() {
onDisable();
}
@Override public int[] getPluginVersion() {
String ver = getDescription().getVersion();
if (ver.contains("-")) {
ver = ver.split("-")[0];
}
String[] split = ver.split("\\.");
return new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1]),
Integer.parseInt(split[2])};
}
@Override public String getPluginVersionString() {
return getDescription().getVersion();
}
@Override public void registerCommands() {
final BukkitCommand bukkitCommand = new BukkitCommand();
final PluginCommand plotCommand = getCommand("plots");
plotCommand.setExecutor(bukkitCommand);
plotCommand.setAliases(Arrays.asList("p", "ps", "plotme", "plot"));
plotCommand.setTabCompleter(bukkitCommand);
}
@Override public File getDirectory() {
return getDataFolder();
}
@Override public File getWorldContainer() {
return Bukkit.getWorldContainer();
}
@Override public TaskManager getTaskManager() {
return new BukkitTaskManager(this);
}
@Override @SuppressWarnings("deprecation") public void runEntityTask() {
PlotSquared.log(C.PREFIX + "KillAllEntities started.");
TaskManager
.runTaskRepeat(() -> PlotSquared.get().foreachPlotArea(new RunnableVal<PlotArea>() {
@Override public void run(PlotArea plotArea) {
final World world = Bukkit.getWorld(plotArea.worldname);
try {
if (world == null) {
return;
}
List<Entity> entities = world.getEntities();
Iterator<Entity> iterator = entities.iterator();
while (iterator.hasNext()) {
Entity entity = iterator.next();
switch (entity.getType()) {
case EGG:
case COMPLEX_PART:
case FISHING_HOOK:
case ENDER_SIGNAL:
case LINGERING_POTION:
case AREA_EFFECT_CLOUD:
case EXPERIENCE_ORB:
case LEASH_HITCH:
case FIREWORK:
case WEATHER:
case LIGHTNING:
case WITHER_SKULL:
case UNKNOWN:
case PLAYER:
// non moving / unmovable
continue;
case THROWN_EXP_BOTTLE:
case SPLASH_POTION:
case SNOWBALL:
case SHULKER_BULLET:
case SPECTRAL_ARROW:
case TIPPED_ARROW:
case ENDER_PEARL:
case ARROW:
case LLAMA_SPIT:
// managed elsewhere | projectile
continue;
case ITEM_FRAME:
case PAINTING:
// Not vehicles
continue;
case ARMOR_STAND:
// Temporarily classify as vehicle
case MINECART:
case MINECART_CHEST:
case MINECART_COMMAND:
case MINECART_FURNACE:
case MINECART_HOPPER:
case MINECART_MOB_SPAWNER:
case ENDER_CRYSTAL:
case MINECART_TNT:
case BOAT:
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
com.github.intellectualsites.plotsquared.plot.object.Location
location = BukkitUtil.getLocation(entity.getLocation());
Plot plot = location.getPlot();
if (plot == null) {
if (location.isPlotArea()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
continue;
}
List<MetadataValue> meta = entity.getMetadata("plot");
if (meta.isEmpty()) {
continue;
}
Plot origin = (Plot) meta.get(0).value();
if (!plot.equals(origin.getBasePlot(false))) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
continue;
} else {
continue;
}
case SMALL_FIREBALL:
case FIREBALL:
case DRAGON_FIREBALL:
case DROPPED_ITEM:
if (Settings.Enabled_Components.KILL_ROAD_ITEMS) {
entity.remove();
}
// dropped item
continue;
case PRIMED_TNT:
case FALLING_BLOCK:
// managed elsewhere
continue;
case LLAMA:
case DONKEY:
case MULE:
case ZOMBIE_HORSE:
case SKELETON_HORSE:
case HUSK:
case ELDER_GUARDIAN:
case WITHER_SKELETON:
case STRAY:
case ZOMBIE_VILLAGER:
case EVOKER:
case EVOKER_FANGS:
case VEX:
case VINDICATOR:
case POLAR_BEAR:
case BAT:
case BLAZE:
case CAVE_SPIDER:
case CHICKEN:
case COW:
case CREEPER:
case ENDERMAN:
case ENDERMITE:
case ENDER_DRAGON:
case GHAST:
case GIANT:
case GUARDIAN:
case HORSE:
case IRON_GOLEM:
case MAGMA_CUBE:
case MUSHROOM_COW:
case OCELOT:
case PIG:
case PIG_ZOMBIE:
case RABBIT:
case SHEEP:
case SILVERFISH:
case SKELETON:
case SLIME:
case SNOWMAN:
case SPIDER:
case SQUID:
case VILLAGER:
case WITCH:
case WITHER:
case WOLF:
case ZOMBIE:
default: {
if (Settings.Enabled_Components.KILL_ROAD_MOBS) {
Location location = entity.getLocation();
if (BukkitUtil.getLocation(location).isPlotRoad()) {
if (entity instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) entity;
if (!livingEntity.isLeashed() || !entity
.hasMetadata("keep")) {
Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity
.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
continue;
}
}
} else {
Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity
.getMetadata("keep").isEmpty()) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
continue;
}
}
}
}
continue;
}
case SHULKER: {
if (Settings.Enabled_Components.KILL_ROAD_MOBS) {
LivingEntity livingEntity = (LivingEntity) entity;
List<MetadataValue> meta = entity.getMetadata("plot");
if (meta != null && !meta.isEmpty()) {
if (livingEntity.isLeashed())
continue;
List<MetadataValue> keep = entity.getMetadata("keep");
if (keep != null && !keep.isEmpty())
continue;
PlotId originalPlotId = (PlotId) meta.get(0).value();
if (originalPlotId != null) {
com.github.intellectualsites.plotsquared.plot.object.Location
pLoc =
BukkitUtil.getLocation(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
PlotId currentPlotId =
PlotId.of(area.getPlotAbs(pLoc));
if (!originalPlotId.equals(currentPlotId) && (
currentPlotId == null || !area
.getPlot(originalPlotId)
.equals(area.getPlot(currentPlotId)))) {
if (entity.hasMetadata("ps-tmp-teleport")) {
continue;
}
iterator.remove();
entity.remove();
}
}
}
} else {
//This is to apply the metadata to already spawned shulkers (see EntitySpawnListener.java)
com.github.intellectualsites.plotsquared.plot.object.Location
pLoc = BukkitUtil.getLocation(entity.getLocation());
PlotArea area = pLoc.getPlotArea();
if (area != null) {
PlotId currentPlotId =
PlotId.of(area.getPlotAbs(pLoc));
if (currentPlotId != null) {
entity.setMetadata("plot",
new FixedMetadataValue(
(Plugin) PlotSquared.get().IMP,
currentPlotId));
}
}
}
}
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}), 20);
}
@Override @Nullable
public final ChunkGenerator getDefaultWorldGenerator(final String world, final String id) {
if (Settings.Enabled_Components.PLOTME_CONVERTER) {
initPlotMeConverter();
Settings.Enabled_Components.PLOTME_CONVERTER = false;
}
final IndependentPlotGenerator result;
if (id != null && id.equalsIgnoreCase("single")) {
result = new SingleWorldGenerator();
} else {
result = PlotSquared.get().IMP.getDefaultGenerator();
if (!PlotSquared.get().setupPlotWorld(world, id, result)) {
return null;
}
}
return (ChunkGenerator) result.specify(world);
}
@Override public void registerPlayerEvents() {
final PlayerEvents main = new PlayerEvents();
getServer().getPluginManager().registerEvents(main, this);
try {
getServer().getClass().getMethod("spigot");
Class.forName("org.bukkit.event.entity.EntitySpawnEvent");
getServer().getPluginManager().registerEvents(new EntitySpawnListener(), this);
} catch (final NoSuchMethodException | ClassNotFoundException ignored) {
PlotSquared.debug("Not running Spigot. Skipping EntitySpawnListener event.");
}
}
@Override public void registerInventoryEvents() {
// Part of PlayerEvents - can be moved if necessary
}
@Override public void registerPlotPlusEvents() {
PlotPlusListener.startRunnable(this);
getServer().getPluginManager().registerEvents(new PlotPlusListener(), this);
}
@Override public void registerForceFieldEvents() {
}
@Override public boolean initWorldEdit() {
if (getServer().getPluginManager().getPlugin("WorldEdit") != null) {
worldEdit = WorldEdit.getInstance();
return true;
}
return false;
}
@Override public EconHandler getEconomyHandler() {
try {
BukkitEconHandler econ = new BukkitEconHandler();
if (econ.init()) {
return econ;
}
} catch (Throwable ignored) {
PlotSquared.debug("No economy detected!");
}
return null;
}
@Override public QueueProvider initBlockQueue() {
try {
new SendChunk();
MainUtil.canSendChunk = true;
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
PlotSquared.debug(
SendChunk.class + " does not support " + StringMan.getString(getServerVersion()));
MainUtil.canSendChunk = false;
}
return QueueProvider.of(BukkitLocalQueue.class, BukkitLocalQueue.class);
}
@Override public WorldUtil initWorldUtil() {
return new BukkitUtil();
}
@Override public boolean initPlotMeConverter() {
if (new LikePlotMeConverter("PlotMe").run(new ClassicPlotMeConnector())) {
return true;
} else if (new LikePlotMeConverter("PlotMe").run(new PlotMeConnector_017())) {
return true;
}
return false;
}
@Override @Nullable public GeneratorWrapper<?> getGenerator(@NonNull final String world,
@Nullable final String name) {
if (name == null) {
return null;
}
final Plugin genPlugin = Bukkit.getPluginManager().getPlugin(name);
if (genPlugin != null && genPlugin.isEnabled()) {
ChunkGenerator gen = genPlugin.getDefaultWorldGenerator(world, "");
if (gen instanceof GeneratorWrapper<?>) {
return (GeneratorWrapper<?>) gen;
}
return new BukkitPlotGenerator(world, gen);
} else {
return new BukkitPlotGenerator(PlotSquared.get().IMP.getDefaultGenerator());
}
}
@Override public HybridUtils initHybridUtils() {
return new BukkitHybridUtils();
}
@Override public SetupUtils initSetupUtils() {
return new BukkitSetupUtils();
}
@Override public UUIDHandlerImplementation initUUIDHandler() {
boolean checkVersion = false;
try {
OfflinePlayer.class.getDeclaredMethod("getUniqueId");
checkVersion = true;
} catch (Throwable ignore) {
}
final UUIDWrapper wrapper;
if (Settings.UUID.OFFLINE) {
if (Settings.UUID.FORCE_LOWERCASE) {
wrapper = new LowerOfflineUUIDWrapper();
} else {
wrapper = new OfflineUUIDWrapper();
}
Settings.UUID.OFFLINE = true;
} else if (checkVersion) {
wrapper = new DefaultUUIDWrapper();
Settings.UUID.OFFLINE = false;
} else {
if (Settings.UUID.FORCE_LOWERCASE) {
wrapper = new LowerOfflineUUIDWrapper();
} else {
wrapper = new OfflineUUIDWrapper();
}
Settings.UUID.OFFLINE = true;
}
if (!checkVersion) {
PlotSquared.log(C.PREFIX
+ " &c[WARN] Titles are disabled - please update your version of Bukkit to support this feature.");
Settings.TITLES = false;
} else {
AbstractTitle.TITLE_CLASS = new DefaultTitle_111();
if (wrapper instanceof DefaultUUIDWrapper
|| wrapper.getClass() == OfflineUUIDWrapper.class && !Bukkit.getOnlineMode()) {
Settings.UUID.NATIVE_UUID_PROVIDER = true;
}
}
if (Settings.UUID.OFFLINE) {
PlotSquared.log(C.PREFIX + " &6" + getPluginName()
+ " is using Offline Mode UUIDs either because of user preference, or because you are using an old version of "
+ "Bukkit");
} else {
PlotSquared.log(C.PREFIX + " &6" + getPluginName() + " is using online UUIDs");
}
if (Settings.UUID.USE_SQLUUIDHANDLER) {
return new SQLUUIDHandler(wrapper);
} else {
return new FileUUIDHandler(wrapper);
}
}
@Override public ChunkManager initChunkManager() {
return new BukkitChunkManager();
}
@Override public EventUtil initEventUtil() {
return new BukkitEventUtil();
}
@Override public void unregister(@NonNull final PlotPlayer player) {
BukkitUtil.removePlayer(player.getName());
}
@Override public void registerChunkProcessor() {
getServer().getPluginManager().registerEvents(new ChunkListener(), this);
}
@Override public void registerWorldEvents() {
getServer().getPluginManager().registerEvents(new WorldEvents(), this);
}
@Override public IndependentPlotGenerator getDefaultGenerator() {
return new HybridGen();
}
@Override public InventoryUtil initInventoryUtil() {
return new BukkitInventoryUtil();
}
@Override public void startMetrics() {
if (this.metricsStarted) {
return;
}
System.setProperty("bstats.relocatecheck",
"false"); // We do not want to relocate the package...
new org.bstats.bukkit.Metrics(this); // bstats
PlotSquared.log(C.PREFIX + "&6Metrics enabled.");
this.metricsStarted = true;
}
@Override public void setGenerator(@NonNull final String worldName) {
World world = BukkitUtil.getWorld(worldName);
if (world == null) {
// create world
ConfigurationSection worldConfig =
PlotSquared.get().worlds.getConfigurationSection("worlds." + worldName);
String manager = worldConfig.getString("generator.plugin", getPluginName());
SetupObject setup = new SetupObject();
setup.plotManager = manager;
setup.setupGenerator = worldConfig.getString("generator.init", manager);
setup.type = worldConfig.getInt("generator.type");
setup.terrain = worldConfig.getInt("generator.terrain");
setup.step = new ConfigurationNode[0];
setup.world = worldName;
SetupUtils.manager.setupWorld(setup);
world = Bukkit.getWorld(worldName);
} else {
try {
if (!PlotSquared.get().hasPlotArea(worldName)) {
SetGenCB.setGenerator(BukkitUtil.getWorld(worldName));
}
} catch (Exception e) {
PlotSquared.log("Failed to reload world: " + world + " | " + e.getMessage());
Bukkit.getServer().unloadWorld(world, false);
return;
}
}
ChunkGenerator gen = world.getGenerator();
if (gen instanceof BukkitPlotGenerator) {
PlotSquared.get().loadWorld(worldName, (BukkitPlotGenerator) gen);
} else if (gen != null) {
PlotSquared.get().loadWorld(worldName, new BukkitPlotGenerator(worldName, gen));
} else if (PlotSquared.get().worlds.contains("worlds." + worldName)) {
PlotSquared.get().loadWorld(worldName, null);
}
}
@Override public SchematicHandler initSchematicHandler() {
return new BukkitSchematicHandler();
}
@Override public AbstractTitle initTitleManager() {
// Already initialized in UUID handler
return AbstractTitle.TITLE_CLASS;
}
@Override @Nullable public PlotPlayer wrapPlayer(final Object player) {
if (player instanceof Player) {
return BukkitUtil.getPlayer((Player) player);
}
if (player instanceof OfflinePlayer) {
return BukkitUtil.getPlayer((OfflinePlayer) player);
}
if (player instanceof String) {
return UUIDHandler.getPlayer((String) player);
}
if (player instanceof UUID) {
return UUIDHandler.getPlayer((UUID) player);
}
return null;
}
@Override public String getNMSPackage() {
final String name = Bukkit.getServer().getClass().getPackage().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
@Override public ChatManager<?> initChatManager() {
if (Settings.Chat.INTERACTIVE) {
return new BukkitChatManager();
} else {
return new PlainChatManager();
}
}
@Override public GeneratorWrapper<?> wrapPlotGenerator(@Nullable final String world,
@NonNull final IndependentPlotGenerator generator) {
return new BukkitPlotGenerator(generator);
}
@Override public List<String> getPluginIds() {
final List<String> names = new ArrayList<>();
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
names.add(plugin.getName() + ';' + plugin.getDescription().getVersion() + ':' + plugin
.isEnabled());
}
return names;
}
@Override public BlockRegistry<Material> getBlockRegistry() {
return this.blockRegistry;
}
@Override public LegacyMappings getLegacyMappings() {
return this.legacyMappings;
}
}

View File

@ -0,0 +1,107 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import org.apache.commons.lang.Validate;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
/**
* Represents a wrapper around an array class of an arbitrary reference type,
* which properly implements "value" hash code and equality functions.
* <p>
* This class is intended for use as a key to a map.
* </p>
*
* @param <E> The type of elements in the array.
* @author Glen Husman
* @see Arrays
*/
public final class ArrayWrapper<E> {
private E[] _array;
/**
* Creates an array wrapper with some elements.
*
* @param elements The elements of the array.
*/
public ArrayWrapper(E... elements) {
setArray(elements);
}
/**
* Converts an iterable element collection to an array of elements.
* The iteration order of the specified object will be used as the array element order.
*
* @param list The iterable of objects which will be converted to an array.
* @param c The type of the elements of the array.
* @return An array of elements in the specified iterable.
*/
@SuppressWarnings("unchecked") public static <T> T[] toArray(Iterable<? extends T> list,
Class<T> c) {
int size = -1;
if (list instanceof Collection<?>) {
@SuppressWarnings("rawtypes") Collection coll = (Collection) list;
size = coll.size();
}
if (size < 0) {
size = 0;
// Ugly hack: Count it ourselves
for (@SuppressWarnings("unused") T element : list) {
size++;
}
}
T[] result = (T[]) Array.newInstance(c, size);
int i = 0;
for (T element : list) { // Assumes iteration order is consistent
result[i++] = element; // Assign array element at index THEN increment counter
}
return result;
}
/**
* Retrieves a reference to the wrapped array instance.
*
* @return The array wrapped by this instance.
*/
public E[] getArray() {
return _array;
}
/**
* Set this wrapper to wrap a new array instance.
*
* @param array The new wrapped array.
*/
public void setArray(E[] array) {
Validate.notNull(array, "The array must not be null.");
_array = array;
}
/**
* Determines if this object has a value equivalent to another object.
*
* @see Arrays#equals(Object[], Object[])
*/
@SuppressWarnings("rawtypes") @Override public boolean equals(Object other) {
if (!(other instanceof ArrayWrapper)) {
return false;
}
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
}
/**
* Gets the hash code represented by this objects value.
*
* @return This object's hash code.
* @see Arrays#hashCode(Object[])
*/
@Override public int hashCode() {
return Arrays.hashCode(_array);
}
}

View File

@ -0,0 +1,923 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import org.bukkit.*;
import org.bukkit.Statistic.Type;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.*;
import java.util.*;
import java.util.logging.Level;
/**
* Represents a formattable message. Such messages can use elements such as colors, formatting codes, hover and click data, and other features provided by the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Tellraw#Raw_JSON_Text">JSON message formatter</a>.
* This class allows plugins to emulate the functionality of the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Commands#tellraw">tellraw command</a>.
* <p>
* This class follows the builder pattern, allowing for method chaining.
* It is set up such that invocations of property-setting methods will affect the current editing component,
* and a call to {@link #then()} or {@link #then(String)} will append a new editing component to the end of the message,
* optionally initializing it with text. Further property-setting method calls will affect that editing component.
* </p>
*/
public class FancyMessage
implements JsonRepresentedObject, Cloneable, Iterable<MessagePart>, ConfigurationSerializable {
private static Constructor<?> nmsPacketPlayOutChatConstructor;
// The ChatSerializer's instance of Gson
private static Object nmsChatSerializerGsonInstance;
private static Method fromJsonMethod;
private static JsonParser _stringParser = new JsonParser();
static {
ConfigurationSerialization.registerClass(FancyMessage.class);
}
private List<MessagePart> messageParts;
private String jsonString;
private boolean dirty;
/**
* Creates a JSON message with text.
*
* @param firstPartText The existing text in the message.
*/
public FancyMessage(final String firstPartText) {
this(TextualComponent.rawText(firstPartText));
}
private FancyMessage(final TextualComponent firstPartText) {
messageParts = new ArrayList<>();
messageParts.add(new MessagePart(firstPartText));
jsonString = null;
dirty = false;
if (nmsPacketPlayOutChatConstructor == null) {
try {
nmsPacketPlayOutChatConstructor = Reflection.getNMSClass("PacketPlayOutChat")
.getDeclaredConstructor(Reflection.getNMSClass("IChatBaseComponent"));
nmsPacketPlayOutChatConstructor.setAccessible(true);
} catch (NoSuchMethodException e) {
Bukkit.getLogger()
.log(Level.SEVERE, "Could not find Minecraft method or constructor.", e);
} catch (SecurityException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access constructor.", e);
}
}
}
/**
* Creates a JSON message without text.
*/
public FancyMessage() {
this((TextualComponent) null);
}
/**
* Deserializes a JSON-represented message from a mapping of key-value pairs.
* This is called by the Bukkit serialization API.
* It is not intended for direct public API consumption.
*
* @param serialized The key-value mapping which represents a fancy message.
*/
@SuppressWarnings("unchecked") public static FancyMessage deserialize(
Map<String, Object> serialized) {
FancyMessage msg = new FancyMessage();
msg.messageParts = (List<MessagePart>) serialized.get("messageParts");
msg.jsonString = serialized.containsKey("JSON") ? serialized.get("JSON").toString() : null;
msg.dirty = !serialized.containsKey("JSON");
return msg;
}
/**
* Deserializes a fancy message from its JSON representation. This JSON representation is of the format of
* that returned by {@link #toJSONString()}, and is compatible with vanilla inputs.
*
* @param json The JSON string which represents a fancy message.
* @return A {@code FancyMessage} representing the parameterized JSON message.
*/
public static FancyMessage deserialize(String json) {
JsonObject serialized = _stringParser.parse(json).getAsJsonObject();
JsonArray extra = serialized.getAsJsonArray("extra"); // Get the extra component
FancyMessage returnVal = new FancyMessage();
returnVal.messageParts.clear();
for (JsonElement mPrt : extra) {
MessagePart component = new MessagePart();
JsonObject messagePart = mPrt.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
// Deserialize text
if (TextualComponent.isTextKey(entry.getKey())) {
// The map mimics the YAML serialization, which has a "key" field and one or more "value" fields
Map<String, Object> serializedMapForm =
new HashMap<>(); // Must be object due to Bukkit serializer API compliance
serializedMapForm.put("key", entry.getKey());
if (entry.getValue().isJsonPrimitive()) {
// Assume string
serializedMapForm.put("value", entry.getValue().getAsString());
} else {
// Composite object, but we assume each element is a string
for (Map.Entry<String, JsonElement> compositeNestedElement : entry
.getValue().getAsJsonObject().entrySet()) {
serializedMapForm.put("value." + compositeNestedElement.getKey(),
compositeNestedElement.getValue().getAsString());
}
}
component.text = TextualComponent.deserialize(serializedMapForm);
} else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
if (entry.getValue().getAsBoolean()) {
component.styles
.add(MessagePart.stylesToNames.inverse().get(entry.getKey()));
}
} else if (entry.getKey().equals("color")) {
component.color =
ChatColor.valueOf(entry.getValue().getAsString().toUpperCase());
} else if (entry.getKey().equals("clickEvent")) {
JsonObject object = entry.getValue().getAsJsonObject();
component.clickActionName = object.get("action").getAsString();
component.clickActionData = object.get("value").getAsString();
} else if (entry.getKey().equals("hoverEvent")) {
JsonObject object = entry.getValue().getAsJsonObject();
component.hoverActionName = object.get("action").getAsString();
if (object.get("value").isJsonPrimitive()) {
// Assume string
component.hoverActionData =
new JsonString(object.get("value").getAsString());
} else {
// Assume composite type
// The only composite type we currently store is another FancyMessage
// Therefore, recursion time!
component.hoverActionData = deserialize(object.get("value")
.toString() /* This should properly serialize the JSON object as a JSON string */);
}
} else if (entry.getKey().equals("insertion")) {
component.insertionData = entry.getValue().getAsString();
} else if (entry.getKey().equals("with")) {
for (JsonElement object : entry.getValue().getAsJsonArray()) {
if (object.isJsonPrimitive()) {
component.translationReplacements
.add(new JsonString(object.getAsString()));
} else {
// Only composite type stored in this array is - again - FancyMessages
// Recurse within this function to parse this as a translation replacement
component.translationReplacements.add(deserialize(object.toString()));
}
}
}
}
returnVal.messageParts.add(component);
}
return returnVal;
}
@Override public FancyMessage clone() throws CloneNotSupportedException {
FancyMessage instance = (FancyMessage) super.clone();
instance.messageParts = new ArrayList<>(messageParts.size());
for (int i = 0; i < messageParts.size(); i++) {
instance.messageParts.add(i, messageParts.get(i).clone());
}
instance.dirty = false;
instance.jsonString = null;
return instance;
}
/**
* Sets the text of the current editing component to a value.
*
* @param text The new text of the current editing component.
* @return This builder instance.
*/
public FancyMessage text(String text) {
MessagePart latest = latest();
latest.text = TextualComponent.rawText(text);
dirty = true;
return this;
}
/**
* Sets the text of the current editing component to a value.
*
* @param text The new text of the current editing component.
* @return This builder instance.
*/
public FancyMessage text(TextualComponent text) {
MessagePart latest = latest();
latest.text = text;
dirty = true;
return this;
}
/**
* Sets the color of the current editing component to a value.
*
* @param color The new color of the current editing component.
* @return This builder instance.
* @throws IllegalArgumentException If the specified {@code ChatColor} enumeration value is not a color (but a format value).
*/
public FancyMessage color(final ChatColor color) {
if (!color.isColor()) {
throw new IllegalArgumentException(color.name() + " is not a color");
}
latest().color = color;
dirty = true;
return this;
}
/**
* Sets the stylization of the current editing component.
*
* @param styles The array of styles to apply to the editing component.
* @return This builder instance.
* @throws IllegalArgumentException If any of the enumeration values in the array do not represent formatters.
*/
public FancyMessage style(ChatColor... styles) {
for (final ChatColor style : styles) {
if (!style.isFormat()) {
throw new IllegalArgumentException(style.name() + " is not a style");
}
}
latest().styles.addAll(Arrays.asList(styles));
dirty = true;
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to open a file on the client side filesystem when the currently edited part of the {@code FancyMessage} is clicked.
*
* @param path The path of the file on the client filesystem.
* @return This builder instance.
*/
public FancyMessage file(final String path) {
onClick("open_file", path);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to open a webpage in the client's web browser when the currently edited part of the {@code FancyMessage} is clicked.
*
* @param url The URL of the page to open when the link is clicked.
* @return This builder instance.
*/
public FancyMessage link(final String url) {
onClick("open_url", url);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to replace the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is clicked.
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
*
* @param command The text to display in the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage suggest(final String command) {
onClick("suggest_command", command);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to append the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is SHIFT-CLICKED.
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
*
* @param command The text to append to the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage insert(final String command) {
latest().insertionData = command;
dirty = true;
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to send the specified string to the server as a chat message when the currently edited part of the {@code FancyMessage} is clicked.
* The client <b>will</b> immediately send the command to the server to be executed when the editing component is clicked.
*
* @param command The text to display in the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage command(final String command) {
onClick("run_command", command);
return this;
}
/**
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param name The name of the achievement to display, excluding the "achievement." prefix.
* @return This builder instance.
*/
public FancyMessage achievementTooltip(final String name) {
onHover("show_achievement", new JsonString("achievement." + name));
return this;
}
/**
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The achievement to display.
* @return This builder instance.
*/
public FancyMessage achievementTooltip(final Achievement which) {
try {
Object achievement = Reflection
.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement",
Achievement.class).invoke(null, which);
return achievementTooltip(
(String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name")
.get(achievement));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a parameterless statistic when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied.
*/
public FancyMessage statisticTooltip(final Statistic which) {
Type type = which.getType();
if (type != Type.UNTYPED) {
throw new IllegalArgumentException(
"That statistic requires an additional " + type + " parameter!");
}
try {
Object statistic = Reflection
.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic",
Statistic.class).invoke(null, which);
return achievementTooltip(
(String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name")
.get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a statistic parameter with a material when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @param item The sole material parameter to the statistic.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
*/
public FancyMessage statisticTooltip(final Statistic which, Material item) {
Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if ((type == Type.BLOCK && item.isBlock()) || type == Type.ENTITY) {
throw new IllegalArgumentException(
"Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = Reflection
.getMethod(Reflection.getOBCClass("CraftStatistic"), "getMaterialStatistic",
Statistic.class, Material.class).invoke(null, which, item);
return achievementTooltip(
(String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name")
.get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a statistic parameter with an entity type when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @param entity The sole entity type parameter to the statistic.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
*/
public FancyMessage statisticTooltip(final Statistic which, EntityType entity) {
Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if (type != Type.ENTITY) {
throw new IllegalArgumentException(
"Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = Reflection
.getMethod(Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic",
Statistic.class, EntityType.class).invoke(null, which, entity);
return achievementTooltip(
(String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name")
.get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A error has occurred during invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param itemJSON A string representing the JSON-serialized NBT data tag of an {@link ItemStack}.
* @return This builder instance.
*/
public FancyMessage itemTooltip(final String itemJSON) {
onHover("show_item", new JsonString(
itemJSON)); // Seems a bit hacky, considering we have a JSON object as a parameter
return this;
}
/**
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param itemStack The stack for which to display information.
* @return This builder instance.
*/
public FancyMessage itemTooltip(final ItemStack itemStack) {
try {
Object nmsItem = Reflection
.getMethod(Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy",
ItemStack.class).invoke(null, itemStack);
return itemTooltip(Reflection.getMethod(Reflection.getNMSClass("ItemStack"), "save",
Reflection.getNMSClass("NBTTagCompound"))
.invoke(nmsItem, Reflection.getNMSClass("NBTTagCompound").newInstance())
.toString());
} catch (Exception e) {
e.printStackTrace();
return this;
}
}
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param text The text, which supports newlines, which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage tooltip(final String text) {
onHover("show_text", new JsonString(text));
return this;
}
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
* @return This builder instance.
*/
public FancyMessage tooltip(final Iterable<String> lines) {
tooltip(ArrayWrapper.toArray(lines, String.class));
return this;
}
/*
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/ /* ------------
public FancyMessage translationReplacements(final Iterable<? extends CharSequence> replacements){
for(CharSequence str : replacements){
latest().translationReplacements.add(new JsonString(str));
}
return this;
}
*/
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage tooltip(final String... lines) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
builder.append(lines[i]);
if (i != lines.length - 1) {
builder.append('\n');
}
}
tooltip(builder.toString());
return this;
}
/**
* Set the behavior of the current editing component to display formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param text The formatted text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(FancyMessage text) {
for (MessagePart component : text.messageParts) {
if (component.clickActionData != null && component.clickActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have click data.");
} else if (component.hoverActionData != null && component.hoverActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
}
}
onHover("show_text", text);
return this;
}
/**
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of formatted text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(FancyMessage... lines) {
if (lines.length < 1) {
onHover(null, null); // Clear tooltip
return this;
}
FancyMessage result = new FancyMessage();
result.messageParts
.clear(); // Remove the one existing text component that exists by default, which destabilizes the object
for (int i = 0; i < lines.length; i++) {
try {
for (MessagePart component : lines[i]) {
if (component.clickActionData != null && component.clickActionName != null) {
throw new IllegalArgumentException(
"The tooltip text cannot have click data.");
} else if (component.hoverActionData != null
&& component.hoverActionName != null) {
throw new IllegalArgumentException(
"The tooltip text cannot have a tooltip.");
}
if (component.hasText()) {
result.messageParts.add(component.clone());
}
}
if (i != lines.length - 1) {
result.messageParts.add(new MessagePart(TextualComponent.rawText("\n")));
}
} catch (CloneNotSupportedException e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to clone object", e);
return this;
}
}
return formattedTooltip(
result.messageParts.isEmpty() ? null : result); // Throws NPE if size is 0, intended
}
/**
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(final Iterable<FancyMessage> lines) {
return formattedTooltip(ArrayWrapper.toArray(lines, FancyMessage.class));
}
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final String... replacements) {
for (String str : replacements) {
latest().translationReplacements.add(new JsonString(str));
}
dirty = true;
return this;
}
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final FancyMessage... replacements) {
for (FancyMessage str : replacements) {
latest().translationReplacements.add(str);
}
dirty = true;
return this;
}
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final Iterable<FancyMessage> replacements) {
return translationReplacements(ArrayWrapper.toArray(replacements, FancyMessage.class));
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @param text The text which will populate the new message component.
* @return This builder instance.
*/
public FancyMessage then(final String text) {
return then(TextualComponent.rawText(text));
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @param text The text which will populate the new message component.
* @return This builder instance.
*/
public FancyMessage then(final TextualComponent text) {
if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text");
}
messageParts.add(new MessagePart(text));
dirty = true;
return this;
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @return This builder instance.
*/
public FancyMessage then() {
if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text");
}
messageParts.add(new MessagePart());
dirty = true;
return this;
}
@Override public void writeJson(JsonWriter writer) throws IOException {
if (messageParts.size() == 1) {
latest().writeJson(writer);
} else {
writer.beginObject().name("text").value("").name("extra").beginArray();
for (final MessagePart part : this) {
part.writeJson(writer);
}
writer.endArray().endObject();
}
}
/**
* Serialize this fancy message, converting it into syntactically-valid JSON using a {@link JsonWriter}.
* This JSON should be compatible with vanilla formatter commands such as {@code /tellraw}.
*
* @return The JSON string representing this object.
*/
public String toJSONString() {
if (!dirty && jsonString != null) {
return jsonString;
}
StringWriter string = new StringWriter();
JsonWriter json = new JsonWriter(string);
try {
writeJson(json);
json.close();
} catch (IOException e) {
throw new RuntimeException("invalid message");
}
jsonString = string.toString();
dirty = false;
return jsonString;
}
/**
* Sends this message to a player. The player will receive the fully-fledged formatted display of this message.
*
* @param player The player who will receive the message.
*/
public void send(Player player) {
send(player, toJSONString());
}
private void send(CommandSender sender, String jsonString) {
if (!(sender instanceof Player)) {
sender.sendMessage(toOldMessageFormat());
return;
}
Player player = (Player) sender;
try {
Object handle = Reflection.getHandle(player);
Object connection =
Reflection.getField(handle.getClass(), "playerConnection").get(handle);
Reflection
.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet"))
.invoke(connection, createChatPacket(jsonString));
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
} catch (InstantiationException e) {
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
} catch (InvocationTargetException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A error has occurred during invoking of method.", e);
} catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
} catch (ClassNotFoundException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find class.", e);
}
}
private Object createChatPacket(String json)
throws IllegalArgumentException, IllegalAccessException, InstantiationException,
InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
if (nmsChatSerializerGsonInstance == null) {
// Find the field and its value, completely bypassing obfuscation
Class<?> chatSerializerClazz;
// Get the three parts of the version string (major version is currently unused)
// vX_Y_RZ
// X = major
// Y = minor
// Z = revision
final String version = Reflection.getVersion();
String[] split =
version.substring(1, version.length() - 1).split("_"); // Remove trailing dot
//int majorVersion = Integer.parseInt(split[0]);
int minorVersion = Integer.parseInt(split[1]);
int revisionVersion = Integer.parseInt(split[2].substring(1)); // Substring to ignore R
if (minorVersion < 8 || (minorVersion == 8 && revisionVersion == 1)) {
chatSerializerClazz = Reflection.getNMSClass("ChatSerializer");
} else {
chatSerializerClazz = Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
}
if (chatSerializerClazz == null) {
throw new ClassNotFoundException("Can't find the ChatSerializer class");
}
for (Field declaredField : chatSerializerClazz.getDeclaredFields()) {
if (Modifier.isFinal(declaredField.getModifiers()) && Modifier
.isStatic(declaredField.getModifiers()) && declaredField.getType().getName()
.endsWith("Gson")) {
// We've found our field
declaredField.setAccessible(true);
nmsChatSerializerGsonInstance = declaredField.get(null);
fromJsonMethod = nmsChatSerializerGsonInstance.getClass()
.getMethod("fromJson", String.class, Class.class);
break;
}
}
}
// Since the method is so simple, and all the obfuscated methods have the same name, it's easier to reimplement 'IChatBaseComponent a(String)' than to reflectively call it
// Of course, the implementation may change, but fuzzy matches might break with signature changes
Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json,
Reflection.getNMSClass("IChatBaseComponent"));
return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
}
/**
* Sends this message to a command sender.
* If the sender is a player, they will receive the fully-fledged formatted display of this message.
* Otherwise, they will receive a version of this message with less formatting.
*
* @param sender The command sender who will receive the message.
* @see #toOldMessageFormat()
*/
public void send(CommandSender sender) {
send(sender, toJSONString());
}
/**
* Sends this message to multiple command senders.
*
* @param senders The command senders who will receive the message.
* @see #send(CommandSender)
*/
public void send(final Iterable<? extends CommandSender> senders) {
String string = toJSONString();
for (final CommandSender sender : senders) {
send(sender, string);
}
}
/**
* Convert this message to a human-readable string with limited formatting.
* This method is used to send this message to clients without JSON formatting support.
* <p>
* Serialization of this message by using this message will include (in this order for each message part):
* <ol>
* <li>The color of each message part.</li>
* <li>The applicable stylizations for each message part.</li>
* <li>The core text of the message part.</li>
* </ol>
* The primary omissions are tooltips and clickable actions. Consequently, this method should be used only as a last resort.
* </p>
* <p>
* Color and formatting can be removed from the returned string by using {@link ChatColor#stripColor(String)}.</p>
*
* @return A human-readable string representing limited formatting in addition to the core text of this message.
*/
public String toOldMessageFormat() {
StringBuilder result = new StringBuilder();
for (MessagePart part : this) {
result.append(part.color == null ? "" : part.color);
for (ChatColor formatSpecifier : part.styles) {
result.append(formatSpecifier);
}
result.append(part.text);
}
return result.toString();
}
private MessagePart latest() {
return messageParts.get(messageParts.size() - 1);
}
private void onClick(final String name, final String data) {
final MessagePart latest = latest();
latest.clickActionName = name;
latest.clickActionData = data;
dirty = true;
}
private void onHover(final String name, final JsonRepresentedObject data) {
final MessagePart latest = latest();
latest.hoverActionName = name;
latest.hoverActionData = data;
dirty = true;
}
// Doc copied from interface
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<>();
map.put("messageParts", messageParts);
// map.put("JSON", toJSONString());
return map;
}
/**
* <b>Internally called method. Not for API consumption.</b>
*/
public Iterator<MessagePart> iterator() {
return messageParts.iterator();
}
}

View File

@ -0,0 +1,20 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
/**
* Represents an object that can be serialized to a JSON writer instance.
*/
interface JsonRepresentedObject {
/**
* Writes the JSON representation of this object to the specified writer.
*
* @param writer The JSON writer which will receive the object.
* @throws IOException If an error occurs writing to the stream.
*/
public void writeJson(JsonWriter writer) throws IOException;
}

View File

@ -0,0 +1,45 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import com.google.gson.stream.JsonWriter;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a JSON string value.
* Writes by this object will not write name values nor begin/end objects in the JSON stream.
* All writes merely write the represented string value.
*/
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
private String _value;
public JsonString(CharSequence value) {
_value = value == null ? null : value.toString();
}
public static JsonString deserialize(Map<String, Object> map) {
return new JsonString(map.get("stringValue").toString());
}
@Override public void writeJson(JsonWriter writer) throws IOException {
writer.value(getValue());
}
public String getValue() {
return _value;
}
public Map<String, Object> serialize() {
HashMap<String, Object> theSingleValue = new HashMap<String, Object>();
theSingleValue.put("stringValue", _value);
return theSingleValue;
}
@Override public String toString() {
return _value;
}
}

View File

@ -0,0 +1,155 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.gson.stream.JsonWriter;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
/**
* Internal class: Represents a component of a JSON-serializable {@link FancyMessage}.
*/
final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
static final BiMap<ChatColor, String> stylesToNames;
static {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) {
continue;
}
String styleName;
switch (style) {
case MAGIC:
styleName = "obfuscated";
break;
case UNDERLINE:
styleName = "underlined";
break;
default:
styleName = style.name().toLowerCase();
break;
}
builder.put(style, styleName);
}
stylesToNames = builder.build();
}
static {
ConfigurationSerialization.registerClass(MessagePart.class);
}
ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<>();
String clickActionName = null;
String clickActionData = null;
String hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<>();
MessagePart(final TextualComponent text) {
this.text = text;
}
MessagePart() {
this.text = null;
}
@SuppressWarnings("unchecked")
public static MessagePart deserialize(Map<String, Object> serialized) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
part.color = ChatColor.getByChar(serialized.get("color").toString());
part.hoverActionName = (String) serialized.get("hoverActionName");
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
part.clickActionName = (String) serialized.get("clickActionName");
part.clickActionData = (String) serialized.get("clickActionData");
part.insertionData = (String) serialized.get("insertion");
part.translationReplacements =
(ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
return part;
}
boolean hasText() {
return text != null;
}
@Override @SuppressWarnings("unchecked") public MessagePart clone()
throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
}
obj.translationReplacements =
(ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj;
}
public void writeJson(JsonWriter json) {
try {
json.beginObject();
text.writeJson(json);
json.name("color").value(color.name().toLowerCase());
for (final ChatColor style : styles) {
json.name(stylesToNames.get(style)).value(true);
}
if (clickActionName != null && clickActionData != null) {
json.name("clickEvent").beginObject().name("action").value(clickActionName)
.name("value").value(clickActionData).endObject();
}
if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent").beginObject().name("action").value(hoverActionName)
.name("value");
hoverActionData.writeJson(json);
json.endObject();
}
if (insertionData != null) {
json.name("insertion").value(insertionData);
}
if (translationReplacements.size() > 0 && text != null && TextualComponent
.isTranslatableText(text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger()
.log(Level.WARNING, "A problem occured during writing of JSON string", e);
}
}
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<>();
map.put("text", text);
map.put("styles", styles);
map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData);
map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements);
return map;
}
}

View File

@ -0,0 +1,210 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import org.bukkit.Bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* A class containing static utility methods and caches which are intended as reflective conveniences.
* Unless otherwise noted, upon failure methods will return {@code null}.
*/
public final class Reflection {
/**
* Stores loaded classes from the {@code net.minecraft.server} package.
*/
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<>();
/**
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
*/
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<>();
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<>();
/**
* Contains loaded methods in a cache.
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
*/
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>>
_loadedMethods = new HashMap<>();
private static String _versionString;
private Reflection() {
}
/**
* Gets the version string from the package name of the CraftBukkit server implementation.
* This is needed to bypass the JAR package name changing on each update.
*
* @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
*/
public synchronized static String getVersion() {
if (_versionString == null) {
if (Bukkit.getServer() == null) {
// The server hasn't started, static initializer call?
return null;
}
String name = Bukkit.getServer().getClass().getPackage().getName();
_versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
}
return _versionString;
}
/**
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
*
* @param className The name of the class, excluding the package, within NMS.
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
*/
public synchronized static Class<?> getNMSClass(String className) {
if (_loadedNMSClasses.containsKey(className)) {
return _loadedNMSClasses.get(className);
}
String fullName = "net.minecraft.server." + getVersion() + className;
Class<?> clazz;
try {
clazz = Class.forName(fullName);
} catch (ClassNotFoundException e) {
_loadedNMSClasses.put(className, null);
throw new RuntimeException(e);
}
_loadedNMSClasses.put(className, clazz);
return clazz;
}
/**
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
*
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory.CraftItemStack}.
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
*/
public synchronized static Class<?> getOBCClass(String className) {
if (_loadedOBCClasses.containsKey(className)) {
return _loadedOBCClasses.get(className);
}
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
Class<?> clazz;
try {
clazz = Class.forName(fullName);
} catch (ClassNotFoundException e) {
_loadedOBCClasses.put(className, null);
throw new RuntimeException(e);
}
_loadedOBCClasses.put(className, clazz);
return clazz;
}
/**
* Attempts to get the NMS handle of a CraftBukkit object.
* <p>
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the runtime type of the specified object.
* </p>
*
* @param obj The object for which to retrieve an NMS handle.
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
*/
public synchronized static Object getHandle(Object obj)
throws InvocationTargetException, IllegalAccessException, IllegalArgumentException {
return getMethod(obj.getClass(), "getHandle").invoke(obj);
}
/**
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
* returned will be an instance or static field.
* <p>
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
* no field will be reflectively looked up twice.
* </p>
* <p>
* If a field is deemed suitable for return, {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
* </p>
*
* @param clazz The class which contains the field to retrieve.
* @param name The declared name of the field in the class.
* @return A field object with the specified name declared by the specified class.
* @see Class#getDeclaredField(String)
*/
public synchronized static Field getField(Class<?> clazz, String name) {
Map<String, Field> loaded;
if (!_loadedFields.containsKey(clazz)) {
loaded = new HashMap<>();
_loadedFields.put(clazz, loaded);
} else {
loaded = _loadedFields.get(clazz);
}
if (loaded.containsKey(name)) {
// If the field is loaded (or cached as not existing), return the relevant value, which might be null
return loaded.get(name);
}
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
loaded.put(name, field);
return field;
} catch (NoSuchFieldException | SecurityException e) {
// Error loading
e.printStackTrace();
// Cache field as not existing
loaded.put(name, null);
return null;
}
}
/**
* Retrieves a {@link Method} instance declared by the specified class with the specified name and argument types.
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
* returned will be an instance or static field.
* <p>
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that
* no method will be reflectively looked up twice.
* <p>
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
* <p>
* This method does <em>not</em> search superclasses of the specified type for methods with the specified signature.
* Callers wishing this behavior should use {@link Class#getDeclaredMethod(String, Class...)}.
*
* @param clazz The class which contains the method to retrieve.
* @param name The declared name of the method in the class.
* @param args The formal argument types of the method.
* @return A method object with the specified name declared by the specified class.
*/
public synchronized static Method getMethod(Class<?> clazz, String name, Class<?>... args) {
if (!_loadedMethods.containsKey(clazz)) {
_loadedMethods.put(clazz, new HashMap<String, Map<ArrayWrapper<Class<?>>, Method>>());
}
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames =
_loadedMethods.get(clazz);
if (!loadedMethodNames.containsKey(name)) {
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>());
}
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<>(args);
if (loadedSignatures.containsKey(wrappedArg)) {
return loadedSignatures.get(wrappedArg);
}
for (Method m : clazz.getMethods()) {
if (m.getName().equals(name) && Arrays.equals(args, m.getParameterTypes())) {
m.setAccessible(true);
loadedSignatures.put(wrappedArg, m);
return m;
}
}
loadedSignatures.put(wrappedArg, null);
return null;
}
}

View File

@ -0,0 +1,313 @@
package com.github.intellectualsites.plotsquared.bukkit.chat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.gson.stream.JsonWriter;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a textual component of a message part.
* This can be used to not only represent string literals in a JSON message,
* but also to represent localized strings and other text values.
* <p>Different instances of this class can be created with static constructor methods.</p>
*/
public abstract class TextualComponent implements Cloneable {
static {
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
}
static TextualComponent deserialize(Map<String, Object> map) {
if (map.containsKey("key") && map.size() == 2 && map.containsKey("value")) {
// Arbitrary text component
return ArbitraryTextTypeComponent.deserialize(map);
} else if (map.size() >= 2 && map.containsKey("key") && !map
.containsKey("value") /* It contains keys that START WITH value */) {
// Complex JSON object
return ComplexTextTypeComponent.deserialize(map);
}
return null;
}
static boolean isTextKey(String key) {
return key.equals("translate") || key.equals("text") || key.equals("score") || key
.equals("selector");
}
static boolean isTranslatableText(TextualComponent component) {
return component instanceof ComplexTextTypeComponent && component.getKey()
.equals("translate");
}
/**
* Create a textual component representing a string literal.
*
* <p>This is the default type of textual component when a single string
* literal is given to a method.
*
* @param textValue The text which will be represented.
* @return The text component representing the specified literal text.
*/
public static TextualComponent rawText(String textValue) {
return new ArbitraryTextTypeComponent("text", textValue);
}
/**
* Create a textual component representing a localized string.
* The client will see this text component as their localized version of the specified string <em>key</em>, which can be overridden by a
* resource pack.
* <p>
* If the specified translation key is not present on the client resource pack, the translation key will be displayed as a string literal to
* the client.
* </p>
*
* @param translateKey The string key which maps to localized text.
* @return The text component representing the specified localized text.
*/
public static TextualComponent localizedText(String translateKey) {
return new ArbitraryTextTypeComponent("translate", translateKey);
}
private static void throwUnsupportedSnapshot() {
throw new UnsupportedOperationException(
"This feature is only supported in snapshot releases.");
}
/**
* Create a textual component representing a scoreboard value.
* The client will see their own score for the specified objective as the text represented by this component.
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score (for the viewing player), or {@code null} if an error occurs during
* JSON serialization.
*/
public static TextualComponent objectiveScore(String scoreboardObjective) {
return objectiveScore("*", scoreboardObjective);
}
/**
* Create a textual component representing a scoreboard value.
* The client will see the score of the specified player for the specified objective as the text represented by this component.
*
* <p><b>This method is currently guaranteed to throw an {@code UnsupportedOperationException}
* as it is only supported on snapshot clients.</b>
*
* @param playerName The name of the player whos score will be shown. If
* this string represents the single-character sequence
* "*", the viewing player's score will be displayed.
* Standard minecraft selectors (@a, @p, etc)
* are <em>not</em> supported.
* @param scoreboardObjective The name of the objective for
* which to display the score.
* @return The text component representing the specified scoreboard score
* for the specified player, or {@code null} if an error occurs during JSON serialization.
*/
public static TextualComponent objectiveScore(String playerName, String scoreboardObjective) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE
// OVERLOADS documentation accordingly
return new ComplexTextTypeComponent("score",
ImmutableMap.<String, String>builder().put("name", playerName)
.put("objective", scoreboardObjective).build());
}
/**
* Create a textual component representing a player name, retrievable by using a standard minecraft selector.
* The client will see the players or entities captured by the specified selector as the text represented by this component.
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param selector The minecraft player or entity selector which will capture the entities whose string representations will be displayed in
* the place of this text component.
* @return The text component representing the name of the entities captured by the selector.
*/
public static TextualComponent selector(String selector) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE
// OVERLOADS documentation accordingly
return new ArbitraryTextTypeComponent("selector", selector);
}
@Override public String toString() {
return getReadableString();
}
/**
* @return The JSON key used to represent text components of this type.
*/
public abstract String getKey();
/**
* @return A readable String
*/
public abstract String getReadableString();
/**
* Clones a textual component instance.
* The returned object should not reference this textual component instance, but should maintain the same key and value.
*/
@Override public abstract TextualComponent clone() throws CloneNotSupportedException;
/**
* Writes the text data represented by this textual component to the specified JSON writer object.
* A new object within the writer is not started.
*
* @param writer The object to which to write the JSON data.
* @throws IOException If an error occurs while writing to the stream.
*/
public abstract void writeJson(JsonWriter writer) throws IOException;
/**
* Internal class used to represent all types of text components.
* Exception validating done is on keys and values.
*/
private static final class ArbitraryTextTypeComponent extends TextualComponent
implements ConfigurationSerializable {
private String key;
private String value;
public ArbitraryTextTypeComponent(String key, String value) {
setKey(key);
setValue(value);
}
public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) {
return new ArbitraryTextTypeComponent(map.get("key").toString(),
map.get("value").toString());
}
@Override public String getKey() {
return key;
}
public void setKey(String key) {
Preconditions
.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
Preconditions.checkArgument(value != null, "The value must be specified.");
this.value = value;
}
@Override public TextualComponent clone() throws CloneNotSupportedException {
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
return new ArbitraryTextTypeComponent(getKey(), getValue());
}
@Override public void writeJson(JsonWriter writer) throws IOException {
writer.name(getKey()).value(getValue());
}
@Override @SuppressWarnings("serial") public Map<String, Object> serialize() {
return new HashMap<String, Object>() {
{
put("key", getKey());
put("value", getValue());
}
};
}
@Override public String getReadableString() {
return getValue();
}
}
/**
* Internal class used to represent a text component with a nested JSON
* value.
*
* <p>Exception validating done is on keys and values.
*/
private static final class ComplexTextTypeComponent extends TextualComponent
implements ConfigurationSerializable {
private String key;
private Map<String, String> value;
public ComplexTextTypeComponent(String key, Map<String, String> values) {
setKey(key);
setValue(values);
}
public static ComplexTextTypeComponent deserialize(Map<String, Object> map) {
String key = null;
Map<String, String> value = new HashMap<>();
for (Map.Entry<String, Object> valEntry : map.entrySet()) {
if (valEntry.getKey().equals("key")) {
key = (String) valEntry.getValue();
} else if (valEntry.getKey().startsWith("value.")) {
value.put(valEntry.getKey().substring(6) /* Strips out the value prefix */,
valEntry.getValue().toString());
}
}
return new ComplexTextTypeComponent(key, value);
}
@Override public String getKey() {
return key;
}
public void setKey(String key) {
Preconditions
.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
this.key = key;
}
public Map<String, String> getValue() {
return value;
}
public void setValue(Map<String, String> value) {
Preconditions.checkArgument(value != null, "The value must be specified.");
this.value = value;
}
@Override public TextualComponent clone() {
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
return new ComplexTextTypeComponent(getKey(), getValue());
}
@Override public void writeJson(JsonWriter writer) throws IOException {
writer.name(getKey());
writer.beginObject();
for (Map.Entry<String, String> jsonPair : value.entrySet()) {
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
}
writer.endObject();
}
@Override @SuppressWarnings("serial") public Map<String, Object> serialize() {
return new java.util.HashMap<String, Object>() {
{
put("key", getKey());
for (Map.Entry<String, String> valEntry : getValue().entrySet()) {
put("value." + valEntry.getKey(), valEntry.getValue());
}
}
};
}
@Override public String getReadableString() {
return getKey();
}
}
}

View File

@ -1,54 +1,42 @@
package com.plotsquared.bukkit.commands;
package com.github.intellectualsites.plotsquared.bukkit.commands;
import com.github.intellectualsites.plotsquared.bukkit.uuid.DatFileFilter;
import com.github.intellectualsites.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
import com.github.intellectualsites.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
import com.github.intellectualsites.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
import com.github.intellectualsites.plotsquared.commands.Argument;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;
import com.github.intellectualsites.plotsquared.plot.commands.RequiredType;
import com.github.intellectualsites.plotsquared.plot.commands.SubCommand;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.StringWrapper;
import com.github.intellectualsites.plotsquared.plot.util.*;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.google.common.collect.Sets;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.commands.CommandCategory;
import com.intellectualcrafters.plot.commands.RequiredType;
import com.intellectualcrafters.plot.commands.SubCommand;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.uuid.DatFileFilter;
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
import com.plotsquared.general.commands.Argument;
import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.*;
import java.util.Map.Entry;
import java.util.UUID;
@CommandDeclaration(
command = "uuidconvert",
permission = "plots.admin",
description = "Debug UUID conversion",
usage = "/plot uuidconvert <lower|offline|online>",
requiredType = RequiredType.CONSOLE,
category = CommandCategory.DEBUG)
public class DebugUUID extends SubCommand {
@CommandDeclaration(command = "uuidconvert", permission = "plots.admin",
description = "Debug UUID conversion", usage = "/plot uuidconvert <lower|offline|online>",
requiredType = RequiredType.CONSOLE, category = CommandCategory.DEBUG) public class DebugUUID
extends SubCommand {
public DebugUUID() {
super(Argument.String);
}
@Override
public boolean onCommand(final PlotPlayer player, String[] args) {
@Override public boolean onCommand(final PlotPlayer player, String[] args) {
final UUIDWrapper currentUUIDWrapper = UUIDHandler.getUUIDWrapper();
final UUIDWrapper newWrapper;
@ -67,7 +55,8 @@ public class DebugUUID extends SubCommand {
Class<?> clazz = Class.forName(args[0]);
newWrapper = (UUIDWrapper) clazz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot uuidconvert <lower|offline|online>");
MainUtil.sendMessage(player, C.COMMAND_SYNTAX,
"/plot uuidconvert <lower|offline|online>");
return false;
}
}
@ -75,23 +64,29 @@ public class DebugUUID extends SubCommand {
if (args.length != 2 || !"-o".equals(args[1])) {
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot uuidconvert " + args[0] + " - o");
MainUtil.sendMessage(player, "&cBe aware of the following!");
MainUtil.sendMessage(player, "&8 - &cUse the database command or another method to backup your plots beforehand");
MainUtil.sendMessage(player, "&8 - &cIf the process is interrupted, all plots could be deleted");
MainUtil.sendMessage(player,
"&8 - &cUse the database command or another method to backup your plots beforehand");
MainUtil.sendMessage(player,
"&8 - &cIf the process is interrupted, all plots could be deleted");
MainUtil.sendMessage(player, "&8 - &cIf an error occurs, all plots could be deleted");
MainUtil.sendMessage(player, "&8 - &cPlot settings WILL be lost upon conversion");
MainUtil.sendMessage(player, "&cTO REITERATE: BACK UP YOUR DATABASE BEFORE USING THIS!!!");
MainUtil.sendMessage(player, "&7Retype the command with the override parameter when ready :)");
MainUtil
.sendMessage(player, "&cTO REITERATE: BACK UP YOUR DATABASE BEFORE USING THIS!!!");
MainUtil.sendMessage(player,
"&7Retype the command with the override parameter when ready :)");
return false;
}
if (currentUUIDWrapper.getClass().getCanonicalName().equals(newWrapper.getClass().getCanonicalName())) {
if (currentUUIDWrapper.getClass().getCanonicalName()
.equals(newWrapper.getClass().getCanonicalName())) {
MainUtil.sendMessage(player, "&cUUID mode already in use!");
return false;
}
MainUtil.sendMessage(player, "&6Beginning UUID mode conversion");
MainUtil.sendMessage(player, "&7 - Disconnecting players");
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
entry.getValue().kick("PlotSquared UUID conversion has been initiated. You may reconnect when finished.");
entry.getValue()
.kick("UUID conversion has been initiated. You may reconnect when finished.");
}
MainUtil.sendMessage(player, "&7 - Initializing map");
@ -135,12 +130,14 @@ public class DebugUUID extends SubCommand {
OfflinePlotPlayer op = wrapper.getOfflinePlayer(uuid);
uuid = currentUUIDWrapper.getUUID(op);
uuid2 = newWrapper.getUUID(op);
if (!uuid.equals(uuid2) && !uCMap.containsKey(uuid) && !uCReverse.containsKey(uuid2)) {
if (!uuid.equals(uuid2) && !uCMap.containsKey(uuid) && !uCReverse
.containsKey(uuid2)) {
uCMap.put(uuid, uuid2);
uCReverse.put(uuid2, uuid);
}
} catch (Throwable ignored) {
MainUtil.sendMessage(player, C.PREFIX + "&6Invalid playerdata: " + uuid.toString() + ".dat");
MainUtil.sendMessage(player,
C.PREFIX + "&6Invalid playerdata: " + uuid.toString() + ".dat");
}
}
for (String name : names) {
@ -155,7 +152,7 @@ public class DebugUUID extends SubCommand {
MainUtil.sendMessage(player, "&c - Error! Attempting to repopulate");
for (OfflinePlotPlayer op : currentUUIDWrapper.getOfflinePlayers()) {
if (op.getLastPlayed() != 0) {
// String name = op.getName();
// String name = op.getPluginName();
// StringWrapper wrap = new StringWrapper(name);
UUID uuid = currentUUIDWrapper.getUUID(op);
uuid2 = newWrapper.getUUID(op);
@ -175,8 +172,7 @@ public class DebugUUID extends SubCommand {
MainUtil.sendMessage(player, "&7 - Replacing cache");
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
for (Entry<UUID, UUID> entry : uCMap.entrySet()) {
String name = UUIDHandler.getName(entry.getKey());
if (name != null) {
@ -186,10 +182,11 @@ public class DebugUUID extends SubCommand {
MainUtil.sendMessage(player, "&7 - Scanning for applicable files (uuids.txt)");
File file = new File(PS.get().IMP.getDirectory(), "uuids.txt");
File file = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt");
if (file.exists()) {
try {
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
List<String> lines =
Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
for (String line : lines) {
try {
line = line.trim();
@ -199,7 +196,8 @@ public class DebugUUID extends SubCommand {
line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", "");
String[] split = line.split("\\|");
String name = split[0];
if (name.isEmpty() || name.length() > 16 || !StringMan.isAlphanumericUnd(name)) {
if (name.isEmpty() || name.length() > 16 || !StringMan
.isAlphanumericUnd(name)) {
continue;
}
UUID old = currentUUIDWrapper.getUUID(name);
@ -224,7 +222,7 @@ public class DebugUUID extends SubCommand {
MainUtil.sendMessage(player, "&7 - Updating plot objects");
for (Plot plot : PS.get().getPlots()) {
for (Plot plot : PlotSquared.get().getPlots()) {
UUID value = uCMap.get(plot.owner);
if (value != null) {
plot.owner = value;
@ -243,18 +241,18 @@ public class DebugUUID extends SubCommand {
DBFunc.createTables();
if (!result) {
MainUtil.sendMessage(player, "&cConversion failed! Attempting recovery");
for (Plot plot : PS.get().getPlots()) {
for (Plot plot : PlotSquared.get().getPlots()) {
UUID value = uCReverse.get(plot.owner);
if (value != null) {
plot.owner = value;
}
}
DBFunc.createPlotsAndData(new ArrayList<>(PS.get().getPlots()), new Runnable() {
@Override
public void run() {
MainUtil.sendMessage(player, "&6Recovery was successful!");
}
});
DBFunc.createPlotsAndData(new ArrayList<>(PlotSquared.get().getPlots()),
new Runnable() {
@Override public void run() {
MainUtil.sendMessage(player, "&6Recovery was successful!");
}
});
return;
}
} catch (Exception e) {
@ -263,27 +261,26 @@ public class DebugUUID extends SubCommand {
}
if (newWrapper instanceof OfflineUUIDWrapper) {
PS.get().worlds.set("UUID.force-lowercase", false);
PS.get().worlds.set("UUID.offline", true);
PlotSquared.get().worlds.set("UUID.force-lowercase", false);
PlotSquared.get().worlds.set("UUID.offline", true);
} else if (newWrapper instanceof DefaultUUIDWrapper) {
PS.get().worlds.set("UUID.force-lowercase", false);
PS.get().worlds.set("UUID.offline", false);
PlotSquared.get().worlds.set("UUID.force-lowercase", false);
PlotSquared.get().worlds.set("UUID.offline", false);
}
try {
PS.get().worlds.save(PS.get().worldsFile);
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
} catch (IOException ignored) {
MainUtil.sendMessage(player, "Could not save configuration. It will need to be manual set!");
MainUtil.sendMessage(player,
"Could not save configuration. It will need to be manual set!");
}
MainUtil.sendMessage(player, "&7 - Populating tables");
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
ArrayList<Plot> plots = new ArrayList<>(PS.get().getPlots());
@Override public void run() {
ArrayList<Plot> plots = new ArrayList<>(PlotSquared.get().getPlots());
DBFunc.createPlotsAndData(plots, new Runnable() {
@Override
public void run() {
@Override public void run() {
MainUtil.sendMessage(player, "&aConversion complete!");
}
});
@ -291,7 +288,8 @@ public class DebugUUID extends SubCommand {
});
MainUtil.sendMessage(player, "&aIt is now safe for players to join");
MainUtil.sendMessage(player, "&cConversion is still in progress, you will be notified when it is complete");
MainUtil.sendMessage(player,
"&cConversion is still in progress, you will be notified when it is complete");
}
});
return true;

View File

@ -1,10 +1,10 @@
package com.plotsquared.bukkit.database.plotme;
package com.github.intellectualsites.plotsquared.bukkit.database.plotme;
import com.intellectualcrafters.configuration.file.FileConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.configuration.file.FileConfiguration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import java.sql.Connection;
import java.sql.SQLException;
@ -13,9 +13,11 @@ import java.util.HashMap;
public abstract class APlotMeConnector {
public abstract Connection getPlotMeConnection(FileConfiguration plotConfig, String dataFolder);
public abstract Connection getPlotMeConnection(String plugin, FileConfiguration plotConfig,
String dataFolder);
public abstract HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection) throws SQLException;
public abstract HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection)
throws SQLException;
public abstract boolean accepts(String version);
@ -25,21 +27,23 @@ public abstract class APlotMeConnector {
public void copyConfig(FileConfiguration plotConfig, String world, String actualWorldName) {
int pathWidth = plotConfig.getInt("worlds." + world + ".PathWidth"); //
PS.get().worlds.set("worlds." + actualWorldName + ".road.width", pathWidth);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".road.width", pathWidth);
int plotSize = plotConfig.getInt("worlds." + world + ".PlotSize"); //
PS.get().worlds.set("worlds." + actualWorldName + ".plot.size", plotSize);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".plot.size", plotSize);
String wallBlock = plotConfig.getString("worlds." + world + ".WallBlockId"); //
PS.get().worlds.set("worlds." + actualWorldName + ".wall.block", wallBlock);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".wall.block", wallBlock);
String floor = plotConfig.getString("worlds." + world + ".PlotFloorBlockId"); //
PS.get().worlds.set("worlds." + actualWorldName + ".plot.floor", Collections.singletonList(floor));
PlotSquared.get().worlds
.set("worlds." + actualWorldName + ".plot.floor", Collections.singletonList(floor));
String filling = plotConfig.getString("worlds." + world + ".PlotFillingBlockId"); //
PS.get().worlds.set("worlds." + actualWorldName + ".plot.filling", Collections.singletonList(filling));
PlotSquared.get().worlds
.set("worlds." + actualWorldName + ".plot.filling", Collections.singletonList(filling));
String road = plotConfig.getString("worlds." + world + ".RoadMainBlockId");
PS.get().worlds.set("worlds." + actualWorldName + ".road.block", road);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".road.block", road);
int height = plotConfig.getInt("worlds." + world + ".RoadHeight"); //
PS.get().worlds.set("worlds." + actualWorldName + ".road.height", height);
PS.get().worlds.set("worlds." + actualWorldName + ".plot.height", height);
PS.get().worlds.set("worlds." + actualWorldName + ".wall.height", height);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".road.height", height);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".plot.height", height);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".wall.height", height);
}
public Location getPlotTopLocAbs(int path, int plot, PlotId plotId) {
@ -58,25 +62,26 @@ public abstract class APlotMeConnector {
return new Location(null, x, 1, z);
}
public void setMerged(HashMap<String, HashMap<PlotId, boolean[]>> merges, String world, PlotId id, int direction) {
public void setMerged(HashMap<String, HashMap<PlotId, boolean[]>> merges, String world,
PlotId id, int direction) {
HashMap<PlotId, boolean[]> plots = merges.get(world);
PlotId id2 = new PlotId(id.x, id.y);
boolean[] merge1;
if (plots.containsKey(id)) {
merge1 = plots.get(id);
} else {
merge1 = new boolean[] { false, false, false, false };
merge1 = new boolean[] {false, false, false, false};
}
boolean[] merge2;
if (plots.containsKey(id2)) {
merge2 = plots.get(id2);
} else {
merge2 = new boolean[] { false, false, false, false };
merge2 = new boolean[] {false, false, false, false};
}
merge1[direction] = true;
merge2[(direction + 2) % 4] = true;
plots.put(id, merge1);
plots.put(id2, merge1);
}
}

View File

@ -1,37 +1,29 @@
package com.plotsquared.bukkit.database.plotme;
package com.github.intellectualsites.plotsquared.bukkit.database.plotme;
import com.github.intellectualsites.plotsquared.configuration.file.FileConfiguration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.database.SQLite;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.google.common.base.Charsets;
import com.intellectualcrafters.configuration.file.FileConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.SQLite;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.UUIDHandler;
import java.io.File;
import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.UUID;
public class ClassicPlotMeConnector extends APlotMeConnector {
private String plugin;
private String plugin = "PlotMe";
private String prefix;
@Override
public Connection getPlotMeConnection(FileConfiguration plotConfig, String dataFolder) {
this.plugin = this.plugin.toLowerCase();
@Override public Connection getPlotMeConnection(String plugin, FileConfiguration plotConfig,
String dataFolder) {
this.plugin = plugin.toLowerCase();
this.prefix = plotConfig.getString("mySQLprefix", this.plugin.toLowerCase());
try {
if (plotConfig.getBoolean("usemySQL")) {
@ -40,7 +32,8 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
String con = plotConfig.getString("mySQLconn");
return DriverManager.getConnection(con, user, password);
} else {
return new SQLite(new File(dataFolder + File.separator + "plots.db")).openConnection();
return new SQLite(new File(dataFolder + File.separator + "plots.db"))
.openConnection();
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
@ -48,13 +41,14 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
return null;
}
@Override
public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection) throws SQLException {
@Override public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection)
throws SQLException {
HashMap<String, Integer> plotWidth = new HashMap<>();
HashMap<String, Integer> roadWidth = new HashMap<>();
HashMap<String, HashMap<PlotId, Plot>> plots = new HashMap<>();
HashMap<String, HashMap<PlotId, boolean[]>> merges = new HashMap<>();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM `" + this.prefix + "Plots`");
PreparedStatement statement =
connection.prepareStatement("SELECT * FROM `" + this.prefix + "Plots`");
ResultSet resultSet = statement.executeQuery();
String column = null;
boolean checkUUID = DBFunc.hasColumn(resultSet, "ownerid");
@ -64,7 +58,8 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
} else if (checkUUID2) {
column = "ownerId";
}
boolean merge = !"plotme".equalsIgnoreCase(this.plugin) && Settings.Enabled_Components.PLOTME_CONVERTER;
boolean merge =
!"plotme".equalsIgnoreCase(this.plugin) && Settings.Enabled_Components.PLOTME_CONVERTER;
int missing = 0;
while (resultSet.next()) {
PlotId id = new PlotId(resultSet.getInt("idX"), resultSet.getInt("idZ"));
@ -73,8 +68,8 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
if (!plots.containsKey(world)) {
plots.put(world, new HashMap<PlotId, Plot>());
if (merge) {
int plot = PS.get().worlds.getInt("worlds." + world + ".plot.size");
int path = PS.get().worlds.getInt("worlds." + world + ".road.width");
int plot = PlotSquared.get().worlds.getInt("worlds." + world + ".plot.size");
int path = PlotSquared.get().worlds.getInt("worlds." + world + ".road.width");
plotWidth.put(world, plot);
roadWidth.put(world, path);
merges.put(world, new HashMap<PlotId, boolean[]>());
@ -105,7 +100,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
UUID owner = UUIDHandler.getUUID(name, null);
if (owner == null) {
if ("*".equals(name)) {
owner = DBFunc.everyone;
owner = DBFunc.EVERYONE;
} else {
if (checkUUID || checkUUID2) {
byte[] bytes = resultSet.getBytes(column);
@ -118,11 +113,13 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
}
}
if (name.isEmpty()) {
PS.log("&cCould not identify owner for plot: " + id + " -> '" + name + "'");
PlotSquared.log(
"&cCould not identify owner for plot: " + id + " -> '" + name + "'");
missing++;
continue;
}
owner = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8));
owner = UUID.nameUUIDFromBytes(
("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8));
}
} else {
UUIDHandler.add(new StringWrapper(name), owner);
@ -131,10 +128,13 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
plots.get(world).put(id, plot);
}
if (missing > 0) {
PS.log("&cSome names could not be identified:");
PS.log("&7 - Empty quotes mean PlotMe just stored an unowned plot in the database");
PS.log("&7 - Names you have never seen before could be from people mistyping commands");
PS.log("&7 - Converting from a non-uuid version of PlotMe can't identify owners if the playerdata files are deleted (these plots will "
PlotSquared.log("&cSome names could not be identified:");
PlotSquared
.log("&7 - Empty quotes mean PlotMe just stored an unowned plot in the database");
PlotSquared.log(
"&7 - Names you have never seen before could be from people mistyping commands");
PlotSquared.log(
"&7 - Converting from a non-uuid version of PlotMe can't identify owners if the playerdata files are deleted (these plots will "
+ "remain unknown until the player connects)");
}
@ -154,7 +154,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
try {
PS.log(" - " + this.prefix + "Denied");
PlotSquared.log(" - " + this.prefix + "Denied");
statement = connection.prepareStatement("SELECT * FROM `" + this.prefix + "Denied`");
resultSet = statement.executeQuery();
@ -165,7 +165,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
UUID denied = UUIDHandler.getUUID(name, null);
if (denied == null) {
if ("*".equals(name)) {
denied = DBFunc.everyone;
denied = DBFunc.EVERYONE;
} else if (DBFunc.hasColumn(resultSet, "playerid")) {
byte[] bytes = resultSet.getBytes("playerid");
if (bytes != null) {
@ -177,7 +177,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
}
}
if (denied == null) {
PS.log("&6Could not identify denied for plot: " + id);
PlotSquared.log("&6Could not identify denied for plot: " + id);
continue;
}
}
@ -200,7 +200,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
UUID helper = UUIDHandler.getUUID(name, null);
if (helper == null) {
if ("*".equals(name)) {
helper = DBFunc.everyone;
helper = DBFunc.EVERYONE;
} else if (DBFunc.hasColumn(resultSet, "playerid")) {
byte[] bytes = resultSet.getBytes("playerid");
if (bytes != null) {
@ -212,7 +212,7 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
}
}
if (helper == null) {
PS.log("&6Could not identify helper for plot: " + id);
PlotSquared.log("&6Could not identify helper for plot: " + id);
continue;
}
}
@ -228,12 +228,13 @@ public class ClassicPlotMeConnector extends APlotMeConnector {
resultSet.close();
statement.close();
} catch (SQLException ignored) {}
} catch (SQLException ignored) {
}
return plots;
}
@Override
public boolean accepts(String version) {
return version == null || PS.get().canUpdate(version, "0.17.0") || PS.get().canUpdate("0.999.999", version);
@Override public boolean accepts(String version) {
return version == null || PlotSquared.get().canUpdate(version, "0.17.0") || PlotSquared
.get().canUpdate("0.999.999", version);
}
}

View File

@ -0,0 +1,393 @@
package com.github.intellectualsites.plotsquared.bukkit.database.plotme;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
import com.github.intellectualsites.plotsquared.configuration.MemorySection;
import com.github.intellectualsites.plotsquared.configuration.file.FileConfiguration;
import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.command.CommandException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
public class LikePlotMeConverter {
private final String plugin;
public LikePlotMeConverter(String plugin) {
this.plugin = plugin;
}
public static String getWorld(String world) {
for (World newWorld : Bukkit.getWorlds()) {
if (newWorld.getName().equalsIgnoreCase(world)) {
return newWorld.getName();
}
}
return world;
}
private void sendMessage(String message) {
PlotSquared
.debug("&3PlotMe&8->&3" + PlotSquared.imp().getPluginName() + "&8: &7" + message);
}
public String getPlotMePath() {
return new File(".").getAbsolutePath() + File.separator + "plugins" + File.separator
+ plugin + File.separator;
}
public FileConfiguration getPlotMeConfig(String dataFolder) {
File plotMeFile = new File(dataFolder + "config.yml");
if (!plotMeFile.exists()) {
return null;
}
return YamlConfiguration.loadConfiguration(plotMeFile);
}
public Set<String> getPlotMeWorlds(FileConfiguration plotConfig) {
return plotConfig.getConfigurationSection("worlds").getKeys(false);
}
public void mergeWorldYml(FileConfiguration plotConfig) {
try {
File genConfig = new File(
"plugins" + File.separator + plugin + File.separator + "PlotMe-DefaultGenerator"
+ File.separator + "config.yml");
if (genConfig.exists()) {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(genConfig);
for (String key : yml.getKeys(true)) {
if (!plotConfig.contains(key)) {
Object value = yml.get(key);
if (!(value instanceof MemorySection)) {
plotConfig.set(key, value);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void updateWorldYml(String location) {
try {
Path path = Paths.get(location);
File file = new File(location);
if (!file.exists()) {
return;
}
String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
String pluginName = PlotSquared.imp().getPluginName();
content = content.replace("PlotMe-DefaultGenerator", pluginName);
content = content.replace("PlotMe", pluginName);
content = content.replace("AthionPlots", pluginName);
content = content.replace("PlotZWorld", pluginName);
Files.write(path, content.getBytes(StandardCharsets.UTF_8));
} catch (IOException ignored) {
}
}
private void copyConfig(ConfigurationSection plotmeDgYml, String world) throws IOException {
String actualWorldName = getWorld(world);
String plotMeWorldName = world.toLowerCase();
Integer pathWidth = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".PathWidth"); //
PlotSquared.get().worlds.set("worlds." + world + ".road.width", pathWidth);
int height = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".RoadHeight",
plotmeDgYml.getInt("worlds." + plotMeWorldName + ".GroundHeight", 64)); //
PlotSquared.get().worlds.set("worlds." + world + ".road.height", height);
PlotSquared.get().worlds.set("worlds." + world + ".wall.height", height);
PlotSquared.get().worlds.set("worlds." + world + ".plot.height", height);
int plotSize = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".PlotSize", 32); //
PlotSquared.get().worlds.set("worlds." + world + ".plot.size", plotSize);
String wallblock = plotmeDgYml.getString("worlds." + plotMeWorldName + ".UnclaimedBorder",
plotmeDgYml.getString("worlds." + plotMeWorldName + ".WallBlock", "44")); //
PlotSquared.get().worlds.set("worlds." + world + ".wall.block", wallblock);
String claimed =
plotmeDgYml.getString("worlds." + plotMeWorldName + ".ProtectedWallBlock", "44:1"); //
PlotSquared.get().worlds.set("worlds." + world + ".wall.block_claimed", claimed);
String floor =
plotmeDgYml.getString("worlds." + plotMeWorldName + ".PlotFloorBlock", "2"); //
PlotSquared.get().worlds
.set("worlds." + world + ".plot.floor", Collections.singletonList(floor));
String filling = plotmeDgYml.getString("worlds." + plotMeWorldName + ".FillBlock", "3"); //
PlotSquared.get().worlds
.set("worlds." + world + ".plot.filling", Collections.singletonList(filling));
String road = plotmeDgYml.getString("worlds." + plotMeWorldName + ".RoadMainBlock", "5");
PlotSquared.get().worlds.set("worlds." + world + ".road.block", road);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".road.height", height);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".plot.height", height);
PlotSquared.get().worlds.set("worlds." + actualWorldName + ".wall.height", height);
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
}
public boolean run(APlotMeConnector connector) {
try {
String dataFolder = getPlotMePath();
FileConfiguration plotConfig = getPlotMeConfig(dataFolder);
if (plotConfig == null) {
return false;
}
String version = plotConfig.getString("Version");
if (version == null) {
version = plotConfig.getString("version");
}
if (!connector.accepts(version)) {
return false;
}
PlotSquared.debug("&3Using connector: " + connector.getClass().getCanonicalName());
Connection connection = connector.getPlotMeConnection(plugin, plotConfig, dataFolder);
if (!connector.isValidConnection(connection)) {
sendMessage("Cannot connect to PlotMe DB. Conversion process will not continue");
return false;
}
sendMessage(
"PlotMe conversion has started. To disable this, please set 'enabled-components -> plotme-converter' to false in the 'settings.yml'");
mergeWorldYml(plotConfig);
sendMessage("Connecting to PlotMe DB");
ArrayList<Plot> createdPlots = new ArrayList<>();
sendMessage("Collecting plot data");
String dbPrefix = "PlotMe".toLowerCase();
sendMessage(" - " + dbPrefix + "Plots");
final Set<String> worlds = getPlotMeWorlds(plotConfig);
if (Settings.Enabled_Components.PLOTME_CONVERTER) {
sendMessage("Updating bukkit.yml");
updateWorldYml("bukkit.yml");
updateWorldYml("plugins/Multiverse-Core/worlds.yml");
for (String world : plotConfig.getConfigurationSection("worlds").getKeys(false)) {
sendMessage("Copying config for: " + world);
try {
String actualWorldName = getWorld(world);
connector.copyConfig(plotConfig, world, actualWorldName);
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
} catch (IOException e) {
e.printStackTrace();
sendMessage("&c-- &lFailed to save configuration for world '" + world
+ "'\nThis will need to be done using the setup command, or manually");
}
}
}
HashMap<String, HashMap<PlotId, Plot>> plots = connector.getPlotMePlots(connection);
int plotCount = 0;
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
plotCount += entry.getValue().size();
}
if (!Settings.Enabled_Components.PLOTME_CONVERTER) {
return false;
}
sendMessage(" - " + dbPrefix + "Allowed");
sendMessage("Collected " + plotCount + " plots from PlotMe");
File plotmeDgFile = new File(
dataFolder + File.separator + "PlotMe-DefaultGenerator" + File.separator
+ "config.yml");
if (plotmeDgFile.exists()) {
YamlConfiguration plotmeDgYml = YamlConfiguration.loadConfiguration(plotmeDgFile);
try {
HashSet<String> allWorlds = new HashSet<>(plots.keySet());
allWorlds.addAll(worlds);
for (String world : allWorlds) {
copyConfig(plotmeDgYml, world);
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
String world = entry.getKey();
PlotArea area = PlotSquared.get().getPlotArea(world, null);
int duplicate = 0;
if (area != null) {
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
if (area.getOwnedPlotAbs(entry2.getKey()) != null) {
duplicate++;
} else {
createdPlots.add(entry2.getValue());
}
}
if (duplicate > 0) {
PlotSquared.debug("&c[WARNING] Found " + duplicate
+ " duplicate plots already in DB for world: '" + world
+ "'. Have you run the converter already?");
}
} else {
if (PlotSquared.get().plots_tmp != null) {
HashMap<PlotId, Plot> map = PlotSquared.get().plots_tmp.get(world);
if (map != null) {
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
if (map.containsKey(entry2.getKey())) {
duplicate++;
} else {
createdPlots.add(entry2.getValue());
}
}
if (duplicate > 0) {
PlotSquared.debug("&c[WARNING] Found " + duplicate
+ " duplicate plots already in DB for world: '" + world
+ "'. Have you run the converter already?");
}
continue;
}
}
createdPlots.addAll(entry.getValue().values());
}
}
sendMessage("Creating plot DB");
Thread.sleep(1000);
final AtomicBoolean done = new AtomicBoolean(false);
DBFunc.createPlotsAndData(createdPlots, new Runnable() {
@Override public void run() {
if (done.get()) {
done();
sendMessage("&aDatabase conversion is now complete!");
PlotSquared.debug("&c - Stop the server");
PlotSquared.debug(
"&c - Disable 'plotme-converter' and 'plotme-convert.cache-uuids' in the settings.yml");
PlotSquared.debug(
"&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
PlotSquared.debug("&c - Start the server");
PlotSquared.get().setPlots(DBFunc.getPlots());
} else {
sendMessage(
"&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
done.set(true);
}
}
});
sendMessage("Saving configuration...");
try {
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
} catch (IOException ignored) {
sendMessage(" - &cFailed to save configuration.");
}
TaskManager.runTask(new Runnable() {
@Override public void run() {
try {
boolean mv = false;
boolean mw = false;
if ((Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null)
&& Bukkit.getPluginManager().getPlugin("Multiverse-Core").isEnabled()) {
mv = true;
} else if ((Bukkit.getPluginManager().getPlugin("MultiWorld") != null)
&& Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
mw = true;
}
for (String worldName : worlds) {
World world = Bukkit.getWorld(getWorld(worldName));
if (world == null) {
sendMessage(
"&cInvalid world in PlotMe configuration: " + worldName);
continue;
}
String actualWorldName = world.getName();
sendMessage(
"Reloading generator for world: '" + actualWorldName + "'...");
if (!Bukkit.getWorlds().isEmpty() && Bukkit.getWorlds().get(0).getName()
.equals(worldName)) {
sendMessage(
"&cYou need to stop the server to reload this world properly");
} else {
PlotSquared.get().removePlotAreas(actualWorldName);
if (mv) {
// unload world with MV
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mv unload " + actualWorldName);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// load world with MV
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mv import " + actualWorldName + " normal -g "
+ PlotSquared.imp().getPluginName());
} else if (mw) {
// unload world with MW
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mw unload " + actualWorldName);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// load world with MW
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mw create " + actualWorldName + " plugin:"
+ PlotSquared.imp().getPluginName());
} else {
// Load using Bukkit API
// - User must set generator manually
Bukkit.getServer().unloadWorld(world, true);
World myWorld = WorldCreator.name(actualWorldName).generator(
new BukkitPlotGenerator(
PlotSquared.get().IMP.getDefaultGenerator()))
.createWorld();
myWorld.save();
}
}
}
} catch (CommandException e) {
e.printStackTrace();
}
if (done.get()) {
done();
sendMessage("&aDatabase conversion is now complete!");
PlotSquared.debug("&c - Stop the server");
PlotSquared.debug(
"&c - Disable 'plotme-converter' and 'plotme-convert.cache-uuids' in the settings.yml");
PlotSquared.debug(
"&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
PlotSquared.debug("&c - Start the server");
} else {
sendMessage(
"&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
done.set(true);
}
}
});
} catch (InterruptedException | SQLException e) {
e.printStackTrace();
PlotSquared.debug("&/end/");
}
return true;
}
public void done() {
PlotSquared.get().setPlots(DBFunc.getPlots());
}
}

View File

@ -1,23 +1,15 @@
package com.plotsquared.bukkit.database.plotme;
package com.github.intellectualsites.plotsquared.bukkit.database.plotme;
import com.intellectualcrafters.configuration.file.FileConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.SQLite;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.configuration.file.FileConfiguration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.DBFunc;
import com.github.intellectualsites.plotsquared.plot.database.SQLite;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.*;
import java.util.HashMap;
import java.util.UUID;
@ -25,9 +17,9 @@ public class PlotMeConnector_017 extends APlotMeConnector {
private String plugin;
@Override
public Connection getPlotMeConnection(FileConfiguration plotConfig, String dataFolder) {
this.plugin = this.plugin.toLowerCase();
@Override public Connection getPlotMeConnection(String plugin, FileConfiguration plotConfig,
String dataFolder) {
this.plugin = plugin.toLowerCase();
try {
if (plotConfig.getBoolean("usemySQL")) {
String user = plotConfig.getString("mySQLuname");
@ -39,7 +31,8 @@ public class PlotMeConnector_017 extends APlotMeConnector {
if (file.exists()) {
return new SQLite(file).openConnection();
}
return new SQLite(new File(dataFolder + File.separator + "plots.db")).openConnection();
return new SQLite(new File(dataFolder + File.separator + "plots.db"))
.openConnection();
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
@ -47,8 +40,8 @@ public class PlotMeConnector_017 extends APlotMeConnector {
return null;
}
@Override
public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection) throws SQLException {
@Override public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(Connection connection)
throws SQLException {
ResultSet resultSet;
PreparedStatement statement;
HashMap<String, Integer> plotWidth = new HashMap<>();
@ -56,26 +49,30 @@ public class PlotMeConnector_017 extends APlotMeConnector {
HashMap<Integer, Plot> plots = new HashMap<>();
HashMap<String, HashMap<PlotId, boolean[]>> merges = new HashMap<>();
try {
statement = connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_plots`");
statement =
connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_plots`");
resultSet = statement.executeQuery();
} catch (SQLException e) {
PS.debug("========= Table does not exist =========");
PlotSquared.debug("========= Table does not exist =========");
e.printStackTrace();
PS.debug("=======================================");
PS.debug("&8 - &7The database does not match the version specified in the PlotMe config");
PS.debug("&8 - &7Please correct this, or if you are unsure, the most common is 0.16.3");
PlotSquared.debug("=======================================");
PlotSquared.debug(
"&8 - &7The database does not match the version specified in the PlotMe config");
PlotSquared.debug(
"&8 - &7Please correct this, or if you are unsure, the most common is 0.16.3");
return null;
}
boolean checkUUID = DBFunc.hasColumn(resultSet, "ownerID");
boolean merge = !this.plugin.equals("plotme") && Settings.Enabled_Components.PLOTME_CONVERTER;
boolean merge =
!"plotme".equals(this.plugin) && Settings.Enabled_Components.PLOTME_CONVERTER;
while (resultSet.next()) {
int key = resultSet.getInt("plot_id");
PlotId id = new PlotId(resultSet.getInt("plotX"), resultSet.getInt("plotZ"));
String name = resultSet.getString("owner");
String world = LikePlotMeConverter.getWorld(resultSet.getString("world"));
if (!plots.containsKey(world) && merge) {
int plot = PS.get().worlds.getInt("worlds." + world + ".plot.size");
int path = PS.get().worlds.getInt("worlds." + world + ".road.width");
int plot = PlotSquared.get().worlds.getInt("worlds." + world + ".plot.size");
int path = PlotSquared.get().worlds.getInt("worlds." + world + ".road.width");
plotWidth.put(world, plot);
roadWidth.put(world, path);
merges.put(world, new HashMap<PlotId, boolean[]>());
@ -105,7 +102,7 @@ public class PlotMeConnector_017 extends APlotMeConnector {
UUID owner = UUIDHandler.getUUID(name, null);
if (owner == null) {
if (name.equals("*")) {
owner = DBFunc.everyone;
owner = DBFunc.EVERYONE;
} else {
if (checkUUID) {
byte[] bytes = resultSet.getBytes("ownerid");
@ -115,7 +112,8 @@ public class PlotMeConnector_017 extends APlotMeConnector {
}
}
if (owner == null) {
PS.log("&cCould not identify owner for plot: " + id + " -> '" + name + '\'');
PlotSquared.log(
"&cCould not identify owner for plot: " + id + " -> '" + name + '\'');
continue;
}
}
@ -126,7 +124,7 @@ public class PlotMeConnector_017 extends APlotMeConnector {
plots.put(key, plot);
}
for (Plot plot : plots.values()) {
HashMap<PlotId, boolean[]> mergeMap = merges.get(plot.getArea().worldname);
HashMap<PlotId, boolean[]> mergeMap = merges.get(plot.getWorldName());
if (mergeMap != null) {
if (mergeMap.containsKey(plot.getId())) {
plot.setMerged(mergeMap.get(plot.getId()));
@ -136,33 +134,39 @@ public class PlotMeConnector_017 extends APlotMeConnector {
resultSet.close();
statement.close();
try {
PS.log(" - " + this.plugin + "core_denied");
statement = connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_denied`");
PlotSquared.log(" - " + this.plugin + "core_denied");
statement =
connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_denied`");
resultSet = statement.executeQuery();
while (resultSet.next()) {
int key = resultSet.getInt("plot_id");
Plot plot = plots.get(key);
if (plot == null) {
PS.log("&6Denied (" + key + ") references deleted plot; ignoring entry.");
PlotSquared
.log("&6Denied (" + key + ") references deleted plot; ignoring entry.");
continue;
}
UUID denied = UUID.fromString(resultSet.getString("player"));
String player = resultSet.getString("player");
UUID denied = player.equals("*") ? DBFunc.EVERYONE : UUID.fromString(player);
plot.getDenied().add(denied);
}
PS.log(" - " + this.plugin + "core_allowed");
statement = connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_allowed`");
PlotSquared.log(" - " + this.plugin + "core_allowed");
statement =
connection.prepareStatement("SELECT * FROM `" + this.plugin + "core_allowed`");
resultSet = statement.executeQuery();
while (resultSet.next()) {
int key = resultSet.getInt("plot_id");
Plot plot = plots.get(key);
if (plot == null) {
PS.log("&6Allowed (" + key + ") references deleted plot; ignoring entry.");
PlotSquared
.log("&6Allowed (" + key + ") references deleted plot; ignoring entry.");
continue;
}
UUID allowed = UUID.fromString(resultSet.getString("player"));
String player = resultSet.getString("player");
UUID allowed = player.equals("*") ? DBFunc.EVERYONE : UUID.fromString(player);
plot.getTrusted().add(allowed);
}
resultSet.close();
@ -174,21 +178,20 @@ public class PlotMeConnector_017 extends APlotMeConnector {
HashMap<String, HashMap<PlotId, Plot>> processed = new HashMap<>();
for (Plot plot : plots.values()) {
HashMap<PlotId, Plot> map = processed.get(plot.getArea().worldname);
HashMap<PlotId, Plot> map = processed.get(plot.getWorldName());
if (map == null) {
map = new HashMap<>();
processed.put(plot.getArea().worldname, map);
processed.put(plot.getWorldName(), map);
}
map.put(plot.getId(), plot);
}
return processed;
}
@Override
public boolean accepts(String version) {
@Override public boolean accepts(String version) {
if (version == null) {
return false;
}
return !PS.get().canUpdate(version, "0.17");
return !PlotSquared.get().canUpdate(version, "0.17");
}
}

View File

@ -1,7 +1,7 @@
package com.plotsquared.bukkit.events;
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.object.PlotCluster;
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
import com.github.intellectualsites.plotsquared.plot.object.PlotCluster;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@ -19,7 +19,7 @@ public class ClusterFlagRemoveEvent extends Event implements Cancellable {
/**
* PlotFlagRemoveEvent: Called when a flag is removed from a plot.
*
* @param flag Flag that was removed
* @param flag Flag that was removed
* @param cluster PlotCluster from which the flag was removed
*/
public ClusterFlagRemoveEvent(Flag flag, PlotCluster cluster) {
@ -49,18 +49,15 @@ public class ClusterFlagRemoveEvent extends Event implements Cancellable {
return this.flag;
}
@Override
public HandlerList getHandlers() {
@Override public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,62 +1,59 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerClaimPlotEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
private final boolean auto;
private boolean cancelled;
/**
* PlayerClaimPlotEvent: Called when a plot is claimed.
*
* @param player Player that claimed the plot
* @param plot Plot that was claimed
*/
public PlayerClaimPlotEvent(Player player, Plot plot, boolean auto) {
super(player);
this.plot = plot;
this.auto = auto;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
/**
* @return true if it was an automated claim, else false
*/
public boolean wasAuto() {
return this.auto;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerClaimPlotEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
private final boolean auto;
private boolean cancelled;
/**
* PlayerClaimPlotEvent: Called when a plot is claimed.
*
* @param player Player that claimed the plot
* @param plot Plot that was claimed
*/
public PlayerClaimPlotEvent(Player player, Plot plot, boolean auto) {
super(player);
this.plot = plot;
this.auto = auto;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
/**
* @return true if it was an automated claim, else false
*/
public boolean wasAuto() {
return this.auto;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,41 +1,40 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerEnterPlotEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
/**
* Called when a player leaves a plot.
*
* @param player Player that entered the plot
* @param plot Plot that was entered
*/
public PlayerEnterPlotEvent(Player player, Plot plot) {
super(player);
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved.
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
public class PlayerEnterPlotEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
/**
* Called when a player leaves a plot.
*
* @param player Player that entered the plot
* @param plot Plot that was entered
*/
public PlayerEnterPlotEvent(Player player, Plot plot) {
super(player);
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved.
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,45 +1,44 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
*/
public class PlayerLeavePlotEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
/**
* PlayerLeavePlotEvent: Called when a player leaves a plot
*
* @param player Player that left the plot
* @param plot Plot that was left
*/
public PlayerLeavePlotEvent(Player player, Plot plot) {
super(player);
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
*/
public class PlayerLeavePlotEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final Plot plot;
/**
* PlayerLeavePlotEvent: Called when a player leaves a plot
*
* @param player Player that left the plot
* @param plot Plot that was left
*/
public PlayerLeavePlotEvent(Player player, Plot plot) {
super(player);
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,66 +1,65 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
public class PlayerPlotDeniedEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotDeniedEvent: Called when the denied UUID list is modified for a plot.
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was denied/un-denied
* @param added true of add to deny list, false if removed
*/
public PlayerPlotDeniedEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a user was added.
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The player added/removed.
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action.
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
public class PlayerPlotDeniedEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotDeniedEvent: Called when the denied UUID list is modified for a plot.
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was denied/un-denied
* @param added true of add to deny list, false if removed
*/
public PlayerPlotDeniedEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a user was added.
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The player added/removed.
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action.
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,70 +1,69 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
/**
*/
public class PlayerPlotHelperEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotHelperEvent: Called when a plot helper is added/removed
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was added/removed from the helper list
* @param added true of the player was added, false if the player was removed
*/
public PlayerPlotHelperEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a player was added
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The UUID added/removed
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
/**
*/
public class PlayerPlotHelperEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotHelperEvent: Called when a plot helper is added/removed
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was added/removed from the helper list
* @param added true of the player was added, false if the player was removed
*/
public PlayerPlotHelperEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a player was added
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The UUID added/removed
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,70 +1,69 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
/**
*/
public class PlayerPlotTrustedEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotTrustedEvent: Called when a plot trusted user is added/removed
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was added/removed from the trusted list
* @param added true of the player was added, false if the player was removed
*/
public PlayerPlotTrustedEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a player was added
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The UUID added/removed
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import java.util.UUID;
/**
*/
public class PlayerPlotTrustedEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final boolean added;
private final UUID player;
/**
* PlayerPlotTrustedEvent: Called when a plot trusted user is added/removed
*
* @param initiator Player that initiated the event
* @param plot Plot in which the event occurred
* @param player Player that was added/removed from the trusted list
* @param added true of the player was added, false if the player was removed
*/
public PlayerPlotTrustedEvent(Player initiator, Plot plot, UUID player, boolean added) {
super(plot);
this.initiator = initiator;
this.added = added;
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* If a player was added
*
* @return boolean
*/
public boolean wasAdded() {
return this.added;
}
/**
* The UUID added/removed
*
* @return UUID
*/
public UUID getPlayer() {
return this.player;
}
/**
* The player initiating the action
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,72 +1,66 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
* Called when a player teleports to a plot
*
*/
public class PlayerTeleportToPlotEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Location from;
private final Plot plot;
private boolean cancelled;
/**
* PlayerTeleportToPlotEvent: Called when a player teleports to a plot
*
* @param player That was teleported
* @param from Start location
* @param plot Plot to which the player was teleported
*/
public PlayerTeleportToPlotEvent(Player player, Location from, Plot plot) {
super(player);
this.from = from;
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
/**
* Get the from location
*
* @return Location
*/
public Location getFrom() {
return this.from;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
* Called when a player teleports to a plot
*/
public class PlayerTeleportToPlotEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Location from;
private final Plot plot;
private boolean cancelled;
/**
* PlayerTeleportToPlotEvent: Called when a player teleports to a plot
*
* @param player That was teleported
* @param from Start location
* @param plot Plot to which the player was teleported
*/
public PlayerTeleportToPlotEvent(Player player, Location from, Plot plot) {
super(player);
this.from = from;
this.plot = plot;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override public HandlerList getHandlers() {
return handlers;
}
/**
* Get the from location
*
* @return Location
*/
public Location getFrom() {
return this.from;
}
/**
* Get the plot involved
*
* @return Plot
*/
public Plot getPlot() {
return this.plot;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -0,0 +1,105 @@
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import java.util.UUID;
public class PlotChangeOwnerEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player initiator;
private final UUID newOwner;
private final UUID oldOwner;
private boolean hasOldOwner;
private boolean cancelled;
/**
* PlotChangeOwnerEvent: Called when a plot's owner is change.
*
* @param newOwner The new owner of the plot
* @param oldOwner The old owner of the plot
* @param plot The plot having its owner changed
*/
public PlotChangeOwnerEvent(Player initiator, Plot plot, UUID oldOwner, UUID newOwner,
boolean hasOldOwner) {
super(plot);
this.initiator = initiator;
this.newOwner = newOwner;
this.oldOwner = oldOwner;
this.hasOldOwner = hasOldOwner;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the PlotId.
*
* @return PlotId
*/
public PlotId getPlotId() {
return getPlot().getId();
}
/**
* Get the world name.
*
* @return String
*/
public String getWorld() {
return getPlot().getWorldName();
}
/**
* Get the change-owner initator
*
* @return Player
*/
public Player getInitiator() {
return this.initiator;
}
/**
* Get the old owner of the plot. Null if not exists.
*
* @return UUID
*/
public UUID getOldOwner() {
return this.oldOwner;
}
/**
* Get the new owner of the plot
*
* @return UUID
*/
public UUID getNewOwner() {
return this.newOwner;
}
/**
* Get if the plot had an old owner
*
* @return boolean
*/
public boolean hasOldOwner() {
return this.hasOldOwner;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,56 +1,53 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a plot is cleared
*
*/
public class PlotClearEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
public PlotClearEvent(Plot plot) {
super(plot);
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the PlotId.
*
* @return PlotId
*/
public PlotId getPlotId() {
return getPlot().getId();
}
/**
* Get the world name.
*
* @return String
*/
public String getWorld() {
return getPlot().getArea().worldname;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a plot is cleared
*/
public class PlotClearEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
public PlotClearEvent(Plot plot) {
super(plot);
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the PlotId.
*
* @return PlotId
*/
public PlotId getPlotId() {
return getPlot().getId();
}
/**
* Get the world name.
*
* @return String
*/
public String getWorld() {
return getPlot().getWorldName();
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,12 +1,11 @@
package com.plotsquared.bukkit.events;
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.event.HandlerList;
/**
* Called when a plot component is set
*
*/
public class PlotComponentSetEvent extends PlotEvent {
@ -37,7 +36,7 @@ public class PlotComponentSetEvent extends PlotEvent {
* @return String
*/
public String getWorld() {
return getPlot().getArea().worldname;
return getPlot().getWorldName();
}
/**
@ -49,8 +48,7 @@ public class PlotComponentSetEvent extends PlotEvent {
return this.component;
}
@Override
public HandlerList getHandlers() {
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,45 +1,43 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import org.bukkit.event.HandlerList;
/**
* Called when a plot is deleted
*
*/
public class PlotDeleteEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
public PlotDeleteEvent(Plot plot) {
super(plot);
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the PlotId
*
* @return PlotId
*/
public PlotId getPlotId() {
return getPlot().getId();
}
/**
* Get the world name
*
* @return String
*/
public String getWorld() {
return getPlot().getArea().worldname;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.event.HandlerList;
/**
* Called when a plot is deleted
*/
public class PlotDeleteEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
public PlotDeleteEvent(Plot plot) {
super(plot);
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the PlotId
*
* @return PlotId
*/
public PlotId getPlotId() {
return getPlot().getId();
}
/**
* Get the world name
*
* @return String
*/
public String getWorld() {
return getPlot().getWorldName();
}
@Override public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,6 +1,6 @@
package com.plotsquared.bukkit.events;
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.event.Event;
public abstract class PlotEvent extends Event {

View File

@ -1,56 +1,52 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a Flag is added to a plot.
*
*/
public class PlotFlagAddEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Flag flag;
private boolean cancelled;
/**
* PlotFlagAddEvent: Called when a Flag is added to a plot.
*
* @param flag Flag that was added
* @param plot Plot to which the flag was added
*/
public PlotFlagAddEvent(Flag flag, Plot plot) {
super(plot);
this.flag = flag;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the flag involved.
*
* @return Flag
*/
public Flag getFlag() {
return this.flag;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public final boolean isCancelled() {
return this.cancelled;
}
@Override
public final void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a Flag is added to a plot.
*/
public class PlotFlagAddEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Flag flag;
private boolean cancelled;
/**
* PlotFlagAddEvent: Called when a Flag is added to a plot.
*
* @param flag Flag that was added
* @param plot Plot to which the flag was added
*/
public PlotFlagAddEvent(Flag flag, Plot plot) {
super(plot);
this.flag = flag;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the flag involved.
*
* @return Flag
*/
public Flag getFlag() {
return this.flag;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public final boolean isCancelled() {
return this.cancelled;
}
@Override public final void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -1,56 +1,52 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.object.Plot;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a flag is removed from a plot
*
*/
public class PlotFlagRemoveEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Flag flag;
private boolean cancelled;
/**
* PlotFlagRemoveEvent: Called when a flag is removed from a plot
*
* @param flag Flag that was removed
* @param plot Plot from which the flag was removed
*/
public PlotFlagRemoveEvent(Flag flag, Plot plot) {
super(plot);
this.flag = flag;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the flag involved
*
* @return Flag
*/
public Flag getFlag() {
return this.flag;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public final boolean isCancelled() {
return this.cancelled;
}
@Override
public final void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
/**
* Called when a flag is removed from a plot
*/
public class PlotFlagRemoveEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Flag flag;
private boolean cancelled;
/**
* PlotFlagRemoveEvent: Called when a flag is removed from a plot
*
* @param flag Flag that was removed
* @param plot Plot from which the flag was removed
*/
public PlotFlagRemoveEvent(Flag flag, Plot plot) {
super(plot);
this.flag = flag;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the flag involved
*
* @return Flag
*/
public Flag getFlag() {
return this.flag;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public final boolean isCancelled() {
return this.cancelled;
}
@Override public final void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -1,62 +1,59 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import org.bukkit.World;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import java.util.ArrayList;
public class PlotMergeEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final ArrayList<PlotId> plots;
private final World world;
private boolean cancelled;
/**
* PlotMergeEvent: Called when plots are merged
*
* @param world World in which the event occurred
* @param plot Plot that was merged
* @param plots A list of plots involved in the event
*/
public PlotMergeEvent(World world, Plot plot, ArrayList<PlotId> plots) {
super(plot);
this.world = world;
this.plots = plots;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plots being added.
*
* @return Plot
*/
public ArrayList<PlotId> getPlots() {
return this.plots;
}
public World getWorld() {
return this.world;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.World;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import java.util.ArrayList;
public class PlotMergeEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final ArrayList<PlotId> plots;
private final World world;
private boolean cancelled;
/**
* PlotMergeEvent: Called when plots are merged
*
* @param world World in which the event occurred
* @param plot Plot that was merged
* @param plots A list of plots involved in the event
*/
public PlotMergeEvent(World world, Plot plot, ArrayList<PlotId> plots) {
super(plot);
this.world = world;
this.plots = plots;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plots being added.
*
* @return Plot
*/
public ArrayList<PlotId> getPlots() {
return this.plots;
}
public World getWorld() {
return this.world;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,41 +1,49 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.Rating;
import org.bukkit.event.HandlerList;
public class PlotRateEvent extends PlotEvent {
private static final HandlerList handlers = new HandlerList();
private final PlotPlayer rater;
private Rating rating;
public PlotRateEvent(PlotPlayer rater, Rating rating, Plot plot) {
super(plot);
this.rater = rater;
this.rating = rating;
}
public static HandlerList getHandlerList() {
return handlers;
}
public PlotPlayer getRater() {
return this.rater;
}
public Rating getRating() {
return this.rating;
}
public void setRating(Rating rating) {
this.rating = rating;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.Rating;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
public class PlotRateEvent extends PlotEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final PlotPlayer rater;
private Rating rating;
private boolean cancelled = false;
public PlotRateEvent(PlotPlayer rater, Rating rating, Plot plot) {
super(plot);
this.rater = rater;
this.rating = rating;
}
public static HandlerList getHandlerList() {
return handlers;
}
public PlotPlayer getRater() {
return this.rater;
}
public Rating getRating() {
return this.rating;
}
public void setRating(Rating rating) {
this.rating = rating;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -1,67 +1,64 @@
package com.plotsquared.bukkit.events;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import org.bukkit.World;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.ArrayList;
public class PlotUnlinkEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final ArrayList<PlotId> plots;
private final World world;
private final PlotArea area;
private boolean cancelled;
/**
* Called when a mega-plot is unlinked.
*
* @param world World in which the event occurred
* @param plots Plots that are involved in the event
*/
public PlotUnlinkEvent(World world, PlotArea area, ArrayList<PlotId> plots) {
this.plots = plots;
this.world = world;
this.area = area;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plots involved.
*
* @return The {@link PlotId}'s of the plots involved
*/
public ArrayList<PlotId> getPlots() {
return this.plots;
}
public World getWorld() {
return this.world;
}
public PlotArea getArea() {
return this.area;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public void setCancelled(boolean b) {
this.cancelled = b;
}
}
package com.github.intellectualsites.plotsquared.bukkit.events;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.PlotId;
import org.bukkit.World;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.ArrayList;
public class PlotUnlinkEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final ArrayList<PlotId> plots;
private final World world;
private final PlotArea area;
private boolean cancelled;
/**
* Called when a mega-plot is unlinked.
*
* @param world World in which the event occurred
* @param plots Plots that are involved in the event
*/
public PlotUnlinkEvent(World world, PlotArea area, ArrayList<PlotId> plots) {
this.plots = plots;
this.world = world;
this.area = area;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Get the plots involved.
*
* @return The {@link PlotId}'s of the plots involved
*/
public ArrayList<PlotId> getPlots() {
return this.plots;
}
public World getWorld() {
return this.world;
}
public PlotArea getArea() {
return this.area;
}
@Override public HandlerList getHandlers() {
return handlers;
}
@Override public boolean isCancelled() {
return this.cancelled;
}
@Override public void setCancelled(boolean b) {
this.cancelled = b;
}
}

View File

@ -1,6 +1,6 @@
package com.plotsquared.bukkit.generator;
package com.github.intellectualsites.plotsquared.bukkit.generator;
import com.intellectualcrafters.plot.generator.AugmentedUtils;
import com.github.intellectualsites.plotsquared.plot.generator.AugmentedUtils;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
@ -8,7 +8,7 @@ import org.bukkit.generator.BlockPopulator;
import java.util.Random;
public class BukkitAugmentedGenerator extends BlockPopulator {
private static BukkitAugmentedGenerator generator;
public static BukkitAugmentedGenerator get(World world) {
@ -24,8 +24,7 @@ public class BukkitAugmentedGenerator extends BlockPopulator {
return generator;
}
@Override
public void populate(World world, Random r, Chunk chunk) {
@Override public void populate(World world, Random r, Chunk chunk) {
AugmentedUtils.generate(world.getName(), chunk.getX(), chunk.getZ(), null);
}
}

View File

@ -1,45 +1,35 @@
package com.plotsquared.bukkit.generator;
package com.github.intellectualsites.plotsquared.bukkit.generator;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.block.GenChunk;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Set;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.bukkit.util.block.GenChunk;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SingleWorldGenerator;
import com.github.intellectualsites.plotsquared.plot.util.ChunkManager;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.MathMan;
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
import java.util.*;
public class BukkitPlotGenerator extends ChunkGenerator
implements GeneratorWrapper<ChunkGenerator> {
private final GenChunk chunkSetter;
private final PseudoRandom random = new PseudoRandom();
private final IndependentPlotGenerator plotGenerator;
private final List<BlockPopulator> populators = new ArrayList<>();
private final ChunkGenerator platformGenerator;
private final boolean full;
private final HashMap<ChunkLoc, byte[][]> dataMap = new HashMap<>();
private List<BlockPopulator> populators;
private boolean loaded = false;
public BukkitPlotGenerator(IndependentPlotGenerator generator) {
@ -48,51 +38,19 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
}
this.plotGenerator = generator;
this.platformGenerator = this;
populators = new ArrayList<>();
this.populators.add(new BlockPopulator() {
private LocalBlockQueue queue;
@Override
public void populate(World world, Random r, Chunk c) {
@Override public void populate(World world, Random r, Chunk c) {
if (queue == null) {
queue = GlobalBlockQueue.IMP.getNewQueue(world.getName(), false);
}
ChunkLoc loc = new ChunkLoc(c.getX(), c.getZ());
byte[][] resultData;
if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) {
GenChunk result = BukkitPlotGenerator.this.chunkSetter;
// Set the chunk location
result.setChunk(c);
// Set the result data
result.result = new short[16][];
result.result_data = new byte[16][];
result.grid = null;
result.cd = null;
// Catch any exceptions (as exceptions usually thrown)
generate(world, loc.x, loc.z, result);
resultData = result.result_data;
} else {
resultData = BukkitPlotGenerator.this.dataMap.remove(loc);
}
if (resultData != null) {
for (int i = 0; i < resultData.length; i++) {
byte[] section = resultData[i];
if (section == null) {
continue;
}
for (int j = 0; j < section.length; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
c.getBlock(x, y, z).setData(section[j]);
}
}
}
BukkitPlotGenerator.this.random.state = c.getX() << 16 | c.getZ() & 0xFFFF;
PlotArea area = PS.get().getPlotArea(world.getName(), null);
PlotArea area = PlotSquared.get().getPlotArea(world.getName(), null);
ChunkWrapper wrap = new ChunkWrapper(area.worldname, c.getX(), c.getZ());
ScopedLocalBlockQueue chunk = queue.getForChunk(wrap.x, wrap.z);
if (BukkitPlotGenerator.this.plotGenerator.populateChunk(chunk, area, BukkitPlotGenerator.this.random)) {
if (BukkitPlotGenerator.this.plotGenerator.populateChunk(chunk, area)) {
queue.flush();
}
}
@ -101,51 +59,49 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
this.full = true;
MainUtil.initCache();
}
public BukkitPlotGenerator(final String world, final ChunkGenerator cg) {
if (cg instanceof BukkitPlotGenerator) {
throw new IllegalArgumentException("ChunkGenerator: " + cg.getClass().getName() + " is already a BukkitPlotGenerator!");
throw new IllegalArgumentException("ChunkGenerator: " + cg.getClass().getName()
+ " is already a BukkitPlotGenerator!");
}
this.full = false;
PS.debug("BukkitPlotGenerator does not fully support: " + cg);
PlotSquared.debug("BukkitPlotGenerator does not fully support: " + cg);
this.platformGenerator = cg;
this.plotGenerator = new IndependentPlotGenerator() {
@Override
public void processSetup(SetupObject setup) {}
@Override
public void initialize(PlotArea area) {}
@Override
public PlotManager getNewPlotManager() {
return new HybridGen().getNewPlotManager();
@Override public void processSetup(SetupObject setup) {
}
@Override
public String getName() {
@Override public void initialize(PlotArea area) {
}
@Override public PlotManager getNewPlotManager() {
return PlotSquared.get().IMP.getDefaultGenerator().getNewPlotManager();
}
@Override public String getName() {
return cg.getClass().getName();
}
@Override
public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) {
return new HybridGen().getNewPlotArea(world, id, min, max);
return PlotSquared.get().IMP.getDefaultGenerator()
.getNewPlotArea(world, id, min, max);
}
@Override
public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings) {
World w = BukkitUtil.getWorld(world);
Location min = result.getMin();
int cx = min.getX() >> 4;
int cz = min.getZ() >> 4;
Random r = new Random(MathMan.pair((short) cx, (short) cz));
BiomeGrid grid = new BiomeGrid() {
@Override
public void setBiome(int x, int z, Biome biome) {
@Override public void setBiome(int x, int z, Biome biome) {
result.setBiome(x, z, biome.name());
}
@Override
public Biome getBiome(int arg0, int arg1) {
@Override public Biome getBiome(int arg0, int arg1) {
return Biome.FOREST;
}
};
@ -155,7 +111,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
if (data != null) {
return;
}
} catch (Throwable ignored) {}
} catch (Throwable ignored) {
}
/* TODO: Redo this
// Populator spillage
short[][] tmp = cg.generateExtBlockSections(w, r, cx, cz, grid);
if (tmp != null) {
@ -166,7 +124,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = i << 4; y < (i << 4) + 16; y++) {
result.setBlock(x, y, z, (short) 0, (byte) 0);
result.setBlock(x, y, z, PlotBlock.get("air"));
}
}
}
@ -181,45 +139,38 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
}
}
}
*/
for (BlockPopulator populator : cg.getDefaultPopulators(w)) {
populator.populate(w, r, w.getChunkAt(cx, cz));
}
}
};
this.chunkSetter = new GenChunk(null, new ChunkWrapper(world, 0, 0));
if (cg != null) {
this.populators.addAll(cg.getDefaultPopulators(BukkitUtil.getWorld(world)));
}
MainUtil.initCache();
}
@Override
public void augment(PlotArea area) {
@Override public void augment(PlotArea area) {
BukkitAugmentedGenerator.get(BukkitUtil.getWorld(area.worldname));
}
@Override
public boolean isFull() {
@Override public boolean isFull() {
return this.full;
}
@Override
public IndependentPlotGenerator getPlotGenerator() {
@Override public IndependentPlotGenerator getPlotGenerator() {
return this.plotGenerator;
}
@Override
public ChunkGenerator getPlatformGenerator() {
@Override public ChunkGenerator getPlatformGenerator() {
return this.platformGenerator;
}
@Override
public List<BlockPopulator> getDefaultPopulators(World world) {
@Override public List<BlockPopulator> getDefaultPopulators(World world) {
try {
if (!this.loaded) {
String name = world.getName();
PS.get().loadWorld(name, this);
Set<PlotArea> areas = PS.get().getPlotAreas(name);
PlotSquared.get().loadWorld(name, this);
Set<PlotArea> areas = PlotSquared.get().getPlotAreas(name);
if (!areas.isEmpty()) {
PlotArea area = areas.iterator().next();
if (!area.MOB_SPAWNING) {
@ -245,6 +196,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
}
ArrayList<BlockPopulator> toAdd = new ArrayList<>();
List<BlockPopulator> existing = world.getPopulators();
if (populators == null && platformGenerator != null) {
populators = new ArrayList<>(platformGenerator.getDefaultPopulators(world));
}
for (BlockPopulator populator : this.populators) {
if (!existing.contains(populator)) {
toAdd.add(populator);
@ -255,71 +209,89 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
@Override
public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) {
GenChunk result = (GenChunk) this.chunkSetter;
GenChunk result = this.chunkSetter;
if (this.getPlotGenerator() instanceof SingleWorldGenerator) {
if (result.getCd() != null) {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
grid.setBiome(x, z, Biome.PLAINS);
}
}
return result.getCd();
}
}
// Set the chunk location
result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
// Set the result data
result.cd = createChunkData(world);
result.setCd(createChunkData(world));
result.grid = grid;
result.result = null;
result.result_data = null;
result.result = generateExtBlockSections(world, random, cx, cz, grid);
// Catch any exceptions (as exceptions usually thrown)
try {
// Fill the result data if necessary
if (this.platformGenerator != this) {
return this.platformGenerator.generateChunkData(world, random, cx, cz, grid);
} else {
generate(world, cx, cz, result);
generate(world, result);
}
} catch (Throwable e) {
e.printStackTrace();
}
// Return the result data
return result.cd;
return result.getCd();
}
public void generate(World world, int cx, int cz, ScopedLocalBlockQueue result) {
private void generate(World world, ScopedLocalBlockQueue result) {
// Load if improperly loaded
if (!this.loaded) {
String name = world.getName();
PS.get().loadWorld(name, this);
PlotSquared.get().loadWorld(name, this);
this.loaded = true;
}
// Set random seed
this.random.state = cx << 16 | cz & 0xFFFF;
// Process the chunk
if (ChunkManager.preProcessChunk(result)) {
return;
}
PlotArea area = PS.get().getPlotArea(world.getName(), null);
PlotArea area = PlotSquared.get().getPlotArea(world.getName(), null);
try {
this.plotGenerator.generateChunk(this.chunkSetter, area, this.random);
this.plotGenerator.generateChunk(this.chunkSetter, area);
} catch (Throwable e) {
// Recover from generator error
e.printStackTrace();
}
ChunkManager.postProcessChunk(result);
}
@Override
public short[][] generateExtBlockSections(World world, Random r, int cx, int cz, BiomeGrid grid) {
GenChunk result = (GenChunk) this.chunkSetter;
public PlotBlock[][] generateExtBlockSections(World world, Random r, int cx, int cz,
BiomeGrid grid) {
GenChunk result = this.chunkSetter;
// Set the chunk location
result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
// Set the result data
result.result = new short[16][];
result.result_data = new byte[16][];
result.result = new PlotBlock[16][];
result.grid = grid;
result.cd = null;
// Catch any exceptions (as exceptions usually thrown)
try {
// Fill the result data
if (this.platformGenerator != this) {
return this.platformGenerator.generateExtBlockSections(world, r, cx, cz, grid);
final ChunkData chunkData =
this.platformGenerator.generateChunkData(world, r, cx, cz, grid);
final PlotBlock[][] blocks = new PlotBlock[world.getMaxHeight() / 16][];
// section ID = Y >> 4
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < world.getMaxHeight(); y++) {
if (blocks[y >> 4] == null) {
blocks[y >> 4] = new PlotBlock[4096];
}
blocks[y >> 4][((y & 0xF) << 8) | (z << 4) | x] =
PlotBlock.get(chunkData.getType(x, y, z));
}
}
}
} else {
generate(world, cx, cz, result);
this.dataMap.put(new ChunkLoc(cx, cz), result.result_data);
generate(world, result);
}
} catch (Throwable e) {
e.printStackTrace();
@ -327,21 +299,21 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
// Return the result data
return result.result;
}
/**
* Allow spawning everywhere.
*
* @param world Ignored
* @param x Ignored
* @param z Ignored
* @param x Ignored
* @param z Ignored
* @return always true
*/
@Override
public boolean canSpawn(World world, int x, int z) {
@Override public boolean canSpawn(World world, int x, int z) {
return true;
}
@Override
public String toString() {
@Override public String toString() {
if (this.platformGenerator == this) {
return this.plotGenerator.getName();
}
@ -351,9 +323,8 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
return this.platformGenerator.getClass().getName();
}
}
@Override
public boolean equals(Object obj) {
@Override public boolean equals(Object obj) {
if (obj == null) {
return false;
}

View File

@ -1,15 +1,14 @@
package com.plotsquared.bukkit.listeners;
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefClass;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefField;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefMethod;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
@ -31,13 +30,15 @@ import org.bukkit.event.world.ChunkUnloadEvent;
import java.lang.reflect.Method;
import java.util.HashSet;
public class ChunkListener implements Listener {
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass;
@SuppressWarnings("unused") public class ChunkListener implements Listener {
private RefMethod methodGetHandleChunk;
private RefField mustSave;
private Chunk lastChunk;
private boolean ignoreUnload = false;
public ChunkListener() {
if (Settings.Chunk_Processor.AUTO_TRIM) {
try {
@ -46,7 +47,8 @@ public class ChunkListener implements Listener {
this.mustSave = classChunk.getField("mustSave");
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
} catch (Throwable ignored) {
PS.debug("PlotSquared/Server not compatible for chunk processor trim/gc");
PlotSquared.debug(PlotSquared.imp().getPluginName()
+ "/Server not compatible for chunk processor trim/gc");
Settings.Chunk_Processor.AUTO_TRIM = false;
}
}
@ -57,21 +59,23 @@ public class ChunkListener implements Listener {
world.setAutoSave(false);
}
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
@Override public void run() {
try {
HashSet<Chunk> toUnload = new HashSet<>();
for (World world : Bukkit.getWorlds()) {
String worldName = world.getName();
if (!PS.get().hasPlotArea(worldName)) {
if (!PlotSquared.get().hasPlotArea(worldName)) {
continue;
}
Object w = world.getClass().getDeclaredMethod("getHandle").invoke(world);
Object chunkMap = w.getClass().getDeclaredMethod("getPlayerChunkMap").invoke(w);
Method methodIsChunkInUse = chunkMap.getClass().getDeclaredMethod("isChunkInUse", int.class, int.class);
Object chunkMap =
w.getClass().getDeclaredMethod("getPlayerChunkMap").invoke(w);
Method methodIsChunkInUse = chunkMap.getClass()
.getDeclaredMethod("isChunkInUse", int.class, int.class);
Chunk[] chunks = world.getLoadedChunks();
for (Chunk chunk : chunks) {
if ((boolean) methodIsChunkInUse.invoke(chunkMap, chunk.getX(), chunk.getZ())) {
if ((boolean) methodIsChunkInUse
.invoke(chunkMap, chunk.getX(), chunk.getZ())) {
continue;
}
int x = chunk.getX();
@ -105,9 +109,14 @@ public class ChunkListener implements Listener {
return false;
}
Object c = this.methodGetHandleChunk.of(chunk).call();
this.mustSave.of(c).set(false);
if (chunk.isLoaded()) {
chunk.unload(false, false);
RefField.RefExecutor field = this.mustSave.of(c);
if ((Boolean) field.get() == true) {
field.set(false);
if (chunk.isLoaded()) {
ignoreUnload = true;
chunk.unload(false, false);
ignoreUnload = false;
}
}
return true;
}
@ -137,12 +146,14 @@ public class ChunkListener implements Listener {
return plot != null && plot.hasOwner();
}
@EventHandler
public void onChunkUnload(ChunkUnloadEvent event) {
@EventHandler public void onChunkUnload(ChunkUnloadEvent event) {
if (ignoreUnload) {
return;
}
if (Settings.Chunk_Processor.AUTO_TRIM) {
Chunk chunk = event.getChunk();
String world = chunk.getWorld().getName();
if (PS.get().hasPlotArea(world)) {
if (PlotSquared.get().hasPlotArea(world)) {
if (unloadChunk(world, chunk, true)) {
return;
}
@ -152,14 +163,12 @@ public class ChunkListener implements Listener {
event.setCancelled(true);
}
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
@EventHandler public void onChunkLoad(ChunkLoadEvent event) {
processChunk(event.getChunk(), false);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onItemSpawn(ItemSpawnEvent event) {
@EventHandler(priority = EventPriority.LOWEST) public void onItemSpawn(ItemSpawnEvent event) {
Item entity = event.getEntity();
Chunk chunk = entity.getLocation().getChunk();
if (chunk == this.lastChunk) {
@ -167,7 +176,7 @@ public class ChunkListener implements Listener {
event.setCancelled(true);
return;
}
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
if (!PlotSquared.get().hasPlotArea(chunk.getWorld().getName())) {
return;
}
Entity[] entities = chunk.getEntities();
@ -179,14 +188,14 @@ public class ChunkListener implements Listener {
this.lastChunk = null;
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockPhysics(BlockPhysicsEvent event) {
if (Settings.Chunk_Processor.DISABLE_PHYSICS) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onEntitySpawn(CreatureSpawnEvent event) {
LivingEntity entity = event.getEntity();
@ -196,7 +205,7 @@ public class ChunkListener implements Listener {
event.setCancelled(true);
return;
}
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
if (!PlotSquared.get().hasPlotArea(chunk.getWorld().getName())) {
return;
}
Entity[] entities = chunk.getEntities();
@ -213,12 +222,12 @@ public class ChunkListener implements Listener {
TaskManager.index.incrementAndGet();
final Integer currentIndex = TaskManager.index.get();
Integer task = TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
@Override public void run() {
if (!chunk.isLoaded()) {
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
TaskManager.tasks.remove(currentIndex);
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
PlotSquared
.debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!");
chunk.unload(true, true);
return;
}
@ -226,7 +235,8 @@ public class ChunkListener implements Listener {
if (tiles.length == 0) {
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
TaskManager.tasks.remove(currentIndex);
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
PlotSquared
.debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!");
chunk.unload(true, true);
return;
}
@ -236,7 +246,8 @@ public class ChunkListener implements Listener {
if (i >= tiles.length) {
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
TaskManager.tasks.remove(currentIndex);
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
PlotSquared
.debug(C.PREFIX.s() + "&aSuccessfully processed and unloaded chunk!");
chunk.unload(true, true);
return;
}
@ -249,7 +260,7 @@ public class ChunkListener implements Listener {
}
public boolean processChunk(Chunk chunk, boolean unload) {
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
if (!PlotSquared.get().hasPlotArea(chunk.getWorld().getName())) {
return false;
}
Entity[] entities = chunk.getEntities();
@ -260,11 +271,15 @@ public class ChunkListener implements Listener {
ent.remove();
}
}
PS.debug("[PlotSquared] &a detected unsafe chunk and processed: " + (chunk.getX() << 4) + "," + (chunk.getX() << 4));
PlotSquared.debug(
C.PREFIX.s() + "&a detected unsafe chunk and processed: " + (chunk.getX() << 4)
+ "," + (chunk.getX() << 4));
}
if (tiles.length > Settings.Chunk_Processor.MAX_TILES) {
if (unload) {
PS.debug("[PlotSquared] &c detected unsafe chunk: " + (chunk.getX() << 4) + "," + (chunk.getX() << 4));
PlotSquared.debug(
C.PREFIX.s() + "&c detected unsafe chunk: " + (chunk.getX() << 4) + "," + (
chunk.getX() << 4));
cleanChunk(chunk);
return true;
}

View File

@ -0,0 +1,142 @@
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import org.bukkit.World;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.entity.EntityTeleportEvent;
import org.bukkit.event.vehicle.*;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import java.util.List;
@SuppressWarnings("unused") public class EntitySpawnListener implements Listener {
private static boolean ignoreTP = false;
public static void test(Entity entity) {
List<MetadataValue> meta = entity.getMetadata("plotworld");
World world = entity.getLocation().getWorld();
if (meta == null || meta.isEmpty()) {
if (PlotSquared.get().hasPlotArea(world.getName())) {
entity.setMetadata("plotworld",
new FixedMetadataValue((Plugin) PlotSquared.get().IMP, entity.getLocation()));
}
} else {
org.bukkit.Location origin = (org.bukkit.Location) meta.get(0).value();
World originWorld = origin.getWorld();
if (!originWorld.equals(world)) {
if (!ignoreTP) {
if (!world.getName().equalsIgnoreCase(originWorld + "_the_end")) {
try {
ignoreTP = true;
entity.teleport(origin);
} finally {
ignoreTP = false;
}
if (entity.getLocation().getWorld().equals(world)) {
entity.remove();
}
}
} else {
entity.remove();
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void creatureSpawnEvent(EntitySpawnEvent event) {
Entity entity = event.getEntity();
Location location = BukkitUtil.getLocation(entity.getLocation());
PlotArea area = location.getPlotArea();
if (area == null) {
return;
}
Plot plot = area.getOwnedPlotAbs(location);
if (plot == null) {
if (!area.MOB_SPAWNING) {
EntityType type = entity.getType();
switch (type) {
case DROPPED_ITEM:
if (Settings.Enabled_Components.KILL_ROAD_ITEMS) {
break;
}
case PLAYER:
return;
}
if (type.isAlive() || !area.MISC_SPAWN_UNOWNED) {
event.setCancelled(true);
}
}
return;
}
if (Settings.Done.RESTRICT_BUILDING && plot.hasFlag(Flags.DONE)) {
event.setCancelled(true);
}
switch (entity.getType()) {
case ENDER_CRYSTAL:
if (PlayerEvents.checkEntity(entity, plot)) {
event.setCancelled(true);
}
case SHULKER:
if (!entity.hasMetadata("plot")) {
entity.setMetadata("plot",
new FixedMetadataValue((Plugin) PlotSquared.get().IMP, plot.getId()));
}
}
}
@EventHandler public void onVehicle(VehicleUpdateEvent event) {
test(event.getVehicle());
}
@EventHandler public void onVehicle(VehicleDestroyEvent event) {
test(event.getVehicle());
}
@EventHandler public void onVehicle(VehicleEntityCollisionEvent event) {
test(event.getVehicle());
}
@EventHandler public void onVehicle(VehicleCreateEvent event) {
test(event.getVehicle());
}
@EventHandler public void onVehicle(VehicleBlockCollisionEvent event) {
test(event.getVehicle());
}
@EventHandler public void onTeleport(EntityTeleportEvent event) {
Entity ent = event.getEntity();
if (ent instanceof Vehicle || ent instanceof ArmorStand)
test(event.getEntity());
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void vehicleMove(VehicleMoveEvent event) throws IllegalAccessException {
test(event.getVehicle());
}
@EventHandler public void spawn(CreatureSpawnEvent event) {
switch (event.getEntityType()) {
case ARMOR_STAND:
test(event.getEntity());
}
}
}

View File

@ -1,100 +1,104 @@
package com.plotsquared.bukkit.listeners;
import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.bukkit.object.BukkitPlayer;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.util.Vector;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class ForceFieldListener implements Listener {
private static Set<PlotPlayer> getNearbyPlayers(Player player, Plot plot) {
Set<PlotPlayer> players = new HashSet<>();
for (Entity entity : player.getNearbyEntities(5d, 5d, 5d)) {
PlotPlayer plotPlayer;
if (!(entity instanceof Player) || ((plotPlayer = BukkitUtil.getPlayer((Player) entity)) == null) || !plot.equals(plotPlayer.getCurrentPlot())) {
continue;
}
if (!plot.isAdded(plotPlayer.getUUID())) {
players.add(plotPlayer);
}
}
return players;
}
private static PlotPlayer hasNearbyPermitted(Player player, Plot plot) {
for (Entity entity : player.getNearbyEntities(5d, 5d, 5d)) {
if (!(entity instanceof Player)) {
continue;
}
PlotPlayer plotPlayer;
if ((plotPlayer = BukkitUtil.getPlayer((Player) entity)) == null) {
continue;
}
if (!plot.equals(plotPlayer.getCurrentPlot())) {
continue;
}
if (plot.isAdded(plotPlayer.getUUID())) {
return plotPlayer;
}
}
return null;
}
private static Vector calculateVelocity(PlotPlayer player, PlotPlayer e) {
Location playerLocation = player.getLocationFull();
Location oPlayerLocation = e.getLocation();
double playerX = playerLocation.getX();
double playerY = playerLocation.getY();
double playerZ = playerLocation.getZ();
double oPlayerX = oPlayerLocation.getX();
double oPlayerY = oPlayerLocation.getY();
double oPlayerZ = oPlayerLocation.getZ();
double x = 0d;
if (playerX < oPlayerX) {
x = 1.0d;
} else if (playerX > oPlayerX) {
x = -1.0d;
}
double y = 0d;
if (playerY < oPlayerY) {
y = 0.5d;
} else if (playerY > oPlayerY) {
y = -0.5d;
}
double z = 0d;
if (playerZ < oPlayerZ) {
z = 1.0d;
} else if (playerZ > oPlayerZ) {
z = -1.0d;
}
return new Vector(x, y, z);
}
public static void handleForcefield(Player player, PlotPlayer plotPlayer, Plot plot) {
if (Flags.FORCEFIELD.isTrue(plot)) {
UUID uuid = plotPlayer.getUUID();
if (plot.isAdded(uuid)) {
Set<PlotPlayer> players = getNearbyPlayers(player, plot);
for (PlotPlayer oPlayer : players) {
((BukkitPlayer) oPlayer).player.setVelocity(calculateVelocity(plotPlayer, oPlayer));
}
} else {
PlotPlayer oPlayer = hasNearbyPermitted(player, plot);
if (oPlayer == null) {
return;
}
player.setVelocity(calculateVelocity(oPlayer, plotPlayer));
}
}
}
}
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.Permissions;
import com.google.common.collect.Iterables;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@SuppressWarnings("unused") public class ForceFieldListener {
private static Set<PlotPlayer> getNearbyPlayers(Player player, Plot plot) {
Set<PlotPlayer> players = new HashSet<>();
for (Player nearPlayer : Iterables
.filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) {
PlotPlayer plotPlayer;
if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot
.equals(plotPlayer.getCurrentPlot())) {
continue;
}
if (!plot.isAdded(plotPlayer.getUUID())) {
players.add(plotPlayer);
}
}
return players;
}
private static PlotPlayer hasNearbyPermitted(Player player, Plot plot) {
for (Player nearPlayer : Iterables
.filter(player.getNearbyEntities(5d, 5d, 5d), Player.class)) {
PlotPlayer plotPlayer;
if ((plotPlayer = BukkitUtil.getPlayer(nearPlayer)) == null || !plot
.equals(plotPlayer.getCurrentPlot())) {
continue;
}
if (plot.isAdded(plotPlayer.getUUID())) {
return plotPlayer;
}
}
return null;
}
private static Vector calculateVelocity(PlotPlayer player, PlotPlayer e) {
Location playerLocation = player.getLocationFull();
Location oPlayerLocation = e.getLocation();
double playerX = playerLocation.getX();
double playerY = playerLocation.getY();
double playerZ = playerLocation.getZ();
double oPlayerX = oPlayerLocation.getX();
double oPlayerY = oPlayerLocation.getY();
double oPlayerZ = oPlayerLocation.getZ();
double x = 0d;
if (playerX < oPlayerX) {
x = 1.0d;
} else if (playerX > oPlayerX) {
x = -1.0d;
}
double y = 0d;
if (playerY < oPlayerY) {
y = 0.5d;
} else if (playerY > oPlayerY) {
y = -0.5d;
}
double z = 0d;
if (playerZ < oPlayerZ) {
z = 1.0d;
} else if (playerZ > oPlayerZ) {
z = -1.0d;
}
return new Vector(x, y, z);
}
public static void handleForcefield(Player player, PlotPlayer plotPlayer, Plot plot) {
if (Flags.FORCEFIELD.isTrue(plot)) {
UUID uuid = plotPlayer.getUUID();
if (plot.isAdded(uuid)) {
Set<PlotPlayer> players = getNearbyPlayers(player, plot);
for (PlotPlayer oPlayer : players) {
if (!Permissions.hasPermission(oPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) {
((BukkitPlayer) oPlayer).player
.setVelocity(calculateVelocity(plotPlayer, oPlayer));
}
}
} else {
PlotPlayer oPlayer = hasNearbyPermitted(player, plot);
if (oPlayer == null) {
return;
}
if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_ENTRY_FORCEFIELD)) {
player.setVelocity(calculateVelocity(oPlayer, plotPlayer));
}
}
}
}
}

View File

@ -1,21 +1,18 @@
package com.plotsquared.bukkit.listeners;
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import com.github.intellectualsites.plotsquared.bukkit.events.PlayerEnterPlotEvent;
import com.github.intellectualsites.plotsquared.bukkit.events.PlayerLeavePlotEvent;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.flag.Flags;
import com.github.intellectualsites.plotsquared.plot.listener.PlotListener;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.google.common.base.Optional;
import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.bukkit.events.PlayerEnterPlotEvent;
import com.plotsquared.bukkit.events.PlayerLeavePlotEvent;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.listener.PlotListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -23,23 +20,28 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class PlotPlusListener extends PlotListener implements Listener {
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.UUID;
private static final HashMap<String, Interval> feedRunnable = new HashMap<>();
private static final HashMap<String, Interval> healRunnable = new HashMap<>();
@SuppressWarnings("unused") public class PlotPlusListener extends PlotListener implements Listener {
private static final HashMap<UUID, Interval> feedRunnable = new HashMap<>();
private static final HashMap<UUID, Interval> healRunnable = new HashMap<>();
public static void startRunnable(JavaPlugin plugin) {
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
@Override
public void run() {
@Override public void run() {
if (!healRunnable.isEmpty()) {
for (Iterator<Entry<String, Interval>> iterator = healRunnable.entrySet().iterator(); iterator.hasNext(); ) {
Entry<String, Interval> entry = iterator.next();
for (Iterator<Entry<UUID, Interval>> iterator =
healRunnable.entrySet().iterator(); iterator.hasNext(); ) {
Entry<UUID, Interval> entry = iterator.next();
Interval value = entry.getValue();
++value.count;
if (value.count == value.interval) {
@ -57,8 +59,9 @@ public class PlotPlusListener extends PlotListener implements Listener {
}
}
if (!feedRunnable.isEmpty()) {
for (Iterator<Entry<String, Interval>> iterator = feedRunnable.entrySet().iterator(); iterator.hasNext(); ) {
Entry<String, Interval> entry = iterator.next();
for (Iterator<Entry<UUID, Interval>> iterator =
feedRunnable.entrySet().iterator(); iterator.hasNext(); ) {
Entry<UUID, Interval> entry = iterator.next();
Interval value = entry.getValue();
++value.count;
if (value.count == value.interval) {
@ -79,8 +82,7 @@ public class PlotPlusListener extends PlotListener implements Listener {
}, 0L, 20L);
}
@EventHandler(priority = EventPriority.HIGH)
public void onInteract(BlockDamageEvent event) {
@EventHandler(priority = EventPriority.HIGH) public void onInteract(BlockDamageEvent event) {
Player player = event.getPlayer();
if (player.getGameMode() != GameMode.SURVIVAL) {
return;
@ -98,9 +100,8 @@ public class PlotPlusListener extends PlotListener implements Listener {
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onDamage(EntityDamageEvent event) {
@EventHandler(priority = EventPriority.HIGH) public void onDamage(EntityDamageEvent event) {
if (event.getEntityType() != EntityType.PLAYER) {
return;
}
@ -113,23 +114,8 @@ public class PlotPlusListener extends PlotListener implements Listener {
event.setCancelled(true);
}
}
@EventHandler
public void onItemPickup(PlayerPickupItemEvent event) {
Player player = event.getPlayer();
PlotPlayer pp = BukkitUtil.getPlayer(player);
Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
if (plot == null) {
return;
}
UUID uuid = pp.getUUID();
if (plot.isAdded(uuid) && Flags.DROP_PROTECTION.isTrue(plot)) {
event.setCancelled(true);
}
}
@EventHandler
public void onItemDrop(PlayerDropItemEvent event) {
@EventHandler public void onItemDrop(PlayerDropItemEvent event) {
Player player = event.getPlayer();
PlotPlayer pp = BukkitUtil.getPlayer(player);
Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
@ -143,42 +129,53 @@ public class PlotPlusListener extends PlotListener implements Listener {
}
}
}
@EventHandler
public void onPlotEnter(PlayerEnterPlotEvent event) {
@EventHandler public void onPlotEnter(PlayerEnterPlotEvent event) {
Player player = event.getPlayer();
Plot plot = event.getPlot();
Optional<Integer[]> feed = plot.getFlag(Flags.FEED);
if (feed.isPresent()) {
Integer[] value = feed.get();
feedRunnable.put(player.getName(), new Interval(value[0], value[1], 20));
feedRunnable.put(player.getUniqueId(), new Interval(value[0], value[1], 20));
}
Optional<Integer[]> heal = plot.getFlag(Flags.HEAL);
if (heal.isPresent()) {
Integer[] value = heal.get();
healRunnable.put(player.getName(), new Interval(value[0], value[1], 20));
healRunnable.put(player.getUniqueId(), new Interval(value[0], value[1], 20));
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
@EventHandler public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
String name = player.getName();
feedRunnable.remove(name);
healRunnable.remove(name);
feedRunnable.remove(player.getUniqueId());
healRunnable.remove(player.getUniqueId());
}
@EventHandler
public void onPlotLeave(PlayerLeavePlotEvent event) {
@EventHandler public void onPlotLeave(PlayerLeavePlotEvent event) {
Player leaver = event.getPlayer();
Plot plot = event.getPlot();
if (!plot.hasOwner()) {
return;
}
BukkitUtil.getPlayer(leaver);
String name = leaver.getName();
feedRunnable.remove(name);
healRunnable.remove(name);
feedRunnable.remove(leaver.getUniqueId());
healRunnable.remove(leaver.getUniqueId());
}
@EventHandler public void onItemPickup(EntityPickupItemEvent event) {
LivingEntity ent = event.getEntity();
if (ent instanceof Player) {
Player player = (Player) ent;
PlotPlayer pp = BukkitUtil.getPlayer(player);
Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
if (plot == null) {
return;
}
UUID uuid = pp.getUUID();
if (!plot.isAdded(uuid) && Flags.DROP_PROTECTION.isTrue(plot)) {
event.setCancelled(true);
}
}
}
private static class Interval {

View File

@ -0,0 +1,106 @@
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass;
@SuppressWarnings("unused") public class SingleWorldListener implements Listener {
private Method methodGetHandleChunk;
private Field mustSave, done, lit, s;
public SingleWorldListener(Plugin plugin) throws Exception {
ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod();
this.mustSave = classChunk.getField("mustSave").getRealField();
try {
this.done = classChunk.getField("done").getRealField();
this.lit = classChunk.getField("lit").getRealField();
this.s = classChunk.getField("s").getRealField();
} catch (Throwable ignore) {
ignore.printStackTrace();
}
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public void markChunkAsClean(Chunk chunk) {
try {
Object nmsChunk = methodGetHandleChunk.invoke(chunk);
if (done != null)
this.done.set(nmsChunk, true);
if (mustSave != null)
this.mustSave.set(nmsChunk, false);
if (lit != null)
this.lit.set(nmsChunk, false);
if (s != null)
this.s.set(nmsChunk, false);
} catch (Throwable e) {
e.printStackTrace();
}
}
private void handle(ChunkEvent event) {
World world = event.getWorld();
String name = world.getName();
PlotAreaManager man = PlotSquared.get().getPlotAreaManager();
if (!(man instanceof SinglePlotAreaManager))
return;
if (!isPlotId(name))
return;
markChunkAsClean(event.getChunk());
}
// @EventHandler
// public void onPopulate(ChunkPopulateEvent event) {
// handle(event);
// }
@EventHandler(priority = EventPriority.LOWEST) public void onChunkLoad(ChunkLoadEvent event) {
handle(event);
}
private boolean isPlotId(String worldName) {
int len = worldName.length();
int separator = 0;
for (int i = 0; i < len; i++) {
switch (worldName.charAt(i)) {
case ',':
case ';':
separator++;
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
break;
default:
return false;
}
}
return separator == 1;
}
}

View File

@ -0,0 +1,36 @@
package com.github.intellectualsites.plotsquared.bukkit.listeners;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.ChunkGenerator;
@SuppressWarnings("unused") public class WorldEvents implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onWorldInit(WorldInitEvent event) {
World world = event.getWorld();
String name = world.getName();
PlotAreaManager manager = PlotSquared.get().getPlotAreaManager();
if (manager instanceof SinglePlotAreaManager) {
SinglePlotAreaManager single = (SinglePlotAreaManager) manager;
if (single.isWorld(name)) {
world.setKeepSpawnInMemory(false);
return;
}
}
ChunkGenerator gen = world.getGenerator();
if (gen instanceof GeneratorWrapper) {
PlotSquared.get().loadWorld(name, (GeneratorWrapper<?>) gen);
} else {
PlotSquared.get().loadWorld(name, new BukkitPlotGenerator(name, gen));
}
}
}

View File

@ -0,0 +1,25 @@
package com.github.intellectualsites.plotsquared.bukkit.object;
import com.github.intellectualsites.plotsquared.plot.object.LazyBlock;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.StringPlotBlock;
import org.bukkit.block.Block;
public class BukkitLazyBlock extends LazyBlock {
private StringPlotBlock pb;
public BukkitLazyBlock(Block block) {
this.pb = (StringPlotBlock) PlotBlock.get(block.getType().toString());
}
public BukkitLazyBlock(StringPlotBlock pb) {
this.pb = pb;
}
public StringPlotBlock getPlotBlock() {
return this.pb;
}
}

View File

@ -1,6 +1,6 @@
package com.plotsquared.bukkit.object;
package com.github.intellectualsites.plotsquared.bukkit.object;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
@ -19,23 +19,19 @@ public class BukkitOfflinePlayer implements OfflinePlotPlayer {
this.player = player;
}
@Override
public UUID getUUID() {
@Override public UUID getUUID() {
return this.player.getUniqueId();
}
@Override
public long getLastPlayed() {
@Override public long getLastPlayed() {
return this.player.getLastPlayed();
}
@Override
public boolean isOnline() {
@Override public boolean isOnline() {
return this.player.isOnline();
}
@Override
public String getName() {
@Override public String getName() {
return this.player.getName();
}
}

View File

@ -0,0 +1,282 @@
package com.github.intellectualsites.plotsquared.bukkit.object;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.*;
import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.RegisteredListener;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class BukkitPlayer extends PlotPlayer {
public final Player player;
public boolean offline;
private UUID uuid;
private String name;
/**
* <p>Please do not use this method. Instead use
* BukkitUtil.getPlayer(Player), as it caches player objects.</p>
*
* @param player
*/
public BukkitPlayer(Player player) {
this.player = player;
super.populatePersistentMetaMap();
}
public BukkitPlayer(Player player, boolean offline) {
this.player = player;
this.offline = offline;
super.populatePersistentMetaMap();
}
@Override public Location getLocation() {
Location location = super.getLocation();
return location == null ? BukkitUtil.getLocation(this.player) : location;
}
@Override public UUID getUUID() {
if (this.uuid == null) {
this.uuid = UUIDHandler.getUUID(this);
}
return this.uuid;
}
@Override public long getLastPlayed() {
return this.player.getLastPlayed();
}
@Override public boolean canTeleport(Location loc) {
org.bukkit.Location to = BukkitUtil.getLocation(loc);
org.bukkit.Location from = player.getLocation();
PlayerTeleportEvent event = new PlayerTeleportEvent(player, from, to);
callEvent(event);
if (event.isCancelled() || !event.getTo().equals(to)) {
return false;
}
event = new PlayerTeleportEvent(player, to, from);
callEvent(event);
return true;
}
private void callEvent(final Event event) {
RegisteredListener[] listeners = event.getHandlers().getRegisteredListeners();
for (RegisteredListener listener : listeners) {
if (listener.getPlugin().getName().equals(PlotSquared.imp().getPluginName())) {
continue;
}
try {
listener.callEvent(event);
} catch (EventException e) {
e.printStackTrace();
}
}
}
@Override public boolean hasPermission(String permission) {
if (this.offline && EconHandler.manager != null) {
return EconHandler.manager.hasPermission(getName(), permission);
}
return this.player.hasPermission(permission);
}
@Override public int hasPermissionRange(String stub, int range) {
if (hasPermission(C.PERMISSION_ADMIN.s())) {
return Integer.MAX_VALUE;
}
String[] nodes = stub.split("\\.");
StringBuilder n = new StringBuilder();
for (int i = 0; i < (nodes.length - 1); i++) {
n.append(nodes[i]).append(".");
if (!stub.equals(n + C.PERMISSION_STAR.s())) {
if (hasPermission(n + C.PERMISSION_STAR.s())) {
return Integer.MAX_VALUE;
}
}
}
if (hasPermission(stub + ".*")) {
return Integer.MAX_VALUE;
}
int max = 0;
String stubPlus = stub + ".";
Set<PermissionAttachmentInfo> effective = player.getEffectivePermissions();
if (!effective.isEmpty()) {
for (PermissionAttachmentInfo attach : effective) {
String perm = attach.getPermission();
if (perm.startsWith(stubPlus)) {
String end = perm.substring(stubPlus.length());
if (MathMan.isInteger(end)) {
int val = Integer.parseInt(end);
if (val > range)
return val;
if (val > max)
max = val;
}
}
}
} else {
for (int i = range; i > 0; i--) {
if (hasPermission(stub + "." + i)) {
return i;
}
}
}
return max;
}
@Override public boolean isPermissionSet(String permission) {
return this.player.isPermissionSet(permission);
}
@Override public void sendMessage(String message) {
if (!StringMan.isEqual(this.<String>getMeta("lastMessage"), message) || (
System.currentTimeMillis() - this.<Long>getMeta("lastMessageTime") > 5000)) {
setMeta("lastMessage", message);
setMeta("lastMessageTime", System.currentTimeMillis());
this.player.sendMessage(message);
}
}
@Override public void teleport(Location location) {
if (Math.abs(location.getX()) >= 30000000 || Math.abs(location.getZ()) >= 30000000) {
return;
}
this.player.teleport(
new org.bukkit.Location(BukkitUtil.getWorld(location.getWorld()), location.getX() + 0.5,
location.getY(), location.getZ() + 0.5, location.getYaw(), location.getPitch()),
TeleportCause.COMMAND);
}
@Override public String getName() {
if (this.name == null) {
this.name = this.player.getName();
}
return this.name;
}
@Override public boolean isOnline() {
return !this.offline && this.player.isOnline();
}
@Override public void setCompassTarget(Location location) {
this.player.setCompassTarget(
new org.bukkit.Location(BukkitUtil.getWorld(location.getWorld()), location.getX(),
location.getY(), location.getZ()));
}
@Override public Location getLocationFull() {
return BukkitUtil.getLocationFull(this.player);
}
@Override public void setWeather(PlotWeather weather) {
switch (weather) {
case CLEAR:
this.player.setPlayerWeather(WeatherType.CLEAR);
break;
case RAIN:
this.player.setPlayerWeather(WeatherType.DOWNFALL);
break;
case RESET:
this.player.resetPlayerWeather();
break;
default:
this.player.resetPlayerWeather();
break;
}
}
@Override public PlotGameMode getGameMode() {
switch (this.player.getGameMode()) {
case ADVENTURE:
return PlotGameMode.ADVENTURE;
case CREATIVE:
return PlotGameMode.CREATIVE;
case SPECTATOR:
return PlotGameMode.SPECTATOR;
case SURVIVAL:
return PlotGameMode.SURVIVAL;
default:
return PlotGameMode.NOT_SET;
}
}
@Override public void setGameMode(PlotGameMode gameMode) {
switch (gameMode) {
case ADVENTURE:
this.player.setGameMode(GameMode.ADVENTURE);
break;
case CREATIVE:
this.player.setGameMode(GameMode.CREATIVE);
break;
case SPECTATOR:
this.player.setGameMode(GameMode.SPECTATOR);
break;
case SURVIVAL:
this.player.setGameMode(GameMode.SURVIVAL);
break;
default:
this.player.setGameMode(GameMode.SURVIVAL);
break;
}
}
@Override public void setTime(long time) {
if (time != Long.MAX_VALUE) {
this.player.setPlayerTime(time, false);
} else {
this.player.resetPlayerTime();
}
}
@Override public boolean getFlight() {
return player.getAllowFlight();
}
@Override public void setFlight(boolean fly) {
this.player.setAllowFlight(fly);
}
@Override public void playMusic(Location location, PlotBlock id) {
if (PlotBlock.isEverything(id) || id.isAir()) {
// Let's just stop all the discs because why not?
for (final Sound sound : Arrays.stream(Sound.values()).filter(sound -> sound.name().contains("DISC")).collect(
Collectors.toList())) {
player.stopSound(sound);
}
// this.player.playEffect(BukkitUtil.getLocation(location), Effect.RECORD_PLAY, Material.AIR);
} else {
// this.player.playEffect(BukkitUtil.getLocation(location), Effect.RECORD_PLAY, id.to(Material.class));
this.player.playSound(BukkitUtil.getLocation(location), Sound.valueOf(id.to(Material.class).name()), Float.MAX_VALUE, 1f);
}
}
@Override public void kick(String message) {
this.player.kickPlayer(message);
}
@Override public void stopSpectating() {
if (getGameMode() == PlotGameMode.SPECTATOR) {
this.player.setSpectatorTarget(null);
}
}
@Override public boolean isBanned() {
return this.player.isBanned();
}
}

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
class AgeableStats {

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
class ArmorStandStats {

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
class EntityBaseStats {

View File

@ -0,0 +1,40 @@
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import lombok.Getter;
import lombok.NonNull;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@Getter public abstract class EntityWrapper {
protected final float yaw;
protected final float pitch;
private final Entity entity;
private final EntityType type;
public double x;
public double y;
public double z;
EntityWrapper(@NonNull final Entity entity) {
this.entity = entity;
this.type = entity.getType();
final Location location = entity.getLocation();
this.x = location.getX();
this.y = location.getY();
this.z = location.getZ();
this.yaw = location.getYaw();
this.pitch = location.getPitch();
}
@SuppressWarnings("deprecation") @Override public String toString() {
return String.format("[%s, x=%s, y=%s, z=%s]", type.getName(), x, y, z);
}
public abstract Entity spawn(World world, int xOffset, int zOffset);
public abstract void saveEntity();
}

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import org.bukkit.entity.Horse;

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;

View File

@ -1,51 +1,21 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import com.intellectualcrafters.plot.PS;
import org.bukkit.Art;
import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.Rotation;
import org.bukkit.TreeSpecies;
import org.bukkit.World;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import org.bukkit.*;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Bat;
import org.bukkit.entity.Boat;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Guardian;
import org.bukkit.entity.Horse;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Rabbit;
import org.bukkit.entity.Rabbit.Type;
import org.bukkit.entity.Sheep;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.Skeleton.SkeletonType;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.*;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
public class EntityWrapper {
public final class ReplicatingEntityWrapper extends EntityWrapper {
private final EntityType type;
private final float yaw;
private final float pitch;
private final short depth;
private final int hash;
private final EntityBaseStats base = new EntityBaseStats();
public double x;
public double y;
public double z;
public ItemStack[] inventory;
// Extended
private ItemStack stack;
@ -59,22 +29,18 @@ public class EntityWrapper {
private HorseStats horse;
private boolean noGravity;
public EntityWrapper(Entity entity, short depth) {
public ReplicatingEntityWrapper(Entity entity, short depth) {
super(entity);
this.hash = entity.getEntityId();
this.depth = depth;
Location location = entity.getLocation();
this.yaw = location.getYaw();
this.pitch = location.getPitch();
this.x = location.getX();
this.y = location.getY();
this.z = location.getZ();
this.type = entity.getType();
if (depth == 0) {
return;
}
Entity passenger = entity.getPassenger();
if (passenger != null) {
this.base.passenger = new EntityWrapper(passenger, depth);
this.base.passenger = new ReplicatingEntityWrapper(passenger, depth);
}
this.base.fall = entity.getFallDistance();
this.base.fire = (short) entity.getFireTicks();
@ -86,18 +52,15 @@ public class EntityWrapper {
if (depth == 1) {
return;
}
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 10, 0) || entity instanceof ArmorStand) {
if (!entity.hasGravity()) {
this.noGravity = true;
}
if (!entity.hasGravity()) {
this.noGravity = true;
}
switch (entity.getType()) {
case ARROW:
case BOAT:
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 0)) {
Boat boat = (Boat) entity;
this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType());
}
Boat boat = (Boat) entity;
this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType());
return;
case ARROW:
case COMPLEX_PART:
case EGG:
case ENDER_CRYSTAL:
@ -133,9 +96,6 @@ public class EntityWrapper {
case AREA_EFFECT_CLOUD:
// Do this stuff later
return;
default:
PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
return;
// MISC //
case DROPPED_ITEM:
Item item = (Item) entity;
@ -209,7 +169,7 @@ public class EntityWrapper {
storeLiving((LivingEntity) entity);
return;
case RABBIT:
this.dataByte = getOrdinal(Type.values(), ((Rabbit) entity).getRabbitType());
this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType());
storeAgeable((Ageable) entity);
storeLiving((LivingEntity) entity);
return;
@ -219,13 +179,16 @@ public class EntityWrapper {
storeLiving((LivingEntity) entity);
return;
case SKELETON:
this.dataByte = getOrdinal(SkeletonType.values(),((Skeleton)entity).getSkeletonType());
this.dataByte = getOrdinal(Skeleton.SkeletonType.values(),
((Skeleton) entity).getSkeletonType());
storeLiving((LivingEntity) entity);
return;
case ARMOR_STAND:
ArmorStand stand = (ArmorStand) entity;
this.inventory = new ItemStack[]{stand.getItemInHand().clone(), stand.getHelmet().clone(), stand.getChestplate().clone(),
stand.getLeggings().clone(), stand.getBoots().clone()};
this.inventory =
new ItemStack[] {stand.getItemInHand().clone(), stand.getHelmet().clone(),
stand.getChestplate().clone(), stand.getLeggings().clone(),
stand.getBoots().clone()};
storeLiving(stand);
this.stand = new ArmorStandStats();
@ -311,16 +274,16 @@ public class EntityWrapper {
}
storeLiving((LivingEntity) entity);
// END LIVING //
default:
PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
}
}
@Override
public boolean equals(Object obj) {
@Override public boolean equals(Object obj) {
return this.hash == obj.hashCode();
}
@Override
public int hashCode() {
@Override public int hashCode() {
return this.hash;
}
@ -353,12 +316,8 @@ public class EntityWrapper {
void restoreEquipment(LivingEntity entity) {
EntityEquipment equipment = entity.getEquipment();
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 0)) {
equipment.setItemInMainHand(this.lived.mainHand);
equipment.setItemInOffHand(this.lived.offHand);
} else {
equipment.setItemInHand(this.lived.mainHand);
}
equipment.setItemInMainHand(this.lived.mainHand);
equipment.setItemInOffHand(this.lived.offHand);
equipment.setHelmet(this.lived.helmet);
equipment.setChestplate(this.lived.chestplate);
equipment.setLeggings(this.lived.leggings);
@ -366,7 +325,11 @@ public class EntityWrapper {
}
private void restoreInventory(InventoryHolder entity) {
entity.getInventory().setContents(this.inventory);
try {
entity.getInventory().setContents(this.inventory);
} catch (IllegalArgumentException e) {
PlotSquared.debug("&c[WARN] Failed to restore inventory.\n Reason: " + e.getMessage());
}
}
public void storeLiving(LivingEntity lived) {
@ -393,13 +356,8 @@ public class EntityWrapper {
}
void storeEquipment(EntityEquipment equipment) {
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 0)) {
this.lived.mainHand = equipment.getItemInMainHand().clone();
this.lived.offHand = equipment.getItemInOffHand().clone();
} else {
this.lived.mainHand = equipment.getItemInHand().clone();
this.lived.offHand = null;
}
this.lived.mainHand = equipment.getItemInMainHand().clone();
this.lived.offHand = equipment.getItemInOffHand().clone();
this.lived.boots = equipment.getBoots().clone();
this.lived.leggings = equipment.getLeggings().clone();
this.lived.chestplate = equipment.getChestplate().clone();
@ -438,15 +396,15 @@ public class EntityWrapper {
this.tamed.tamed = tamed.isTamed();
}
public Entity spawn(World world, int xOffset, int zOffset) {
@Override public Entity spawn(World world, int xOffset, int zOffset) {
Location location = new Location(world, this.x + xOffset, this.y, this.z + zOffset);
location.setYaw(this.yaw);
location.setPitch(this.pitch);
if (!this.type.isSpawnable()) {
if (!this.getType().isSpawnable()) {
return null;
}
Entity entity;
switch (this.type) {
switch (this.getType()) {
case DROPPED_ITEM:
return world.dropItem(location, this.stack);
case PLAYER:
@ -459,7 +417,7 @@ public class EntityWrapper {
entity = world.spawn(location, Painting.class);
break;
default:
entity = world.spawnEntity(location, this.type);
entity = world.spawnEntity(location, this.getType());
break;
}
if (this.depth == 0) {
@ -468,7 +426,8 @@ public class EntityWrapper {
if (this.base.passenger != null) {
try {
entity.setPassenger(this.base.passenger.spawn(world, xOffset, zOffset));
} catch (Exception ignored) { }
} catch (Exception ignored) {
}
}
if (this.base.fall != 0) {
entity.setFallDistance(this.base.fall);
@ -483,19 +442,18 @@ public class EntityWrapper {
if (this.depth == 1) {
return entity;
}
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 10, 0) || entity instanceof ArmorStand) {
if (this.noGravity) {
entity.setGravity(false);
}
if (this.noGravity) {
entity.setGravity(false);
}
switch (entity.getType()) {
case ARROW:
case BOAT:
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 0)) {
Boat boat = (Boat) entity;
boat.setWoodType(TreeSpecies.values()[dataByte]);
}
Boat boat = (Boat) entity;
boat.setWoodType(TreeSpecies.values()[dataByte]);
return entity;
case SLIME:
((Slime) entity).setSize(this.dataByte);
return entity;
case ARROW:
case COMPLEX_PART:
case EGG:
case ENDER_CRYSTAL:
@ -515,10 +473,6 @@ public class EntityWrapper {
case MINECART_TNT:
case PLAYER:
case PRIMED_TNT:
return entity;
case SLIME:
((Slime) entity).setSize(this.dataByte);
return entity;
case SMALL_FIREBALL:
case SNOWBALL:
case SPLASH_POTION:
@ -535,9 +489,6 @@ public class EntityWrapper {
case UNKNOWN:
// Do this stuff later
return entity;
default:
PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
return entity;
// MISC //
case ITEM_FRAME:
ItemFrame itemframe = (ItemFrame) entity;
@ -601,7 +552,7 @@ public class EntityWrapper {
// END AGEABLE //
case RABBIT:
if (this.dataByte != 0) {
((Rabbit) entity).setRabbitType(Type.values()[this.dataByte]);
((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]);
}
restoreAgeable((Ageable) entity);
restoreLiving((LivingEntity) entity);
@ -614,7 +565,8 @@ public class EntityWrapper {
return entity;
case SKELETON:
if (this.dataByte != 0) {
((Skeleton) entity).setSkeletonType(SkeletonType.values()[this.dataByte]);
((Skeleton) entity)
.setSkeletonType(Skeleton.SkeletonType.values()[this.dataByte]);
}
storeLiving((LivingEntity) entity);
return entity;
@ -637,27 +589,37 @@ public class EntityWrapper {
stand.setBoots(this.inventory[4]);
}
if (this.stand.head[0] != 0 || this.stand.head[1] != 0 || this.stand.head[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]);
EulerAngle pose =
new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]);
stand.setHeadPose(pose);
}
if (this.stand.body[0] != 0 || this.stand.body[1] != 0 || this.stand.body[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]);
EulerAngle pose =
new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]);
stand.setBodyPose(pose);
}
if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0 || this.stand.leftLeg[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], this.stand.leftLeg[2]);
if (this.stand.leftLeg[0] != 0 || this.stand.leftLeg[1] != 0
|| this.stand.leftLeg[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1],
this.stand.leftLeg[2]);
stand.setLeftLegPose(pose);
}
if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0 || this.stand.rightLeg[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], this.stand.rightLeg[2]);
if (this.stand.rightLeg[0] != 0 || this.stand.rightLeg[1] != 0
|| this.stand.rightLeg[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1],
this.stand.rightLeg[2]);
stand.setRightLegPose(pose);
}
if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0 || this.stand.leftArm[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], this.stand.leftArm[2]);
if (this.stand.leftArm[0] != 0 || this.stand.leftArm[1] != 0
|| this.stand.leftArm[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1],
this.stand.leftArm[2]);
stand.setLeftArmPose(pose);
}
if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0 || this.stand.rightArm[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], this.stand.rightArm[2]);
if (this.stand.rightArm[0] != 0 || this.stand.rightArm[1] != 0
|| this.stand.rightArm[2] != 0) {
EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1],
this.stand.rightArm[2]);
stand.setRightArmPose(pose);
}
if (this.stand.invisible) {
@ -711,10 +673,16 @@ public class EntityWrapper {
}
restoreLiving((LivingEntity) entity);
return entity;
// END LIVING
default:
PlotSquared.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
return entity;
// END LIVING
}
}
public void saveEntity() {
}
private byte getOrdinal(Object[] list, Object value) {
for (byte i = 0; i < list.length; i++) {
if (list[i].equals(value)) {
@ -724,9 +692,5 @@ public class EntityWrapper {
return 0;
}
@SuppressWarnings("deprecation")
@Override
public String toString() {
return String.format("[%s, x=%s, y=%s, z=%s]", type.getName(), x, y, z);
}
}

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.object.entity;
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import org.bukkit.entity.AnimalTamer;

View File

@ -0,0 +1,93 @@
package com.github.intellectualsites.plotsquared.bukkit.object.entity;
import com.github.intellectualsites.plotsquared.bukkit.BukkitMain;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.metadata.FixedMetadataValue;
public class TeleportEntityWrapper extends EntityWrapper {
private Location oldLocation;
private boolean gravityOld;
private boolean invulnerableOld;
private int fireTicksOld;
private int livingTicksOld;
public TeleportEntityWrapper(final Entity entity) {
super(entity);
}
@Override public Entity spawn(final World world, final int xOffset, final int zOffset) {
if (!getEntity().getLocation().getChunk().equals(oldLocation.getChunk())) {
final Location oldLocation = this.oldLocation.clone();
oldLocation.add(xOffset, 0, xOffset);
getEntity().teleport(oldLocation);
getEntity().setGravity(gravityOld);
getEntity().setInvulnerable(invulnerableOld);
getEntity().setFireTicks(fireTicksOld);
getEntity().setTicksLived(livingTicksOld);
getEntity().removeMetadata("ps-tmp-teleport", BukkitMain.getPlugin(BukkitMain.class));
}
return getEntity();
}
@Override public void saveEntity() {
if (getEntity().hasMetadata("ps-tmp-teleport")) {
this.oldLocation = (Location) this.getEntity().getMetadata("ps-tmp-teleport").get(0);
} else {
this.oldLocation = this.getEntity().getLocation();
}
// To account for offsets in the chunk manager
this.oldLocation = oldLocation.clone();
this.oldLocation.setX(this.x);
this.oldLocation.setY(this.y);
this.oldLocation.setZ(this.z);
this.gravityOld = this.getEntity().hasGravity();
this.getEntity().setGravity(false);
this.invulnerableOld = this.getEntity().isInvulnerable();
this.getEntity().setInvulnerable(true);
this.fireTicksOld = this.getEntity().getFireTicks();
this.livingTicksOld = this.getEntity().getTicksLived();
this.getEntity().setMetadata("ps-tmp-teleport",
new FixedMetadataValue(BukkitMain.getPlugin(BukkitMain.class), oldLocation));
final Chunk newChunk = getNewChunk();
this.getEntity().teleport(
new Location(newChunk.getWorld(), newChunk.getX() << 4, 5000, newChunk.getZ() << 4));
}
private Chunk getNewChunk() {
final Chunk oldChunk = oldLocation.getChunk();
Chunk chunk = null;
for (Chunk lChunk : oldChunk.getWorld().getLoadedChunks()) {
if (!lChunk.equals(oldChunk) && lChunk.isLoaded()) {
chunk = lChunk;
break;
}
}
if (chunk == null) {
for (int dx = 1; dx < Integer.MAX_VALUE; dx++) {
for (int dz = 0; dz < Integer.MAX_VALUE; dz++) {
if ((chunk = getChunkRelative(oldChunk, dx, dz)).isLoaded()) {
break;
} else if ((chunk = getChunkRelative(oldChunk, -dx, dz)).isLoaded()) {
break;
} else if ((chunk = getChunkRelative(oldChunk, dx, -dz)).isLoaded()) {
break;
} else if ((chunk = getChunkRelative(oldChunk, -dx, -dz)).isLoaded()) {
break;
}
}
}
}
return chunk;
}
private Chunk getChunkRelative(final Chunk chunk, final int dx, final int dz) {
return chunk.getWorld().getChunkAt(chunk.getX() + dx, chunk.getZ() + dz);
}
}

View File

@ -0,0 +1,245 @@
package com.github.intellectualsites.plotsquared.bukkit.object.schematic;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.sk89q.jnbt.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class StateWrapper {
public BlockState state = null;
public CompoundTag tag = null;
public StateWrapper(BlockState state) {
this.state = state;
}
public StateWrapper(CompoundTag tag) {
this.tag = tag;
}
public static String jsonToColourCode(String str) {
str = str.replace("{\"extra\":", "").replace("],\"text\":\"\"}", "]")
.replace("[{\"color\":\"black\",\"text\":\"", "&0")
.replace("[{\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("[{\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("[{\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("[{\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("[{\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("[{\"color\":\"gold\",\"text\":\"", "&6")
.replace("[{\"color\":\"gray\",\"text\":\"", "&7")
.replace("[{\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("[{\"color\":\"blue\",\"text\":\"", "&9")
.replace("[{\"color\":\"green\",\"text\":\"", "&a")
.replace("[{\"color\":\"aqua\",\"text\":\"", "&b")
.replace("[{\"color\":\"red\",\"text\":\"", "&c")
.replace("[{\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("[{\"color\":\"yellow\",\"text\":\"", "&e")
.replace("[{\"color\":\"white\",\"text\":\"", "&f")
.replace("[{\"obfuscated\":true,\"text\":\"", "&k")
.replace("[{\"bold\":true,\"text\":\"", "&l")
.replace("[{\"strikethrough\":true,\"text\":\"", "&m")
.replace("[{\"underlined\":true,\"text\":\"", "&n")
.replace("[{\"italic\":true,\"text\":\"", "&o").replace("[{\"color\":\"black\",", "&0")
.replace("[{\"color\":\"dark_blue\",", "&1")
.replace("[{\"color\":\"dark_green\",", "&2")
.replace("[{\"color\":\"dark_aqua\",", "&3").replace("[{\"color\":\"dark_red\",", "&4")
.replace("[{\"color\":\"dark_purple\",", "&5").replace("[{\"color\":\"gold\",", "&6")
.replace("[{\"color\":\"gray\",", "&7").replace("[{\"color\":\"dark_gray\",", "&8")
.replace("[{\"color\":\"blue\",", "&9").replace("[{\"color\":\"green\",", "&a")
.replace("[{\"color\":\"aqua\",", "&b").replace("[{\"color\":\"red\",", "&c")
.replace("[{\"color\":\"light_purple\",", "&d").replace("[{\"color\":\"yellow\",", "&e")
.replace("[{\"color\":\"white\",", "&f").replace("[{\"obfuscated\":true,", "&k")
.replace("[{\"bold\":true,", "&l").replace("[{\"strikethrough\":true,", "&m")
.replace("[{\"underlined\":true,", "&n").replace("[{\"italic\":true,", "&o")
.replace("{\"color\":\"black\",\"text\":\"", "&0")
.replace("{\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("{\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("{\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("{\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("{\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("{\"color\":\"gold\",\"text\":\"", "&6")
.replace("{\"color\":\"gray\",\"text\":\"", "&7")
.replace("{\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("{\"color\":\"blue\",\"text\":\"", "&9")
.replace("{\"color\":\"green\",\"text\":\"", "&a")
.replace("{\"color\":\"aqua\",\"text\":\"", "&b")
.replace("{\"color\":\"red\",\"text\":\"", "&c")
.replace("{\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("{\"color\":\"yellow\",\"text\":\"", "&e")
.replace("{\"color\":\"white\",\"text\":\"", "&f")
.replace("{\"obfuscated\":true,\"text\":\"", "&k")
.replace("{\"bold\":true,\"text\":\"", "&l")
.replace("{\"strikethrough\":true,\"text\":\"", "&m")
.replace("{\"underlined\":true,\"text\":\"", "&n")
.replace("{\"italic\":true,\"text\":\"", "&o").replace("{\"color\":\"black\",", "&0")
.replace("{\"color\":\"dark_blue\",", "&1").replace("{\"color\":\"dark_green\",", "&2")
.replace("{\"color\":\"dark_aqua\",", "&3").replace("{\"color\":\"dark_red\",", "&4")
.replace("{\"color\":\"dark_purple\",", "&5").replace("{\"color\":\"gold\",", "&6")
.replace("{\"color\":\"gray\",", "&7").replace("{\"color\":\"dark_gray\",", "&8")
.replace("{\"color\":\"blue\",", "&9").replace("{\"color\":\"green\",", "&a")
.replace("{\"color\":\"aqua\",", "&b").replace("{\"color\":\"red\",", "&c")
.replace("{\"color\":\"light_purple\",", "&d").replace("{\"color\":\"yellow\",", "&e")
.replace("{\"color\":\"white\",", "&f").replace("{\"obfuscated\":true,", "&k")
.replace("{\"bold\":true,", "&l").replace("{\"strikethrough\":true,", "&m")
.replace("{\"underlined\":true,", "&n").replace("{\"italic\":true,", "&o")
.replace("\"color\":\"black\",\"text\":\"", "&0")
.replace("\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("\"color\":\"gold\",\"text\":\"", "&6")
.replace("\"color\":\"gray\",\"text\":\"", "&7")
.replace("\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("\"color\":\"blue\",\"text\":\"", "&9")
.replace("\"color\":\"green\",\"text\":\"", "&a")
.replace("\"color\":\"aqua\",\"text\":\"", "&b")
.replace("\"color\":\"red\",\"text\":\"", "&c")
.replace("\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("\"color\":\"yellow\",\"text\":\"", "&e")
.replace("\"color\":\"white\",\"text\":\"", "&f")
.replace("\"obfuscated\":true,\"text\":\"", "&k")
.replace("\"bold\":true,\"text\":\"", "&l")
.replace("\"strikethrough\":true,\"text\":\"", "&m")
.replace("\"underlined\":true,\"text\":\"", "&n")
.replace("\"italic\":true,\"text\":\"", "&o").replace("\"color\":\"black\",", "&0")
.replace("\"color\":\"dark_blue\",", "&1").replace("\"color\":\"dark_green\",", "&2")
.replace("\"color\":\"dark_aqua\",", "&3").replace("\"color\":\"dark_red\",", "&4")
.replace("\"color\":\"dark_purple\",", "&5").replace("\"color\":\"gold\",", "&6")
.replace("\"color\":\"gray\",", "&7").replace("\"color\":\"dark_gray\",", "&8")
.replace("\"color\":\"blue\",", "&9").replace("\"color\":\"green\",", "&a")
.replace("\"color\":\"aqua\",", "&b").replace("\"color\":\"red\",", "&c")
.replace("\"color\":\"light_purple\",", "&d").replace("\"color\":\"yellow\",", "&e")
.replace("\"color\":\"white\",", "&f").replace("\"obfuscated\":true,", "&k")
.replace("\"bold\":true,", "&l").replace("\"strikethrough\":true,", "&m")
.replace("\"underlined\":true,", "&n").replace("\"italic\":true,", "&o")
.replace("[{\"text\":\"", "&0").replace("{\"text\":\"", "&0").replace("\"},", "")
.replace("\"}]", "").replace("\"}", "");
for (Entry<String, String> entry : C.replacements.entrySet()) {
str = str.replace(entry.getKey(), entry.getValue());
}
return str;
}
public boolean restoreTag(String worldName, int x, int y, int z) {
if (this.tag == null) {
return false;
}
String tileid = this.tag.getString("id").toLowerCase();
if (tileid.startsWith("minecraft:")) {
tileid = tileid.replace("minecraft:", "");
}
World world = BukkitUtil.getWorld(worldName);
Block block = world.getBlockAt(x, y, z);
if (block == null) {
return false;
}
BlockState state = block.getState();
switch (tileid) {
case "chest":
List<Tag> itemsTag = this.tag.getListTag("Items").getValue();
int length = itemsTag.size();
String[] ids = new String[length];
byte[] amounts = new byte[length];
byte[] slots = new byte[length];
for (int i = 0; i < length; i++) {
Tag itemTag = itemsTag.get(i);
CompoundTag itemComp = (CompoundTag) itemTag;
String id = itemComp.getString("Id");
ids[i] = id;
amounts[i] = itemComp.getByte("Count");
slots[i] = itemComp.getByte("Slot");
}
if (state instanceof InventoryHolder) {
InventoryHolder holder = (InventoryHolder) state;
Inventory inv = holder.getInventory();
for (int i = 0; i < ids.length; i++) {
ItemStack item =
new ItemStack(Material.getMaterial(ids[i]), (int) amounts[i]);
inv.addItem(item);
}
state.update(true);
return true;
}
return false;
case "sign":
if (state instanceof Sign) {
Sign sign = (Sign) state;
sign.setLine(0, jsonToColourCode(tag.getString("Text1")));
sign.setLine(1, jsonToColourCode(tag.getString("Text2")));
sign.setLine(2, jsonToColourCode(tag.getString("Text3")));
sign.setLine(3, jsonToColourCode(tag.getString("Text4")));
state.update(true);
return true;
}
return false;
}
return false;
}
public CompoundTag getTag() {
if (this.tag != null) {
return this.tag;
}
if (this.state instanceof InventoryHolder) {
InventoryHolder inv = (InventoryHolder) this.state;
ItemStack[] contents = inv.getInventory().getContents();
Map<String, Tag> values = new HashMap<>();
values.put("Items", new ListTag(CompoundTag.class, serializeInventory(contents)));
return new CompoundTag(values);
}
return null;
}
public String getId() {
return "Chest";
}
public List<CompoundTag> serializeInventory(ItemStack[] items) {
List<CompoundTag> tags = new ArrayList<>();
for (int i = 0; i < items.length; ++i) {
if (items[i] != null) {
Map<String, Tag> tagData = serializeItem(items[i]);
tagData.put("Slot", new ByteTag((byte) i));
tags.add(new CompoundTag(tagData));
}
}
return tags;
}
public Map<String, Tag> serializeItem(ItemStack item) {
Map<String, Tag> data = new HashMap<>();
data.put("id", new StringTag(item.getType().name()));
data.put("Damage", new ShortTag(item.getDurability()));
data.put("Count", new ByteTag((byte) item.getAmount()));
if (!item.getEnchantments().isEmpty()) {
List<CompoundTag> enchantmentList = new ArrayList<>();
for (Entry<Enchantment, Integer> entry : item.getEnchantments().entrySet()) {
Map<String, Tag> enchantment = new HashMap<>();
enchantment.put("id", new StringTag(entry.getKey().toString()));
enchantment.put("lvl", new ShortTag(entry.getValue().shortValue()));
enchantmentList.add(new CompoundTag(enchantment));
}
Map<String, Tag> auxData = new HashMap<>();
auxData.put("ench", new ListTag(CompoundTag.class, enchantmentList));
data.put("tag", new CompoundTag(auxData));
}
return data;
}
}

View File

@ -1,6 +1,6 @@
package com.plotsquared.bukkit.titles;
package com.github.intellectualsites.plotsquared.bukkit.titles;
import com.plotsquared.bukkit.chat.Reflection;
import com.github.intellectualsites.plotsquared.bukkit.chat.Reflection;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
@ -12,13 +12,14 @@ public class DefaultTitleManager extends TitleManager {
/**
* Create a new 1.8 title.
*
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param fadeOutTime Fade out time
*/
public DefaultTitleManager(String title, String subtitle, int fadeInTime, int stayTime, int fadeOutTime) {
DefaultTitleManager(String title, String subtitle, int fadeInTime, int stayTime,
int fadeOutTime) {
super(title, subtitle, fadeInTime, stayTime, fadeOutTime);
}
@ -32,7 +33,8 @@ public class DefaultTitleManager extends TitleManager {
this.nmsChatSerializer = Reflection.getNMSClass("ChatSerializer");
}
@Override public void send(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void send(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
if (this.packetTitle != null) {
// First reset previous settings
resetTitle(player);
@ -41,38 +43,44 @@ public class DefaultTitleManager extends TitleManager {
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE)
.newInstance(actions[2], null, this.fadeInTime * (this.ticks ? 1 : 20),
this.stayTime * (this.ticks ? 1 : 20), this.fadeOutTime * (this.ticks ? 1 : 20));
Object packet = this.packetTitle
.getConstructor(this.packetActions, this.chatBaseComponent, Integer.TYPE,
Integer.TYPE, Integer.TYPE)
.newInstance(actions[2], null, this.fadeInTime * (this.ticks ? 1 : 20),
this.stayTime * (this.ticks ? 1 : 20),
this.fadeOutTime * (this.ticks ? 1 : 20));
// Send if set
if (this.fadeInTime != -1 && this.fadeOutTime != -1 && this.stayTime != -1) {
sendPacket.invoke(connection, packet);
}
// Send title
Object serialized = getMethod(this.nmsChatSerializer, "a", String.class).invoke(null,
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getTitle()) + "\",color:" + this.titleColor.name().toLowerCase()
+ '}');
packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent).newInstance(actions[0], serialized);
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getTitle())
+ "\",color:" + this.titleColor.name().toLowerCase() + '}');
packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent)
.newInstance(actions[0], serialized);
sendPacket.invoke(connection, packet);
if (!this.getSubtitle().isEmpty()) {
// Send subtitle if present
serialized = getMethod(this.nmsChatSerializer, "a", String.class).invoke(null,
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getSubtitle()) + "\",color:" + this.subtitleColor.name()
.toLowerCase() + '}');
packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent).newInstance(actions[1], serialized);
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getSubtitle())
+ "\",color:" + this.subtitleColor.name().toLowerCase() + '}');
packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent)
.newInstance(actions[1], serialized);
sendPacket.invoke(connection, packet);
}
}
}
@Override
public void clearTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void clearTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
// Send timings first
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent).newInstance(actions[3], null);
Object packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent)
.newInstance(actions[3], null);
sendPacket.invoke(connection, packet);
}
@ -84,14 +92,15 @@ public class DefaultTitleManager extends TitleManager {
* @throws ReflectiveOperationException
* @throws SecurityException
*/
@Override
public void resetTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void resetTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
// Send timings first
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent).newInstance(actions[4], null);
Object packet = this.packetTitle.getConstructor(this.packetActions, this.chatBaseComponent)
.newInstance(actions[4], null);
sendPacket.invoke(connection, packet);
}
@ -106,9 +115,10 @@ public class DefaultTitleManager extends TitleManager {
}
}
private Method getMethod(Class<?> clazz, String name, Class<?>... args) {
Method getMethod(Class<?> clazz, String name, Class<?>... args) {
for (Method m : clazz.getMethods()) {
if (m.getName().equals(name) && (args.length == 0 || ClassListEqual(args, m.getParameterTypes()))) {
if (m.getName().equals(name) && (args.length == 0 || classListEqual(args,
m.getParameterTypes()))) {
m.setAccessible(true);
return m;
}
@ -116,17 +126,4 @@ public class DefaultTitleManager extends TitleManager {
return null;
}
boolean ClassListEqual(Class<?>[] l1, Class<?>[] l2) {
if (l1.length != l2.length) {
return false;
}
boolean equal = true;
for (int i = 0; i < l1.length; i++) {
if (l1[i] != l2[i]) {
equal = false;
break;
}
}
return equal;
}
}

View File

@ -0,0 +1,20 @@
package com.github.intellectualsites.plotsquared.bukkit.titles;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.AbstractTitle;
import org.bukkit.entity.Player;
@SuppressWarnings("deprecation") public class DefaultTitle_111 extends AbstractTitle {
@Override
public void sendTitle(PlotPlayer player, String head, String sub, int in, int delay, int out) {
try {
final Player playerObj = ((BukkitPlayer) player).player;
TitleManager_1_11 title = new TitleManager_1_11(head, sub, in, delay, out);
title.send(playerObj);
return;
} catch (Throwable ignored) {
}
}
}

View File

@ -0,0 +1,22 @@
package com.github.intellectualsites.plotsquared.bukkit.titles;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.AbstractTitle;
public class HackTitle extends AbstractTitle {
@Override
public void sendTitle(PlotPlayer player, String head, String sub, int in, int delay, int out) {
try {
HackTitleManager title = new HackTitleManager(head, sub, in, delay, out);
title.send(((BukkitPlayer) player).player);
} catch (Exception ignored) {
PlotSquared.debug("&cYour server version does not support titles!");
Settings.TITLES = false;
AbstractTitle.TITLE_CLASS = null;
}
}
}

View File

@ -1,6 +1,6 @@
package com.plotsquared.bukkit.titles;
package com.github.intellectualsites.plotsquared.bukkit.titles;
import com.plotsquared.bukkit.chat.Reflection;
import com.github.intellectualsites.plotsquared.bukkit.chat.Reflection;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
@ -13,27 +13,27 @@ public class HackTitleManager extends TitleManager {
/**
* Create a new 1.8 title.
*
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param fadeOutTime Fade out time
*/
public HackTitleManager(String title, String subtitle, int fadeInTime, int stayTime, int fadeOutTime) {
HackTitleManager(String title, String subtitle, int fadeInTime, int stayTime, int fadeOutTime) {
super(title, subtitle, fadeInTime, stayTime, fadeOutTime);
}
/**
* Load spigot and NMS classes.
*/
@Override
void loadClasses() {
@Override void loadClasses() {
this.packetTitle = getClass("org.spigotmc.ProtocolInjector$PacketTitle");
this.packetActions = getClass("org.spigotmc.ProtocolInjector$PacketTitle$Action");
this.nmsChatSerializer = Reflection.getNMSClass("ChatSerializer");
}
@Override public void send(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void send(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
if ((getProtocolVersion(player) >= 47) && isSpigot() && (this.packetTitle != null)) {
// First reset previous settings
resetTitle(player);
@ -42,8 +42,9 @@ public class HackTitleManager extends TitleManager {
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions, Integer.TYPE, Integer.TYPE, Integer.TYPE).newInstance(actions[2],
this.fadeInTime * (this.ticks ? 1 : 20),
Object packet = this.packetTitle
.getConstructor(this.packetActions, Integer.TYPE, Integer.TYPE, Integer.TYPE)
.newInstance(actions[2], this.fadeInTime * (this.ticks ? 1 : 20),
this.stayTime * (this.ticks ? 1 : 20),
this.fadeOutTime * (this.ticks ? 1 : 20));
// Send if set
@ -52,43 +53,49 @@ public class HackTitleManager extends TitleManager {
}
// Send title
Object serialized = getMethod(this.nmsChatSerializer, "a", String.class).invoke(null,
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getTitle()) + "\",color:" + this.titleColor.name().toLowerCase()
+ "}");
packet = this.packetTitle.getConstructor(this.packetActions, Reflection.getNMSClass("IChatBaseComponent"))
.newInstance(actions[0], serialized);
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getTitle())
+ "\",color:" + this.titleColor.name().toLowerCase() + "}");
packet = this.packetTitle
.getConstructor(this.packetActions, Reflection.getNMSClass("IChatBaseComponent"))
.newInstance(actions[0], serialized);
sendPacket.invoke(connection, packet);
if (!this.getSubtitle().isEmpty()) {
// Send subtitle if present
serialized = getMethod(this.nmsChatSerializer, "a", String.class).invoke(null,
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getSubtitle()) + "\",color:" + this.subtitleColor.name()
.toLowerCase() + "}");
packet = this.packetTitle.getConstructor(this.packetActions, Reflection.getNMSClass("IChatBaseComponent"))
.newInstance(actions[1], serialized);
"{text:\"" + ChatColor.translateAlternateColorCodes('&', this.getSubtitle())
+ "\",color:" + this.subtitleColor.name().toLowerCase() + "}");
packet = this.packetTitle.getConstructor(this.packetActions,
Reflection.getNMSClass("IChatBaseComponent"))
.newInstance(actions[1], serialized);
sendPacket.invoke(connection, packet);
}
}
}
@Override public void clearTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void clearTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
if ((getProtocolVersion(player) >= 47) && isSpigot()) {
// Send timings first
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions).newInstance(actions[3]);
Object packet =
this.packetTitle.getConstructor(this.packetActions).newInstance(actions[3]);
sendPacket.invoke(connection, packet);
}
}
@Override public void resetTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
@Override public void resetTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
if ((getProtocolVersion(player) >= 47) && isSpigot()) {
// Send timings first
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = this.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object packet = this.packetTitle.getConstructor(this.packetActions).newInstance(actions[4]);
Object packet =
this.packetTitle.getConstructor(this.packetActions).newInstance(actions[4]);
sendPacket.invoke(connection, packet);
}
}
@ -102,7 +109,8 @@ public class HackTitleManager extends TitleManager {
* @throws ReflectiveOperationException
* @throws SecurityException
*/
private int getProtocolVersion(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
private int getProtocolVersion(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException {
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object networkManager = getValue("networkManager", connection);
@ -127,15 +135,18 @@ public class HackTitleManager extends TitleManager {
private Class<?> getClass(String namespace) {
try {
return Class.forName(namespace);
} catch (ClassNotFoundException ignored) {}
} catch (ClassNotFoundException ignored) {
}
return null;
}
private Field getField(String name, Class<?> clazz) throws NoSuchFieldException, SecurityException {
private Field getField(String name, Class<?> clazz)
throws NoSuchFieldException, SecurityException {
return clazz.getDeclaredField(name);
}
private Object getValue(String name, Object obj) throws ReflectiveOperationException, SecurityException, IllegalArgumentException {
private Object getValue(String name, Object obj)
throws ReflectiveOperationException, SecurityException, IllegalArgumentException {
Field f = getField(name, obj.getClass());
f.setAccessible(true);
return f.get(obj);
@ -154,7 +165,8 @@ public class HackTitleManager extends TitleManager {
private Method getMethod(Class<?> clazz, String name, Class<?>... args) {
for (Method m : clazz.getMethods()) {
if (m.getName().equals(name) && ((args.length == 0) || classListEqual(args, m.getParameterTypes()))) {
if (m.getName().equals(name) && ((args.length == 0) || classListEqual(args,
m.getParameterTypes()))) {
m.setAccessible(true);
return m;
}
@ -162,18 +174,4 @@ public class HackTitleManager extends TitleManager {
return null;
}
private boolean classListEqual(Class<?>[] l1, Class<?>[] l2) {
if (l1.length != l2.length) {
return false;
}
boolean equal = true;
for (int i = 0; i < l1.length; i++) {
if (l1[i] != l2[i]) {
equal = false;
break;
}
}
return equal;
}
}

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.titles;
package com.github.intellectualsites.plotsquared.bukkit.titles;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -12,17 +12,13 @@ import java.util.Map;
public abstract class TitleManager {
private static final Map<Class<?>, Class<?>> CORRESPONDING_TYPES = new HashMap<>();
/* Title packet */
Class<?> packetTitle;
/* Title packet actions ENUM */
Class<?> packetActions;
/* Chat serializer */
Class<?> nmsChatSerializer;
/* Title packet */ Class<?> packetTitle;
/* Title packet actions ENUM */ Class<?> packetActions;
/* Chat serializer */ Class<?> nmsChatSerializer;
Class<?> chatBaseComponent;
ChatColor titleColor = ChatColor.WHITE;
ChatColor subtitleColor = ChatColor.WHITE;
/* Title timings */
int fadeInTime = -1;
/* Title timings */ int fadeInTime = -1;
int stayTime = -1;
int fadeOutTime = -1;
boolean ticks = false;
@ -34,10 +30,10 @@ public abstract class TitleManager {
/**
* Create a new 1.8 title.
*
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param fadeOutTime Fade out time
*/
TitleManager(String title, String subtitle, int fadeInTime, int stayTime, int fadeOutTime) {
@ -52,7 +48,7 @@ public abstract class TitleManager {
abstract void loadClasses();
/**
* Get title text.
* Gets title text.
*
* @return Title text
*/
@ -61,7 +57,7 @@ public abstract class TitleManager {
}
/**
* Set title text.
* Sets the text for the title.
*
* @param title Title
*/
@ -70,7 +66,7 @@ public abstract class TitleManager {
}
/**
* Get subtitle text.
* Gets the subtitle text.
*
* @return Subtitle text
*/
@ -79,7 +75,7 @@ public abstract class TitleManager {
}
/**
* Set subtitle text.
* Sets subtitle text.
*
* @param subtitle Subtitle text
*/
@ -88,7 +84,7 @@ public abstract class TitleManager {
}
/**
* Set the title color.
* Sets the title color.
*
* @param color Chat color
*/
@ -97,7 +93,7 @@ public abstract class TitleManager {
}
/**
* Set the subtitle color.
* Sets the subtitle color.
*
* @param color Chat color
*/
@ -106,7 +102,7 @@ public abstract class TitleManager {
}
/**
* Set title fade in time.
* Sets title fade in time.
*
* @param time Time
*/
@ -115,7 +111,7 @@ public abstract class TitleManager {
}
/**
* Set title fade out time.
* Sets title fade out time.
*
* @param time Time
*/
@ -124,7 +120,7 @@ public abstract class TitleManager {
}
/**
* Set title stay time.
* Sets title stay time.
*
* @param time Time
*/
@ -133,59 +129,62 @@ public abstract class TitleManager {
}
/**
* Set timings to ticks.
* Sets timings to ticks.
*/
public final void setTimingsToTicks() {
this.ticks = true;
}
/**
* Set timings to seconds.
* Sets timings to seconds.
*/
public final void setTimingsToSeconds() {
this.ticks = false;
}
/**
* Send the title to a player.
* Sends the title to a player.
*
* @param player Player
* @throws IllegalArgumentException
* @throws ReflectiveOperationException
* @throws SecurityException
*/
public abstract void send(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
public abstract void send(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
/**
* Broadcast the title to all players.
* Broadcasts the title to all players.
*
* @throws Exception
*/
public final void broadcast() throws Exception {
for (Player p : Bukkit.getOnlinePlayers()) {
send(p);
for (Player player : Bukkit.getOnlinePlayers()) {
send(player);
}
}
/**
* Clear the title.
* Clears the title.
*
* @param player Player
* @throws IllegalArgumentException
* @throws ReflectiveOperationException
* @throws SecurityException
*/
public abstract void clearTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
public abstract void clearTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
/**
* Reset the title settings.
* Resets the title settings.
*
* @param player Player
* @throws IllegalArgumentException
* @throws ReflectiveOperationException
* @throws SecurityException
*/
public abstract void resetTitle(Player player) throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
public abstract void resetTitle(Player player)
throws IllegalArgumentException, ReflectiveOperationException, SecurityException;
private Class<?> getPrimitiveType(Class<?> clazz) {
if (CORRESPONDING_TYPES.containsKey(clazz)) {
@ -195,7 +194,7 @@ public abstract class TitleManager {
}
}
final Class<?>[] toPrimitiveTypeArray(Class<?>[] classes) {
private Class<?>[] toPrimitiveTypeArray(Class<?>[] classes) {
int a;
if (classes != null) {
a = classes.length;
@ -229,7 +228,7 @@ public abstract class TitleManager {
return null;
}
final boolean equalsTypeArray(Class<?>[] a, Class<?>[] o) {
private boolean equalsTypeArray(Class<?>[] a, Class<?>[] o) {
if (a.length != o.length) {
return false;
}
@ -241,4 +240,17 @@ public abstract class TitleManager {
return true;
}
boolean classListEqual(Class<?>[] l1, Class<?>[] l2) {
if (l1.length != l2.length) {
return false;
}
boolean equal = true;
for (int i = 0; i < l1.length; i++) {
if (l1[i] != l2[i]) {
equal = false;
break;
}
}
return equal;
}
}

View File

@ -0,0 +1,497 @@
package com.github.intellectualsites.plotsquared.bukkit.titles;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Minecraft 1.8 Title
* For 1.11
*
* @author Maxim Van de Wynckel
* @version 1.1.0
*/
public class TitleManager_1_11 {
private static final Map<Class<?>, Class<?>> CORRESPONDING_TYPES =
new HashMap<Class<?>, Class<?>>();
/* Title packet */
private static Class<?> packetTitle;
/* Title packet actions ENUM */
private static Class<?> packetActions;
/* Chat serializer */
private static Class<?> nmsChatSerializer;
private static Class<?> chatBaseComponent;
/* NMS player and connection */
private static Class<?> nmsPlayer;
private static Class<?> nmsPlayerConnection;
private static Field playerConnection;
private static Method sendPacket;
private static Class<?> obcPlayer;
private static Method methodPlayerGetHandle;
/* Title text and color */
private String title = "";
private ChatColor titleColor = ChatColor.WHITE;
/* Subtitle text and color */
private String subtitle = "";
private ChatColor subtitleColor = ChatColor.WHITE;
/* Title timings */
private int fadeInTime = -1;
private int stayTime = -1;
private int fadeOutTime = -1;
private boolean ticks = false;
public TitleManager_1_11() {
loadClasses();
}
/**
* Create a new 1.8 title
*
* @param title Title
*/
public TitleManager_1_11(String title) {
this.title = title;
loadClasses();
}
/**
* Create a new 1.8 title
*
* @param title Title text
* @param subtitle Subtitle text
*/
public TitleManager_1_11(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
loadClasses();
}
/**
* Copy 1.8 title
*
* @param title Title
*/
public TitleManager_1_11(TitleManager_1_11 title) {
// Copy title
this.title = title.getTitle();
this.subtitle = title.getSubtitle();
this.titleColor = title.getTitleColor();
this.subtitleColor = title.getSubtitleColor();
this.fadeInTime = title.getFadeInTime();
this.fadeOutTime = title.getFadeOutTime();
this.stayTime = title.getStayTime();
this.ticks = title.isTicks();
loadClasses();
}
/**
* Create a new 1.8 title
*
* @param title Title text
* @param subtitle Subtitle text
* @param fadeInTime Fade in time
* @param stayTime Stay on screen time
* @param fadeOutTime Fade out time
*/
public TitleManager_1_11(String title, String subtitle, int fadeInTime, int stayTime,
int fadeOutTime) {
this.title = title;
this.subtitle = subtitle;
this.fadeInTime = fadeInTime;
this.stayTime = stayTime;
this.fadeOutTime = fadeOutTime;
loadClasses();
}
private static boolean equalsTypeArray(Class<?>[] a, Class<?>[] o) {
if (a.length != o.length)
return false;
for (int i = 0; i < a.length; i++)
if (!a[i].equals(o[i]) && !a[i].isAssignableFrom(o[i]))
return false;
return true;
}
/**
* Load spigot and NMS classes
*/
private void loadClasses() {
if (packetTitle == null) {
packetTitle = getNMSClass("PacketPlayOutTitle");
packetActions = getNMSClass("PacketPlayOutTitle$EnumTitleAction");
chatBaseComponent = getNMSClass("IChatBaseComponent");
nmsChatSerializer = getNMSClass("ChatComponentText");
nmsPlayer = getNMSClass("EntityPlayer");
nmsPlayerConnection = getNMSClass("PlayerConnection");
playerConnection = getField(nmsPlayer, "playerConnection");
sendPacket = getMethod(nmsPlayerConnection, "sendPacket");
obcPlayer = getOBCClass("entity.CraftPlayer");
methodPlayerGetHandle = getMethod("getHandle", obcPlayer);
}
}
/**
* Get title text
*
* @return Title text
*/
public String getTitle() {
return this.title;
}
/**
* Set title text
*
* @param title Title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Get subtitle text
*
* @return Subtitle text
*/
public String getSubtitle() {
return this.subtitle;
}
/**
* Set subtitle text
*
* @param subtitle Subtitle text
*/
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
/**
* Set timings to ticks
*/
public void setTimingsToTicks() {
ticks = true;
}
/**
* Set timings to seconds
*/
public void setTimingsToSeconds() {
ticks = false;
}
/**
* Send the title to a player
*
* @param player Player
*/
public void send(Player player) {
if (packetTitle != null) {
// First reset previous settings
resetTitle(player);
try {
// Send timings first
Object handle = getHandle(player);
Object connection = playerConnection.get(handle);
Object[] actions = packetActions.getEnumConstants();
Object packet = packetTitle
.getConstructor(packetActions, chatBaseComponent, Integer.TYPE, Integer.TYPE,
Integer.TYPE).newInstance(actions[3], null, fadeInTime * (ticks ? 1 : 20),
stayTime * (ticks ? 1 : 20), fadeOutTime * (ticks ? 1 : 20));
// Send if set
if (fadeInTime != -1 && fadeOutTime != -1 && stayTime != -1)
sendPacket.invoke(connection, packet);
Object serialized;
if (!subtitle.equals("")) {
// Send subtitle if present
serialized = nmsChatSerializer.getConstructor(String.class).newInstance(
subtitleColor + ChatColor.translateAlternateColorCodes('&', subtitle));
packet = packetTitle.getConstructor(packetActions, chatBaseComponent)
.newInstance(actions[1], serialized);
sendPacket.invoke(connection, packet);
}
// Send title
serialized = nmsChatSerializer.getConstructor(String.class)
.newInstance(titleColor + ChatColor.translateAlternateColorCodes('&', title));
packet = packetTitle.getConstructor(packetActions, chatBaseComponent)
.newInstance(actions[0], serialized);
sendPacket.invoke(connection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateTimes(Player player) {
if (TitleManager_1_11.packetTitle != null) {
try {
Object handle = getHandle(player);
Object connection = playerConnection.get(handle);
Object[] actions = TitleManager_1_11.packetActions.getEnumConstants();
Object packet = TitleManager_1_11.packetTitle.getConstructor(
new Class[] {TitleManager_1_11.packetActions, chatBaseComponent, Integer.TYPE,
Integer.TYPE, Integer.TYPE})
.newInstance(actions[3], null, this.fadeInTime * (this.ticks ? 1 : 20),
this.stayTime * (this.ticks ? 1 : 20),
this.fadeOutTime * (this.ticks ? 1 : 20));
if ((this.fadeInTime != -1) && (this.fadeOutTime != -1) && (this.stayTime != -1)) {
sendPacket.invoke(connection, packet);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateTitle(Player player) {
if (TitleManager_1_11.packetTitle != null) {
try {
Object handle = getHandle(player);
Object connection = getField(handle.getClass(), "playerConnection").get(handle);
Object[] actions = TitleManager_1_11.packetActions.getEnumConstants();
Method sendPacket = getMethod(connection.getClass(), "sendPacket");
Object serialized = nmsChatSerializer.getConstructor(String.class).newInstance(
titleColor + ChatColor.translateAlternateColorCodes('&', this.title));
Object packet = TitleManager_1_11.packetTitle.getConstructor(
new Class[] {TitleManager_1_11.packetActions, chatBaseComponent})
.newInstance(actions[0], serialized);
sendPacket.invoke(connection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void updateSubtitle(Player player) {
if (TitleManager_1_11.packetTitle != null) {
try {
Object handle = getHandle(player);
Object connection = playerConnection.get(handle);
Object[] actions = TitleManager_1_11.packetActions.getEnumConstants();
Object serialized = nmsChatSerializer.getConstructor(String.class).newInstance(
subtitleColor + ChatColor.translateAlternateColorCodes('&', this.subtitle));
Object packet = TitleManager_1_11.packetTitle.getConstructor(
new Class[] {TitleManager_1_11.packetActions, chatBaseComponent})
.newInstance(actions[1], serialized);
sendPacket.invoke(connection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Broadcast the title to all players
*/
public void broadcast() {
for (Player p : Bukkit.getOnlinePlayers()) {
send(p);
}
}
/**
* Clear the title
*
* @param player Player
*/
public void clearTitle(Player player) {
try {
// Send timings first
Object handle = getHandle(player);
Object connection = playerConnection.get(handle);
Object[] actions = packetActions.getEnumConstants();
Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent)
.newInstance(actions[4], null);
sendPacket.invoke(connection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Reset the title settings
*
* @param player Player
*/
public void resetTitle(Player player) {
try {
// Send timings first
Object handle = getHandle(player);
Object connection = playerConnection.get(handle);
Object[] actions = packetActions.getEnumConstants();
Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent)
.newInstance(actions[5], null);
sendPacket.invoke(connection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
private Class<?> getPrimitiveType(Class<?> clazz) {
return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz;
}
private Class<?>[] toPrimitiveTypeArray(Class<?>[] classes) {
int a = classes != null ? classes.length : 0;
Class<?>[] types = new Class<?>[a];
for (int i = 0; i < a; i++)
types[i] = getPrimitiveType(classes[i]);
return types;
}
private Object getHandle(Player player) {
try {
return methodPlayerGetHandle.invoke(player);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private Method getMethod(String name, Class<?> clazz, Class<?>... paramTypes) {
Class<?>[] t = toPrimitiveTypeArray(paramTypes);
for (Method m : clazz.getMethods()) {
Class<?>[] types = toPrimitiveTypeArray(m.getParameterTypes());
if (m.getName().equals(name) && equalsTypeArray(types, t))
return m;
}
return null;
}
private String getVersion() {
String name = Bukkit.getServer().getClass().getPackage().getName();
String version = name.substring(name.lastIndexOf('.') + 1) + ".";
return version;
}
private Class<?> getNMSClass(String className) {
String fullName = "net.minecraft.server." + getVersion() + className;
Class<?> clazz = null;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
e.printStackTrace();
}
return clazz;
}
private Class<?> getOBCClass(String className) {
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
Class<?> clazz = null;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
e.printStackTrace();
}
return clazz;
}
private Field getField(Class<?> clazz, String name) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private Method getMethod(Class<?> clazz, String name, Class<?>... args) {
for (Method m : clazz.getMethods())
if (m.getName().equals(name) && (args.length == 0 || ClassListEqual(args,
m.getParameterTypes()))) {
m.setAccessible(true);
return m;
}
return null;
}
private boolean ClassListEqual(Class<?>[] l1, Class<?>[] l2) {
boolean equal = true;
if (l1.length != l2.length)
return false;
for (int i = 0; i < l1.length; i++)
if (l1[i] != l2[i]) {
equal = false;
break;
}
return equal;
}
public ChatColor getTitleColor() {
return titleColor;
}
/**
* Set the title color
*
* @param color Chat color
*/
public void setTitleColor(ChatColor color) {
this.titleColor = color;
}
public ChatColor getSubtitleColor() {
return subtitleColor;
}
/**
* Set the subtitle color
*
* @param color Chat color
*/
public void setSubtitleColor(ChatColor color) {
this.subtitleColor = color;
}
public int getFadeInTime() {
return fadeInTime;
}
/**
* Set title fade in time
*
* @param time Time
*/
public void setFadeInTime(int time) {
this.fadeInTime = time;
}
public int getFadeOutTime() {
return fadeOutTime;
}
/**
* Set title fade out time
*
* @param time Time
*/
public void setFadeOutTime(int time) {
this.fadeOutTime = time;
}
public int getStayTime() {
return stayTime;
}
/**
* Set title stay time
*
* @param time Time
*/
public void setStayTime(int time) {
this.stayTime = time;
}
public boolean isTicks() {
return ticks;
}
}

View File

@ -0,0 +1,18 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.plot.object.BlockRegistry;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import lombok.NonNull;
import org.bukkit.Material;
public class BukkitBlockRegistry extends BlockRegistry<Material> {
public BukkitBlockRegistry(final Material... preInitializedItems) {
super(Material.class, preInitializedItems);
}
@Override public PlotBlock getPlotBlock(@NonNull final Material item) {
return PlotBlock.get(item.name());
}
}

View File

@ -0,0 +1,54 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.chat.FancyMessage;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.object.ConsolePlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotMessage;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.ChatManager;
import org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.List;
public class BukkitChatManager extends ChatManager<FancyMessage> {
@Override public FancyMessage builder() {
return new FancyMessage("");
}
@Override public void color(PlotMessage message, String color) {
message.$(this).color(ChatColor.getByChar(C.color(color).substring(1)));
}
@Override public void tooltip(PlotMessage message, PlotMessage... tooltips) {
List<FancyMessage> lines = new ArrayList<>();
for (PlotMessage tooltip : tooltips) {
lines.add(tooltip.$(this));
}
message.$(this).formattedTooltip(lines);
}
@Override public void command(PlotMessage message, String command) {
message.$(this).command(command);
}
@Override public void text(PlotMessage message, String text) {
message.$(this).then(ChatColor.stripColor(text));
}
@Override public void send(PlotMessage plotMessage, PlotPlayer player) {
if (player instanceof ConsolePlayer || !Settings.Chat.INTERACTIVE) {
player.sendMessage(plotMessage.$(this).toOldMessageFormat());
} else {
plotMessage.$(this).send(((BukkitPlayer) player).player);
}
}
@Override public void suggest(PlotMessage plotMessage, String command) {
plotMessage.$(this).suggest(command);
}
}

View File

@ -1,16 +1,10 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.commands.MainCommand;
import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.plotsquared.bukkit.commands.DebugUUID;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.ProxiedCommandSender;
import org.bukkit.command.RemoteConsoleCommandSender;
import org.bukkit.command.TabCompleter;
import com.github.intellectualsites.plotsquared.bukkit.commands.DebugUUID;
import com.github.intellectualsites.plotsquared.plot.commands.MainCommand;
import com.github.intellectualsites.plotsquared.plot.object.ConsolePlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@ -25,19 +19,22 @@ public class BukkitCommand implements CommandExecutor, TabCompleter {
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String commandLabel, String[] args) {
public boolean onCommand(CommandSender commandSender, Command command, String commandLabel,
String[] args) {
if (commandSender instanceof Player) {
return MainCommand.onCommand(BukkitUtil.getPlayer((Player) commandSender), args);
}
if (commandSender instanceof ConsoleCommandSender || commandSender instanceof ProxiedCommandSender
|| commandSender instanceof RemoteConsoleCommandSender) {
if (commandSender instanceof ConsoleCommandSender
|| commandSender instanceof ProxiedCommandSender
|| commandSender instanceof RemoteConsoleCommandSender) {
return MainCommand.onCommand(ConsolePlayer.getConsole(), args);
}
return false;
}
@Override
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] args) {
public List<String> onTabComplete(CommandSender commandSender, Command command, String s,
String[] args) {
if (!(commandSender instanceof Player)) {
return null;
}

View File

@ -1,10 +1,10 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.EconHandler;
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
import com.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitOfflinePlayer;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.EconHandler;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
@ -24,7 +24,8 @@ public class BukkitEconHandler extends EconHandler {
}
private boolean setupPermissions() {
RegisteredServiceProvider<Permission> permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
RegisteredServiceProvider<Permission> permissionProvider =
Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
if (permissionProvider != null) {
this.perms = permissionProvider.getProvider();
}
@ -35,15 +36,15 @@ public class BukkitEconHandler extends EconHandler {
if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> economyProvider = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
RegisteredServiceProvider<Economy> economyProvider =
Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (economyProvider != null) {
this.econ = economyProvider.getProvider();
}
return this.econ != null;
}
@Override
public double getMoney(PlotPlayer player) {
@Override public double getMoney(PlotPlayer player) {
double bal = super.getMoney(player);
if (Double.isNaN(bal)) {
return this.econ.getBalance(((BukkitPlayer) player).player);
@ -51,28 +52,23 @@ public class BukkitEconHandler extends EconHandler {
return bal;
}
@Override
public void withdrawMoney(PlotPlayer player, double amount) {
@Override public void withdrawMoney(PlotPlayer player, double amount) {
this.econ.withdrawPlayer(((BukkitPlayer) player).player, amount);
}
@Override
public void depositMoney(PlotPlayer player, double amount) {
@Override public void depositMoney(PlotPlayer player, double amount) {
this.econ.depositPlayer(((BukkitPlayer) player).player, amount);
}
@Override
public void depositMoney(OfflinePlotPlayer player, double amount) {
@Override public void depositMoney(OfflinePlotPlayer player, double amount) {
this.econ.depositPlayer(((BukkitOfflinePlayer) player).player, amount);
}
@Override
public boolean hasPermission(String world, String player, String perm) {
@Override public boolean hasPermission(String world, String player, String perm) {
return this.perms.playerHas(world, Bukkit.getOfflinePlayer(player), perm);
}
@Override
public double getBalance(PlotPlayer player) {
@Override public double getBalance(PlotPlayer player) {
return this.econ.getBalance(player.getName());
}

View File

@ -0,0 +1,106 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.events.*;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.flag.Flag;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.util.EventUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.UUID;
public class BukkitEventUtil extends EventUtil {
public Player getPlayer(PlotPlayer player) {
if (player instanceof BukkitPlayer) {
return ((BukkitPlayer) player).player;
}
return null;
}
public boolean callEvent(Event event) {
Bukkit.getServer().getPluginManager().callEvent(event);
return !(event instanceof Cancellable) || !((Cancellable) event).isCancelled();
}
@Override public boolean callClaim(PlotPlayer player, Plot plot, boolean auto) {
return callEvent(new PlayerClaimPlotEvent(getPlayer(player), plot, auto));
}
@Override public boolean callTeleport(PlotPlayer player, Location from, Plot plot) {
return callEvent(new PlayerTeleportToPlotEvent(getPlayer(player), from, plot));
}
@Override public boolean callComponentSet(Plot plot, String component) {
return callEvent(new PlotComponentSetEvent(plot, component));
}
@Override public boolean callClear(Plot plot) {
return callEvent(new PlotClearEvent(plot));
}
@Override public void callDelete(Plot plot) {
callEvent(new PlotDeleteEvent(plot));
}
@Override public boolean callFlagAdd(Flag flag, Plot plot) {
return callEvent(new PlotFlagAddEvent(flag, plot));
}
@Override public boolean callFlagRemove(Flag<?> flag, Plot plot, Object value) {
return callEvent(new PlotFlagRemoveEvent(flag, plot));
}
@Override public boolean callMerge(Plot plot, ArrayList<PlotId> plots) {
return callEvent(new PlotMergeEvent(BukkitUtil.getWorld(plot.getWorldName()), plot, plots));
}
@Override public boolean callUnlink(PlotArea area, ArrayList<PlotId> plots) {
return callEvent(new PlotUnlinkEvent(BukkitUtil.getWorld(area.worldname), area, plots));
}
@Override public void callEntry(PlotPlayer player, Plot plot) {
callEvent(new PlayerEnterPlotEvent(getPlayer(player), plot));
}
@Override public void callLeave(PlotPlayer player, Plot plot) {
callEvent(new PlayerLeavePlotEvent(getPlayer(player), plot));
}
@Override public void callDenied(PlotPlayer initiator, Plot plot, UUID player, boolean added) {
callEvent(new PlayerPlotDeniedEvent(getPlayer(initiator), plot, player, added));
}
@Override public void callTrusted(PlotPlayer initiator, Plot plot, UUID player, boolean added) {
callEvent(new PlayerPlotTrustedEvent(getPlayer(initiator), plot, player, added));
}
@Override public void callMember(PlotPlayer initiator, Plot plot, UUID player, boolean added) {
callEvent(new PlayerPlotHelperEvent(getPlayer(initiator), plot, player, added));
}
@Override
public boolean callOwnerChange(PlotPlayer initiator, Plot plot, UUID oldOwner, UUID newOwner,
boolean hasOldOwner) {
return callEvent(
new PlotChangeOwnerEvent(getPlayer(initiator), plot, oldOwner, newOwner, hasOldOwner));
}
@Override public boolean callFlagRemove(Flag flag, Object object, PlotCluster cluster) {
return callEvent(new ClusterFlagRemoveEvent(flag, cluster));
}
@Override @Nullable public Rating callRating(PlotPlayer player, Plot plot, Rating rating) {
PlotRateEvent event = new PlotRateEvent(player, rating, plot);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return null;
}
return event.getRating();
}
}

View File

@ -1,32 +1,14 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import java.util.HashSet;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.material.Directional;
import org.bukkit.material.MaterialData;
import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils;
import com.github.intellectualsites.plotsquared.plot.object.RegionWrapper;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.util.expiry.PlotAnalysis;
public class BukkitHybridUtils extends HybridUtils {
@Override
public void analyzeRegion(final String world, final RegionWrapper region, final RunnableVal<PlotAnalysis> whenDone) {
@Override public void analyzeRegion(final String world, final RegionWrapper region,
final RunnableVal<PlotAnalysis> whenDone) {
// int diff, int variety, int vertices, int rotation, int height_sd
/*
* diff: compare to base by looping through all blocks
@ -39,9 +21,9 @@ public class BukkitHybridUtils extends HybridUtils {
* - recheck each block
*
*/
/* TODO: Redo
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
final World worldObj = Bukkit.getWorld(world);
final ChunkGenerator gen = worldObj.getGenerator();
@ -49,11 +31,10 @@ public class BukkitHybridUtils extends HybridUtils {
return;
}
final BiomeGrid nullBiomeGrid = new BiomeGrid() {
@Override
public void setBiome(int a, int b, Biome c) {}
@Override public void setBiome(int a, int b, Biome c) {
}
@Override
public Biome getBiome(int a, int b) {
@Override public Biome getBiome(int a, int b) {
return null;
}
};
@ -80,15 +61,14 @@ public class BukkitHybridUtils extends HybridUtils {
final short[][][] newBlocks = new short[256][width][length];
final Runnable run = new Runnable() {
@Override
public void run() {
@Override public void run() {
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
@Override public void run(int[] value) {
// [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
int X = value[0];
int Z = value[1];
short[][] result = gen.generateExtBlockSections(worldObj, r, X, Z, nullBiomeGrid);
short[][] result =
gen.generateExtBlockSections(worldObj, r, X, Z, nullBiomeGrid);
int xb = (X << 4) - bx;
int zb = (Z << 4) - bz;
for (int i = 0; i < result.length; i++) {
@ -123,11 +103,9 @@ public class BukkitHybridUtils extends HybridUtils {
}
}, new Runnable() {
@Override
public void run() {
@Override public void run() {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
int size = width * length;
int[] changes = new int[size];
int[] faces = new int[size];
@ -149,7 +127,8 @@ public class BukkitHybridUtils extends HybridUtils {
} else {
// check vertices
// modifications_adjacent
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1 && y < 255) {
if (x > 0 && z > 0 && y > 0 && x < width - 1
&& z < length - 1 && y < 255) {
if (newBlocks[y - 1][x][z] == 0) {
faces[i]++;
}
@ -170,12 +149,17 @@ public class BukkitHybridUtils extends HybridUtils {
}
}
Material material = Material.getMaterial(now);
Class<? extends MaterialData> md = material.getData();
if (md.equals(Directional.class)) {
data[i] += 8;
} else if (!md.equals(MaterialData.class)) {
data[i]++;
Material material =
Material.getMaterial(now);
if (material != null) {
Class<? extends MaterialData> md =
material.getData();
if (md.equals(Directional.class)) {
data[i] += 8;
} else if (!md
.equals(MaterialData.class)) {
data[i]++;
}
}
types.add(now);
}
@ -195,11 +179,14 @@ public class BukkitHybridUtils extends HybridUtils {
analysis.air = (int) (MathMan.getMean(air) * 100);
analysis.variety = (int) (MathMan.getMean(variety) * 100);
analysis.changes_sd = (int) MathMan.getSD(changes, analysis.changes);
analysis.faces_sd = (int) MathMan.getSD(faces, analysis.faces);
analysis.changes_sd =
(int) MathMan.getSD(changes, analysis.changes);
analysis.faces_sd =
(int) MathMan.getSD(faces, analysis.faces);
analysis.data_sd = (int) MathMan.getSD(data, analysis.data);
analysis.air_sd = (int) MathMan.getSD(air, analysis.air);
analysis.variety_sd = (int) MathMan.getSD(variety, analysis.variety);
analysis.variety_sd =
(int) MathMan.getSD(variety, analysis.variety);
System.gc();
System.gc();
whenDone.value = analysis;
@ -215,8 +202,7 @@ public class BukkitHybridUtils extends HybridUtils {
MainUtil.initCache();
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
@Override public void run(int[] value) {
int X = value[0];
int Z = value[1];
worldObj.loadChunk(X, Z);
@ -265,12 +251,12 @@ public class BukkitHybridUtils extends HybridUtils {
worldObj.unloadChunkRequest(X, Z, true);
}
}, new Runnable() {
@Override
public void run() {
@Override public void run() {
TaskManager.runTaskAsync(run);
}
}, 5);
}
});
*/
}
}

View File

@ -1,12 +1,13 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.object.PlotInventory;
import com.intellectualcrafters.plot.object.PlotItemStack;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.InventoryUtil;
import com.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotInventory;
import com.github.intellectualsites.plotsquared.plot.object.PlotItemStack;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.InventoryUtil;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
@ -23,7 +24,7 @@ public class BukkitInventoryUtil extends InventoryUtil {
if (item == null) {
return null;
}
ItemStack stack = new ItemStack(item.id, item.amount, item.data);
ItemStack stack = new ItemStack(BukkitUtil.getMaterial(item.getPlotBlock()), item.amount);
ItemMeta meta = null;
if (item.name != null) {
meta = stack.getItemMeta();
@ -45,8 +46,7 @@ public class BukkitInventoryUtil extends InventoryUtil {
return stack;
}
@Override
public void open(PlotInventory inv) {
@Override public void open(PlotInventory inv) {
BukkitPlayer bp = (BukkitPlayer) inv.player;
Inventory inventory = Bukkit.createInventory(null, inv.size * 9, inv.getTitle());
PlotItemStack[] items = inv.getItems();
@ -56,22 +56,18 @@ public class BukkitInventoryUtil extends InventoryUtil {
inventory.setItem(i, getItem(item));
}
}
inv.player.setMeta("inventory", inv);
bp.player.openInventory(inventory);
}
@Override
public void close(PlotInventory inv) {
@Override public void close(PlotInventory inv) {
if (!inv.isOpen()) {
return;
}
inv.player.deleteMeta("inventory");
BukkitPlayer bp = (BukkitPlayer) inv.player;
bp.player.closeInventory();
}
@Override
public void setItem(PlotInventory inv, int index, PlotItemStack item) {
@Override public void setItem(PlotInventory inv, int index, PlotItemStack item) {
BukkitPlayer bp = (BukkitPlayer) inv.player;
InventoryView opened = bp.player.getOpenInventory();
if (!inv.isOpen()) {
@ -85,7 +81,8 @@ public class BukkitInventoryUtil extends InventoryUtil {
if (item == null) {
return null;
}
int id = item.getTypeId();
// int id = item.getTypeId();
Material id = item.getType();
short data = item.getDurability();
int amount = item.getAmount();
String name = null;
@ -100,11 +97,10 @@ public class BukkitInventoryUtil extends InventoryUtil {
lore = itemLore.toArray(new String[itemLore.size()]);
}
}
return new PlotItemStack(id, data, amount, name, lore);
return new PlotItemStack(id.name(), amount, name, lore);
}
@Override
public PlotItemStack[] getItems(PlotPlayer player) {
@Override public PlotItemStack[] getItems(PlotPlayer player) {
BukkitPlayer bp = (BukkitPlayer) player;
PlayerInventory inv = bp.player.getInventory();
PlotItemStack[] items = new PlotItemStack[36];
@ -114,13 +110,13 @@ public class BukkitInventoryUtil extends InventoryUtil {
return items;
}
@Override
public boolean isOpen(PlotInventory inv) {
@Override public boolean isOpen(PlotInventory inv) {
if (!inv.isOpen()) {
return false;
}
BukkitPlayer bp = (BukkitPlayer) inv.player;
InventoryView opened = bp.player.getOpenInventory();
return inv.isOpen() && opened.getType() == InventoryType.CRAFTING && opened.getTitle() == null;
return inv.isOpen() && opened.getType() == InventoryType.CRAFTING
&& opened.getTitle() == null;
}
}

View File

@ -0,0 +1,828 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.plot.object.LegacyPlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.StringPlotBlock;
import com.github.intellectualsites.plotsquared.plot.util.LegacyMappings;
import com.github.intellectualsites.plotsquared.plot.util.StringComparison;
import lombok.*;
import org.bukkit.Material;
import java.util.*;
import java.util.stream.Collectors;
/**
* Borrowed from https://github.com/Phoenix616/IDConverter/blob/master/mappings/src/main/java/de/themoep/idconverter/IdMappings.java
* Original License:
* <p>
* Minecraft ID mappings
* Copyright (C) 2017 Max Lee (https://github.com/Phoenix616)
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
public final class BukkitLegacyMappings extends LegacyMappings {
private static final LegacyBlock[] BLOCKS =
new LegacyBlock[] {new LegacyBlock(0, "air"), new LegacyBlock(1, "stone"),
new LegacyBlock(1, 1, "stone", "granite"),
new LegacyBlock(1, 2, "stone", "polished_granite"),
new LegacyBlock(1, 3, "stone", "diorite"),
new LegacyBlock(1, 4, "stone", "polished_diorite"),
new LegacyBlock(1, 5, "stone", "andesite"),
new LegacyBlock(1, 6, "stone", "polished_andesite"),
new LegacyBlock(2, "grass", "grass_block"), new LegacyBlock(3, "dirt"),
new LegacyBlock(3, 1, "dirt", "coarse_dirt"), new LegacyBlock(3, 2, "dirt", "podzol"),
new LegacyBlock(4, "cobblestone"), new LegacyBlock(5, "wood", "oak_planks"),
new LegacyBlock(5, 1, "wood", "spruce_planks"),
new LegacyBlock(5, 2, "wood", "birch_planks"),
new LegacyBlock(5, 3, "wood", "jungle_planks"),
new LegacyBlock(5, 4, "wood", "acacia_planks"),
new LegacyBlock(5, 5, "wood", "dark_oak_planks"),
new LegacyBlock(6, "sapling", "oak_sapling"),
new LegacyBlock(6, 1, "sapling", "spruce_sapling"),
new LegacyBlock(6, 2, "sapling", "birch_sapling"),
new LegacyBlock(6, 3, "sapling", "jungle_sapling"),
new LegacyBlock(6, 4, "sapling", "acacia_sapling"),
new LegacyBlock(6, 5, "sapling", "dark_oak_sapling"), new LegacyBlock(7, "bedrock"),
new LegacyBlock(8, "water", "flowing_water"),
new LegacyBlock(9, "stationary_water", "water"),
new LegacyBlock(10, "lava", "flowing_lava"),
new LegacyBlock(11, "stationary_lava", "lava"), new LegacyBlock(12, "sand"),
new LegacyBlock(12, 1, "sand", "red_sand"), new LegacyBlock(13, "gravel"),
new LegacyBlock(14, "gold_ore"), new LegacyBlock(15, "iron_ore"),
new LegacyBlock(16, "coal_ore"), new LegacyBlock(17, "log", "oak_log"),
new LegacyBlock(17, 1, "log", "oak_log"), new LegacyBlock(17, 2, "log", "spruce_log"),
new LegacyBlock(17, 3, "log", "birch_log"), new LegacyBlock(17, 4, "log", "jungle_log"),
new LegacyBlock(17, 5, "log", "oak_bark"), new LegacyBlock(17, 6, "log", "spruce_bark"),
new LegacyBlock(17, 7, "log", "birch_bark"),
new LegacyBlock(17, 8, "log", "jungle_bark"),
new LegacyBlock(18, "leaves", "oak_leaves"),
new LegacyBlock(18, 1, "leaves", "spruce_leaves"),
new LegacyBlock(18, 2, "leaves", "birch_leaves"),
new LegacyBlock(18, 3, "leaves", "jungle_leaves"), new LegacyBlock(19, "sponge"),
new LegacyBlock(19, 1, "sponge", "wet_sponge"), new LegacyBlock(20, "glass"),
new LegacyBlock(21, "lapis_ore"), new LegacyBlock(22, "lapis_block"),
new LegacyBlock(23, "dispenser"), new LegacyBlock(24, "sandstone"),
new LegacyBlock(24, 1, "sandstone", "chisled_sandstone"),
new LegacyBlock(24, 2, "sandstone", "cut_sandstone"), new LegacyBlock(25, "note_block"),
new LegacyBlock(26, "bed_block"), new LegacyBlock(27, "powered_rail"),
new LegacyBlock(28, "detector_rail"),
new LegacyBlock(29, "piston_sticky_base", "sticky_piston"),
new LegacyBlock(30, "web", "cobweb"), new LegacyBlock(31, "long_grass", "dead_bush"),
new LegacyBlock(31, 1, "long_grass", "grass"),
new LegacyBlock(31, 2, "long_grass", "fern"), new LegacyBlock(32, "dead_bush"),
new LegacyBlock(33, "piston_base", "piston"),
new LegacyBlock(34, "piston_extension", "piston_head"),
new LegacyBlock(35, "wool", "white_wool"),
new LegacyBlock(35, 1, "wool", "orange_wool"),
new LegacyBlock(35, 2, "wool", "magenta_wool"),
new LegacyBlock(35, 3, "wool", "light_blue_wool"),
new LegacyBlock(35, 4, "wool", "yellow_wool"),
new LegacyBlock(35, 5, "wool", "lime_wool"),
new LegacyBlock(35, 6, "wool", "pink_wool"),
new LegacyBlock(35, 7, "wool", "gray_wool"),
new LegacyBlock(35, 8, "wool", "light_gray_wool"),
new LegacyBlock(35, 9, "wool", "cyan_wool"),
new LegacyBlock(35, 10, "wool", "purple_wool"),
new LegacyBlock(35, 11, "wool", "blue_wool"),
new LegacyBlock(35, 12, "wool", "brown_wool"),
new LegacyBlock(35, 13, "wool", "green_wool"),
new LegacyBlock(35, 14, "wool", "red_wool"),
new LegacyBlock(35, 15, "wool", "black_wool"),
new LegacyBlock(36, "piston_moving_piece", "moving_piston"),
new LegacyBlock(37, "yellow_flower", "dandelion"),
new LegacyBlock(38, "red_rose", "poppy"),
new LegacyBlock(38, 1, "red_rose", "blue_orchid"),
new LegacyBlock(38, 2, "red_rose", "allium"),
new LegacyBlock(38, 3, "red_rose", "azure_bluet"),
new LegacyBlock(38, 4, "red_rose", "red_tulip"),
new LegacyBlock(38, 5, "red_rose", "orange_tulip"),
new LegacyBlock(38, 6, "red_rose", "white_tulip"),
new LegacyBlock(38, 7, "red_rose", "pink_tulip"),
new LegacyBlock(38, 8, "red_rose", "oxeye_daisy"),
new LegacyBlock(39, "brown_mushroom"), new LegacyBlock(40, "red_mushroom"),
new LegacyBlock(41, "gold_block"), new LegacyBlock(42, "iron_block"),
new LegacyBlock(43, "double_step"),
new LegacyBlock(43, 6, "double_step", "smooth_quartz"),
new LegacyBlock(43, 8, "double_step", "smooth_stone"),
new LegacyBlock(43, 9, "double_step", "smooth_sandstone"),
new LegacyBlock(44, "step", "stone_slab"),
new LegacyBlock(44, 1, "step", "sandstone_slab"),
new LegacyBlock(44, 2, "step", "petrified_oak_slab"),
new LegacyBlock(44, 3, "step", "cobblestone_slab"),
new LegacyBlock(44, 4, "step", "brick_slab"),
new LegacyBlock(44, 5, "step", "stone_brick_slab"),
new LegacyBlock(44, 6, "step", "nether_brick_slab"),
new LegacyBlock(44, 7, "step", "quartz_slab"), new LegacyBlock(45, "brick", "bricks"),
new LegacyBlock(46, "tnt"), new LegacyBlock(47, "bookshelf"),
new LegacyBlock(48, "mossy_cobblestone"), new LegacyBlock(49, "obsidian"),
new LegacyBlock(50, "torch"), new LegacyBlock(50, 1, "torch", "wall_torch"),
new LegacyBlock(50, 2, "torch", "wall_torch"),
new LegacyBlock(50, 3, "torch", "wall_torch"),
new LegacyBlock(50, 4, "torch", "wall_torch"), new LegacyBlock(50, 5, "torch"),
new LegacyBlock(51, "fire"), new LegacyBlock(52, "mob_spawner"),
new LegacyBlock(53, "wood_stairs", "oak_stairs"), new LegacyBlock(54, "chest", "chest"),
new LegacyBlock(55, "redstone_wire"), new LegacyBlock(56, "diamond_ore"),
new LegacyBlock(57, "diamond_block"),
new LegacyBlock(58, "workbench", "crafting_table"),
new LegacyBlock(59, "crops", "wheat"), new LegacyBlock(60, "soil", "farmland"),
new LegacyBlock(61, "furnace"), new LegacyBlock(62, "burning_furnace"),
new LegacyBlock(63, "sign_post", "sign"),
new LegacyBlock(64, "wooden_door", "oak_door"), new LegacyBlock(65, "ladder"),
new LegacyBlock(66, "rails", "rail"), new LegacyBlock(67, "cobblestone_stairs"),
new LegacyBlock(68, "wall_sign"), new LegacyBlock(69, "lever"),
new LegacyBlock(70, "stone_plate", "stone_pressure_plate"),
new LegacyBlock(71, "iron_door_block", "iron_door"),
new LegacyBlock(72, "wood_plate", "oak_pressure_plate"),
new LegacyBlock(73, "redstone_ore"), new LegacyBlock(74, "glowing_redstone_ore"),
new LegacyBlock(75, "redstone_torch_off"),
new LegacyBlock(76, "redstone_torch_on", "redstone_torch"),
new LegacyBlock(76, 1, "redstone_torch_on", "redstone_wall_torch"),
new LegacyBlock(76, 2, "redstone_torch_on", "redstone_wall_torch"),
new LegacyBlock(76, 3, "redstone_torch_on", "redstone_wall_torch"),
new LegacyBlock(76, 4, "redstone_torch_on", "redstone_wall_torch"),
new LegacyBlock(76, 5, "redstone_torch_on", "redstone_torch"),
new LegacyBlock(77, "stone_button"), new LegacyBlock(78, "snow"),
new LegacyBlock(79, "ice"), new LegacyBlock(80, "snow_block"),
new LegacyBlock(81, "cactus"), new LegacyBlock(82, "clay"),
new LegacyBlock(83, "sugar_cane_block", "sugar_cane"), new LegacyBlock(84, "jukebox"),
new LegacyBlock(85, "fence", "oak_fence"),
new LegacyBlock(86, "pumpkin", "carved_pumpkin"), new LegacyBlock(87, "netherrack"),
new LegacyBlock(88, "soul_sand"), new LegacyBlock(89, "glowstone"),
new LegacyBlock(90, "portal"), new LegacyBlock(91, "jack_o_lantern"),
new LegacyBlock(92, "cake_block", "cake"), new LegacyBlock(93, "diode_block_off"),
new LegacyBlock(94, "diode_block_on", "repeater"),
new LegacyBlock(95, "stained_glass", "white_stained_glass"),
new LegacyBlock(95, 1, "stained_glass", "orange_stained_glass"),
new LegacyBlock(95, 2, "stained_glass", "magenta_stained_glass"),
new LegacyBlock(95, 3, "stained_glass", "light_blue_stained_glass"),
new LegacyBlock(95, 4, "stained_glass", "yellow_stained_glass"),
new LegacyBlock(95, 5, "stained_glass", "lime_stained_glass"),
new LegacyBlock(95, 6, "stained_glass", "pink_stained_glass"),
new LegacyBlock(95, 7, "stained_glass", "gray_stained_glass"),
new LegacyBlock(95, 8, "stained_glass", "light_gray_stained_glass"),
new LegacyBlock(95, 9, "stained_glass", "cyan_stained_glass"),
new LegacyBlock(95, 10, "stained_glass", "purple_stained_glass"),
new LegacyBlock(95, 11, "stained_glass", "blue_stained_glass"),
new LegacyBlock(95, 12, "stained_glass", "brown_stained_glass"),
new LegacyBlock(95, 13, "stained_glass", "green_stained_glass"),
new LegacyBlock(95, 14, "stained_glass", "red_stained_glass"),
new LegacyBlock(95, 15, "stained_glass", "black_stained_glass"),
new LegacyBlock(96, "trap_door", "oak_trapdoor"),
new LegacyBlock(97, "monster_eggs", "infested_stone"),
new LegacyBlock(97, 1, "monster_eggs", "infested_coblestone"),
new LegacyBlock(97, 2, "monster_eggs", "infested_stone_bricks"),
new LegacyBlock(97, 3, "monster_eggs", "infested_mossy_stone_bricks"),
new LegacyBlock(97, 4, "monster_eggs", "infested_crcked_stone_bricks"),
new LegacyBlock(97, 5, "monster_eggs", "infested_chiseled_stone_bricks"),
new LegacyBlock(98, "smooth_brick", "stone_bricks"),
new LegacyBlock(98, 1, "smooth_brick", "mossy_stone_bricks"),
new LegacyBlock(98, 2, "smooth_brick", "cracked_stone_bricks"),
new LegacyBlock(98, 3, "smooth_brick", "chiseled_bricks"),
new LegacyBlock(99, "huge_mushroom_1", "brown_mushroom_block"),
new LegacyBlock(99, 1, "huge_mushroom_1"), new LegacyBlock(99, 2, "huge_mushroom_1"),
new LegacyBlock(99, 3, "huge_mushroom_1"), new LegacyBlock(99, 4, "huge_mushroom_1"),
new LegacyBlock(99, 5, "huge_mushroom_1"), new LegacyBlock(99, 6, "huge_mushroom_1"),
new LegacyBlock(99, 7, "huge_mushroom_1"), new LegacyBlock(99, 8, "huge_mushroom_1"),
new LegacyBlock(99, 9, "huge_mushroom_1"),
new LegacyBlock(99, 10, "huge_mushroom_1", "mushroom_stem"),
new LegacyBlock(99, 14, "huge_mushroom_1"), new LegacyBlock(99, 15, "huge_mushroom_1"),
new LegacyBlock(100, "huge_mushroom_2", "red_mushroom_block"),
new LegacyBlock(100, 1, "huge_mushroom_2"), new LegacyBlock(100, 2, "huge_mushroom_2"),
new LegacyBlock(100, 3, "huge_mushroom_2"), new LegacyBlock(100, 4, "huge_mushroom_2"),
new LegacyBlock(100, 5, "huge_mushroom_2"), new LegacyBlock(100, 6, "huge_mushroom_2"),
new LegacyBlock(100, 7, "huge_mushroom_2"), new LegacyBlock(100, 8, "huge_mushroom_2"),
new LegacyBlock(100, 9, "huge_mushroom_2"),
new LegacyBlock(100, 10, "huge_mushroom_2", "mushroom_stem"),
new LegacyBlock(100, 14, "huge_mushroom_2"),
new LegacyBlock(100, 15, "huge_mushroom_2"),
new LegacyBlock(101, "iron_fence", "ironbars"),
new LegacyBlock(102, "thin_glass", "glass_pane"), new LegacyBlock(103, "melon_block"),
new LegacyBlock(104, "pumpkin_stem"), new LegacyBlock(105, "melon_stem"),
new LegacyBlock(106, "vine"), new LegacyBlock(107, "fence_gate", "oak_fence_gate"),
new LegacyBlock(108, "brick_stairs"),
new LegacyBlock(109, "smooth_stairs", "stone_brick_stairs"),
new LegacyBlock(110, "mycel", "mycelium"),
new LegacyBlock(111, "water_lily", "lily_pad"),
new LegacyBlock(112, "nether_brick", "nether_bricks"),
new LegacyBlock(113, "nether_fence", "nether_brick_fence"),
new LegacyBlock(114, "nether_brick_stairs"),
new LegacyBlock(115, "nether_warts", "nether_wart"),
new LegacyBlock(116, "enchantment_table", "enchanting_table"),
new LegacyBlock(117, "brewing_stand"), new LegacyBlock(118, "cauldron"),
new LegacyBlock(119, "ender_portal", "end_portal"),
new LegacyBlock(120, "ender_portal_frame", "end_portal_frame"),
new LegacyBlock(121, "ender_stone", "end_stone"), new LegacyBlock(122, "dragon_egg"),
new LegacyBlock(123, "redstone_lamp_off"),
new LegacyBlock(124, "redstone_lamp_on", "redstone_lamp"),
new LegacyBlock(125, "wood_double_step"), new LegacyBlock(125, 1, "wood_double_step"),
new LegacyBlock(125, 2, "wood_double_step"),
new LegacyBlock(125, 3, "wood_double_step"),
new LegacyBlock(125, 4, "wood_double_step"),
new LegacyBlock(125, 5, "wood_double_step"),
new LegacyBlock(126, "wood_step", "oak_slab"),
new LegacyBlock(126, 1, "wood_step", "spruce_slab"),
new LegacyBlock(126, 2, "wood_step", "birch_slab"),
new LegacyBlock(126, 3, "wood_step", "jungle_slab"),
new LegacyBlock(126, 4, "wood_step", "acacia_slab"),
new LegacyBlock(126, 5, "wood_step", "dark_oak_slab"), new LegacyBlock(127, "cocoa"),
new LegacyBlock(128, "sandstone_stairs"), new LegacyBlock(129, "emerald_ore"),
new LegacyBlock(130, "ender_chest"), new LegacyBlock(131, "tripwire_hook"),
new LegacyBlock(132, "tripwire"), new LegacyBlock(133, "emerald_block"),
new LegacyBlock(134, "spruce_wood_stairs", "spruce_stairs"),
new LegacyBlock(135, "birch_wood_stairs", "birch_stairs"),
new LegacyBlock(136, "jungle_wood_stairs", "jungle_stairs"),
new LegacyBlock(137, "command", "command_block"), new LegacyBlock(138, "beacon"),
new LegacyBlock(139, "cobble_wall", "cobblestone_wall"),
new LegacyBlock(139, 1, "cobble_wall", "mossy_cobblestone_wall"),
new LegacyBlock(140, "flower_pot"), new LegacyBlock(141, "carrot", "carrots"),
new LegacyBlock(142, "potato", "potatoes"),
new LegacyBlock(143, "wood_button", "oak_button"),
new LegacyBlock(144, "skull", "skeleton_skull"),
new LegacyBlock(144, 1, "skull", "skeleton_wall_skull"),
new LegacyBlock(144, 2, "skull", "skeleton_wall_skull"),
new LegacyBlock(144, 3, "skull", "skeleton_wall_skull"),
new LegacyBlock(144, 4, "skull", "skeleton_wall_skull"),
new LegacyBlock(144, 5, "skull", "skeleton_wall_skull"), new LegacyBlock(145, "anvil"),
new LegacyBlock(145, 1, "anvil", "chipped_anvil"),
new LegacyBlock(145, 2, "anvil", "damaged_anvil"),
new LegacyBlock(146, "trapped_chest"),
new LegacyBlock(147, "gold_plate", "light_weighted_pressure_plate"),
new LegacyBlock(148, "iron_plate", "heavy_weighted_pressure_plate"),
new LegacyBlock(149, "redstone_comparator_off"),
new LegacyBlock(150, "redstone_comparator_on", "comparator"),
new LegacyBlock(151, "daylight_detector"), new LegacyBlock(152, "redstone_block"),
new LegacyBlock(153, "quartz_ore", "nether_quartz_ore"), new LegacyBlock(154, "hopper"),
new LegacyBlock(155, "quartz_block"), new LegacyBlock(156, "quartz_stairs"),
new LegacyBlock(157, "activator_rail"), new LegacyBlock(158, "dropper"),
new LegacyBlock(159, "stained_clay", "white_terracotta"),
new LegacyBlock(159, 1, "stained_clay", "orange_terracotta"),
new LegacyBlock(159, 2, "stained_clay", "magenta_terracotta"),
new LegacyBlock(159, 3, "stained_clay", "light_blue_terracotta"),
new LegacyBlock(159, 4, "stained_clay", "yellow_terracotta"),
new LegacyBlock(159, 5, "stained_clay", "lime_terracotta"),
new LegacyBlock(159, 6, "stained_clay", "pink_terracotta"),
new LegacyBlock(159, 7, "stained_clay", "gray_terracotta"),
new LegacyBlock(159, 8, "stained_clay", "light_gray_terracotta"),
new LegacyBlock(159, 9, "stained_clay", "cyan_terracotta"),
new LegacyBlock(159, 10, "stained_clay", "purple_terracotta"),
new LegacyBlock(159, 11, "stained_clay", "blue_terracotta"),
new LegacyBlock(159, 12, "stained_clay", "brown_terracotta"),
new LegacyBlock(159, 13, "stained_clay", "green_terracotta"),
new LegacyBlock(159, 14, "stained_clay", "red_terracotta"),
new LegacyBlock(159, 15, "stained_clay", "black_terracotta"),
new LegacyBlock(160, "stained_glass_pane", "white_stained_glass_pane"),
new LegacyBlock(160, 1, "stained_glass_pane", "orange_stained_glass_pane"),
new LegacyBlock(160, 2, "stained_glass_pane", "magenta_stained_glass_pane"),
new LegacyBlock(160, 3, "stained_glass_pane", "light_blue_stained_glass_pane"),
new LegacyBlock(160, 4, "stained_glass_pane", "yellow_stained_glass_pane"),
new LegacyBlock(160, 5, "stained_glass_pane", "lime_stained_glass_pane"),
new LegacyBlock(160, 6, "stained_glass_pane", "pink_stained_glass_pane"),
new LegacyBlock(160, 7, "stained_glass_pane", "gray_stained_glass_pane"),
new LegacyBlock(160, 8, "stained_glass_pane", "light_gray_stained_glass_pane"),
new LegacyBlock(160, 9, "stained_glass_pane", "cyan_stained_glass_pane"),
new LegacyBlock(160, 10, "stained_glass_pane", "purple_stained_glass_pane"),
new LegacyBlock(160, 11, "stained_glass_pane", "blue_stained_glass_pane"),
new LegacyBlock(160, 12, "stained_glass_pane", "brown_stained_glass_pane"),
new LegacyBlock(160, 13, "stained_glass_pane", "green_stained_glass_pane"),
new LegacyBlock(160, 14, "stained_glass_pane", "red_stained_glass_pane"),
new LegacyBlock(160, 15, "stained_glass_pane", "black_stained_glass_pane"),
new LegacyBlock(161, "leaves_2", "acacia_leaves"),
new LegacyBlock(161, 1, "leaves_2", "dark_oak_leaves"),
new LegacyBlock(162, "log_2", "acacia_log"),
new LegacyBlock(162, 1, "log_2", "spruce_log"),
new LegacyBlock(162, 2, "log_2", "birch_log"),
new LegacyBlock(162, 3, "log_2", "jungle_log"),
new LegacyBlock(163, "acacia_stairs", "acacia_stairs"),
new LegacyBlock(164, "dark_oak_stairs", "dark_oak_stairs"),
new LegacyBlock(165, "slime_block", "slime_block"),
new LegacyBlock(166, "barrier", "barrier"),
new LegacyBlock(167, "iron_trapdoor", "iron_trapdoor"),
new LegacyBlock(168, "prismarine"),
new LegacyBlock(168, 1, "prismarine", "prismarine_bricks"),
new LegacyBlock(168, 2, "prismarine", "dark_prismarine"),
new LegacyBlock(169, "sea_lantern"), new LegacyBlock(170, "hay_block"),
new LegacyBlock(171, "carpet", "white_carpet"),
new LegacyBlock(171, 1, "carpet", "orange_carpet"),
new LegacyBlock(171, 2, "carpet", "magenta_carpet"),
new LegacyBlock(171, 3, "carpet", "light_blue_carpet"),
new LegacyBlock(171, 4, "carpet", "yellow_carpet"),
new LegacyBlock(171, 5, "carpet", "lime_carpet"),
new LegacyBlock(171, 6, "carpet", "pink_carpet"),
new LegacyBlock(171, 7, "carpet", "gray_carpet"),
new LegacyBlock(171, 8, "carpet", "light_gray_carpet"),
new LegacyBlock(171, 9, "carpet", "cyan_carpet"),
new LegacyBlock(171, 10, "carpet", "purple_carpet"),
new LegacyBlock(171, 11, "carpet", "blue_carpet"),
new LegacyBlock(171, 12, "carpet", "brown_carpet"),
new LegacyBlock(171, 13, "carpet", "green_carpet"),
new LegacyBlock(171, 14, "carpet", "red_carpet"),
new LegacyBlock(171, 15, "carpet", "black_carpet"),
new LegacyBlock(172, "hard_clay", "terracotta"), new LegacyBlock(173, "coal_block"),
new LegacyBlock(174, "packed_ice"), new LegacyBlock(175, "double_plant", "sunflower"),
new LegacyBlock(175, 1, "double_plant", "lilac"),
new LegacyBlock(175, 2, "double_plant", "tall_grass"),
new LegacyBlock(175, 3, "double_plant", "large_fern"),
new LegacyBlock(175, 4, "double_plant", "rose_bush"),
new LegacyBlock(175, 5, "double_plant", "peony"),
new LegacyBlock(176, "standing_banner"), new LegacyBlock(177, "wall_banner"),
new LegacyBlock(178, "daylight_detector_inverted"),
new LegacyBlock(179, "red_sandstone", "red_sandstone"),
new LegacyBlock(179, 1, "red_sandstone", "chiseled_red_sandstone"),
new LegacyBlock(179, 2, "red_sandstone", "cut_red_sandstone"),
new LegacyBlock(180, "red_sandstone_stairs"),
new LegacyBlock(181, "double_stone_slab2"),
new LegacyBlock(181, 8, "double_stone_slab2", "smooth_red_sandstone"),
new LegacyBlock(182, "stone_slab2", "red_sandstone_slab"),
new LegacyBlock(183, "spruce_fence_gate"), new LegacyBlock(184, "birch_fence_gate"),
new LegacyBlock(185, "jungle_fence_gate"), new LegacyBlock(186, "dark_oak_fence_gate"),
new LegacyBlock(187, "acacia_fence_gate"), new LegacyBlock(188, "spruce_fence"),
new LegacyBlock(189, "birch_fence"), new LegacyBlock(190, "jungle_fence"),
new LegacyBlock(191, "dark_oak_fence"), new LegacyBlock(192, "acacia_fence"),
new LegacyBlock(193, "spruce_door"), new LegacyBlock(194, "birch_door"),
new LegacyBlock(195, "jungle_door"), new LegacyBlock(196, "acacia_door"),
new LegacyBlock(197, "dark_oak_door"), new LegacyBlock(198, "end_rod"),
new LegacyBlock(199, "chorus_plant"), new LegacyBlock(200, "chorus_flower"),
new LegacyBlock(201, "purpur_block"), new LegacyBlock(202, "purpur_pillar"),
new LegacyBlock(203, "purpur_stairs"), new LegacyBlock(204, "purpur_double_slab"),
new LegacyBlock(205, "purpur_slab"),
new LegacyBlock(206, "end_bricks", "end_stone_bricks"),
new LegacyBlock(207, "beetroot_block", "beetroots"), new LegacyBlock(208, "grass_path"),
new LegacyBlock(209, "end_gateway"),
new LegacyBlock(210, "command_repeating", "repeating_command_block"),
new LegacyBlock(211, "command_chain", "chain_command_block"),
new LegacyBlock(212, "frosted_ice"), new LegacyBlock(213, "magma", "magma_block"),
new LegacyBlock(214, "nether_wart_block"),
new LegacyBlock(215, "red_nether_brick", "red_nether_bricks"),
new LegacyBlock(216, "bone_block"), new LegacyBlock(217, "structure_void"),
new LegacyBlock(218, "observer"), new LegacyBlock(219, "white_shulker_box"),
new LegacyBlock(220, "orange_shulker_box"), new LegacyBlock(221, "magenta_shulker_box"),
new LegacyBlock(222, "light_blue_shulker_box"),
new LegacyBlock(223, "yellow_shulker_box"), new LegacyBlock(224, "lime_shulker_box"),
new LegacyBlock(225, "pink_shulker_box"), new LegacyBlock(226, "gray_shulker_box"),
new LegacyBlock(227, "silver_shulker_box", "light_gray_shulker_box"),
new LegacyBlock(228, "cyan_shulker_box"), new LegacyBlock(229, "purple_shulker_box"),
new LegacyBlock(230, "blue_shulker_box"), new LegacyBlock(231, "brown_shulker_box"),
new LegacyBlock(232, "green_shulker_box"), new LegacyBlock(233, "red_shulker_box"),
new LegacyBlock(234, "black_shulker_box"),
new LegacyBlock(235, "white_glazed_terracotta"),
new LegacyBlock(236, "orange_glazed_terracotta"),
new LegacyBlock(237, "magenta_glazed_terracotta"),
new LegacyBlock(238, "light_blue_glazed_terracotta"),
new LegacyBlock(239, "yellow_glazed_terracotta"),
new LegacyBlock(240, "lime_glazed_terracotta"),
new LegacyBlock(241, "pink_glazed_terracotta"),
new LegacyBlock(242, "gray_glazed_terracotta"),
new LegacyBlock(243, "silver_glazed_terracotta", "light_gray_glazed_terracotta"),
new LegacyBlock(244, "cyan_glazed_terracotta"),
new LegacyBlock(245, "purple_glazed_terracotta"),
new LegacyBlock(246, "blue_glazed_terracotta"),
new LegacyBlock(247, "brown_glazed_terracotta"),
new LegacyBlock(248, "green_glazed_terracotta"),
new LegacyBlock(249, "red_glazed_terracotta"),
new LegacyBlock(250, "black_glazed_terracotta"),
new LegacyBlock(251, "concrete", "white_concrete"),
new LegacyBlock(251, 1, "concrete", "orange_concrete"),
new LegacyBlock(251, 2, "concrete", "magenta_concrete"),
new LegacyBlock(251, 3, "concrete", "light_blue_concrete"),
new LegacyBlock(251, 4, "concrete", "yellow_concrete"),
new LegacyBlock(251, 5, "concrete", "lime_concrete"),
new LegacyBlock(251, 6, "concrete", "pink_concrete"),
new LegacyBlock(251, 7, "concrete", "gray_concrete"),
new LegacyBlock(251, 8, "concrete", "light_gray_concrete"),
new LegacyBlock(251, 9, "concrete", "cyan_concrete"),
new LegacyBlock(251, 10, "concrete", "purple_concrete"),
new LegacyBlock(251, 11, "concrete", "blue_concrete"),
new LegacyBlock(251, 12, "concrete", "brown_concrete"),
new LegacyBlock(251, 13, "concrete", "green_concrete"),
new LegacyBlock(251, 14, "concrete", "red_concrete"),
new LegacyBlock(251, 15, "concrete", "black_concrete"),
new LegacyBlock(252, "concrete_powder", "white_concrete_powder"),
new LegacyBlock(252, 1, "concrete_powder", "orange_concrete_powder"),
new LegacyBlock(252, 2, "concrete_powder", "magenta_concrete_powder"),
new LegacyBlock(252, 3, "concrete_powder", "light_blue_concrete_powder"),
new LegacyBlock(252, 4, "concrete_powder", "yellow_concrete_powder"),
new LegacyBlock(252, 5, "concrete_powder", "lime_concrete_powder"),
new LegacyBlock(252, 6, "concrete_powder", "pink_concrete_powder"),
new LegacyBlock(252, 7, "concrete_powder", "gray_concrete_powder"),
new LegacyBlock(252, 8, "concrete_powder", "light_gray_concrete_powder"),
new LegacyBlock(252, 9, "concrete_powder", "cyan_concrete_powder"),
new LegacyBlock(252, 10, "concrete_powder", "purple_concrete_powder"),
new LegacyBlock(252, 11, "concrete_powder", "blue_concrete_powder"),
new LegacyBlock(252, 12, "concrete_powder", "brown_concrete_powder"),
new LegacyBlock(252, 13, "concrete_powder", "green_concrete_powder"),
new LegacyBlock(252, 14, "concrete_powder", "red_concrete_powder"),
new LegacyBlock(252, 15, "concrete_powder", "black_concrete_powder"),
new LegacyBlock(255, "structure_block"),
new LegacyBlock(256, "iron_spade", "iron_shovel"), new LegacyBlock(257, "iron_pickaxe"),
new LegacyBlock(258, "iron_axe"), new LegacyBlock(259, "flint_and_steel"),
new LegacyBlock(260, "apple"), new LegacyBlock(261, "bow"),
new LegacyBlock(262, "arrow"), new LegacyBlock(263, "coal"),
new LegacyBlock(263, 1, "coal", "charcoal"), new LegacyBlock(264, "diamond"),
new LegacyBlock(265, "iron_ingot"), new LegacyBlock(266, "gold_ingot"),
new LegacyBlock(267, "iron_sword"), new LegacyBlock(268, "wood_sword", "wooden_sword"),
new LegacyBlock(269, "wood_spade", "wooden_shovel"),
new LegacyBlock(270, "wood_pickaxe", "wooden_pickaxe"),
new LegacyBlock(271, "wood_axe", "wooden_axe"), new LegacyBlock(272, "stone_sword"),
new LegacyBlock(273, "stone_spade", "stone_shovel"),
new LegacyBlock(274, "stone_pickaxe"), new LegacyBlock(275, "stone_axe"),
new LegacyBlock(276, "diamond_sword"),
new LegacyBlock(277, "diamond_spade", "diamond_shovel"),
new LegacyBlock(278, "diamond_pickaxe"), new LegacyBlock(279, "diamond_axe"),
new LegacyBlock(280, "stick"), new LegacyBlock(281, "bowl"),
new LegacyBlock(282, "mushroom_soup", "mushroom_stew"),
new LegacyBlock(283, "gold_sword", "golden_sword"),
new LegacyBlock(284, "gold_spade", "golden_shovel"),
new LegacyBlock(285, "gold_pickaxe", "golden_pickaxe"),
new LegacyBlock(286, "gold_axe", "golden_axe"), new LegacyBlock(287, "string"),
new LegacyBlock(288, "feather"), new LegacyBlock(289, "sulphur", "gunpowder"),
new LegacyBlock(290, "wood_hoe", "wooden_hoe"), new LegacyBlock(291, "stone_hoe"),
new LegacyBlock(292, "iron_hoe"), new LegacyBlock(293, "diamond_hoe"),
new LegacyBlock(294, "gold_hoe", "golden_hoe"),
new LegacyBlock(295, "seeds", "wheat_seeds"), new LegacyBlock(296, "wheat"),
new LegacyBlock(297, "bread"), new LegacyBlock(298, "leather_helmet"),
new LegacyBlock(299, "leather_chestplate"), new LegacyBlock(300, "leather_leggings"),
new LegacyBlock(301, "leather_boots"), new LegacyBlock(302, "chainmail_helmet"),
new LegacyBlock(303, "chainmail_chestplate"),
new LegacyBlock(304, "chainmail_leggings"), new LegacyBlock(305, "chainmail_boots"),
new LegacyBlock(306, "iron_helmet"), new LegacyBlock(307, "iron_chestplate"),
new LegacyBlock(308, "iron_leggings"), new LegacyBlock(309, "iron_boots"),
new LegacyBlock(310, "diamond_helmet"), new LegacyBlock(311, "diamond_chestplate"),
new LegacyBlock(312, "diamond_leggings"), new LegacyBlock(313, "diamond_boots"),
new LegacyBlock(314, "gold_helmet", "golden_helmet"),
new LegacyBlock(315, "gold_chestplate", "golden_chestplate"),
new LegacyBlock(316, "gold_leggings", "golden_leggings"),
new LegacyBlock(317, "gold_boots", "golden_boots"), new LegacyBlock(318, "flint"),
new LegacyBlock(319, "pork", "porkchop"),
new LegacyBlock(320, "grilled_pork", "cooked_porkchop"),
new LegacyBlock(321, "painting"), new LegacyBlock(322, "golden_apple", "golden_apple"),
new LegacyBlock(322, 1, "golden_apple", "enchanted_golden_apple"),
new LegacyBlock(323, "sign"), new LegacyBlock(324, "wood_door", "oak_door"),
new LegacyBlock(325, "bucket"), new LegacyBlock(326, "water_bucket"),
new LegacyBlock(327, "lava_bucket"), new LegacyBlock(328, "minecart"),
new LegacyBlock(329, "saddle"), new LegacyBlock(330, "iron_door"),
new LegacyBlock(331, "redstone"), new LegacyBlock(332, "snow_ball", "snowball"),
new LegacyBlock(333, "boat", "oak_boat"), new LegacyBlock(334, "leather"),
new LegacyBlock(335, "milk_bucket"), new LegacyBlock(336, "clay_brick", "brick"),
new LegacyBlock(337, "clay_ball"), new LegacyBlock(338, "sugar_cane"),
new LegacyBlock(339, "paper"), new LegacyBlock(340, "book"),
new LegacyBlock(341, "slime_ball"),
new LegacyBlock(342, "storage_minecart", "chest_minecart"),
new LegacyBlock(343, "powered_minecart", "furnace_minecart"),
new LegacyBlock(344, "egg"), new LegacyBlock(345, "compass"),
new LegacyBlock(346, "fishing_rod"), new LegacyBlock(347, "watch", "clock"),
new LegacyBlock(348, "glowstone_dust"), new LegacyBlock(349, "raw_fish", "cod"),
new LegacyBlock(349, 1, "raw_fish", "salmon"),
new LegacyBlock(349, 2, "raw_fish", "tropical_fish"),
new LegacyBlock(349, 3, "raw_fish", "pufferfish"),
new LegacyBlock(350, "cooked_fish", "cooked_cod"),
new LegacyBlock(350, 1, "cooked_fish", "cooked_salmon"),
new LegacyBlock(351, "ink_sack", "ink_sac"),
new LegacyBlock(351, 1, "ink_sack", "rose_red"),
new LegacyBlock(351, 2, "ink_sack", "cactus_green"),
new LegacyBlock(351, 3, "ink_sack", "cocoa_beans"),
new LegacyBlock(351, 4, "ink_sack", "lapis_lazuli"),
new LegacyBlock(351, 5, "ink_sack", "purple_dye"),
new LegacyBlock(351, 6, "ink_sack", "cyan_dye"),
new LegacyBlock(351, 7, "ink_sack", "light_gray_dye"),
new LegacyBlock(351, 8, "ink_sack", "gray_dye"),
new LegacyBlock(351, 9, "ink_sack", "pink_dye"),
new LegacyBlock(351, 10, "ink_sack", "lime_dye"),
new LegacyBlock(351, 11, "ink_sack", "dandelion_yellow"),
new LegacyBlock(351, 12, "ink_sack", "light_blue_dye"),
new LegacyBlock(351, 13, "ink_sack", "magenta_dye"),
new LegacyBlock(351, 14, "ink_sack", "orange_dye"),
new LegacyBlock(351, 15, "ink_sack", "bone_meal"), new LegacyBlock(352, "bone"),
new LegacyBlock(353, "sugar", "sugar"), new LegacyBlock(354, "cake", "cake"),
new LegacyBlock(355, "bed", "white_bed"), new LegacyBlock(355, 1, "bed", "orange_bed"),
new LegacyBlock(355, 2, "bed", "magenta_bed"),
new LegacyBlock(355, 3, "bed", "light_blue_bed"),
new LegacyBlock(355, 4, "bed", "yellow_bed"),
new LegacyBlock(355, 5, "bed", "lime_bed"), new LegacyBlock(355, 6, "bed", "pink_bed"),
new LegacyBlock(355, 7, "bed", "gray_bed"),
new LegacyBlock(355, 8, "bed", "light_gray_bed"),
new LegacyBlock(355, 9, "bed", "cyan_bed"),
new LegacyBlock(355, 10, "bed", "purple_bed"),
new LegacyBlock(355, 11, "bed", "blue_bed"),
new LegacyBlock(355, 12, "bed", "brown_bed"),
new LegacyBlock(355, 13, "bed", "green_bed"),
new LegacyBlock(355, 14, "bed", "red_bed"),
new LegacyBlock(355, 15, "bed", "black_bed"), new LegacyBlock(356, "diode", "repeater"),
new LegacyBlock(357, "cookie", "cookie"), new LegacyBlock(358, "map"),
new LegacyBlock(359, "shears"), new LegacyBlock(360, "melon", "melon"),
new LegacyBlock(361, "pumpkin_seeds", "pumpkin_seeds"),
new LegacyBlock(362, "melon_seeds", "melon_seeds"),
new LegacyBlock(363, "raw_beef", "beef"), new LegacyBlock(364, "cooked_beef"),
new LegacyBlock(365, "raw_chicken", "chicken"), new LegacyBlock(366, "cooked_chicken"),
new LegacyBlock(367, "rotten_flesh"), new LegacyBlock(368, "ender_pearl"),
new LegacyBlock(369, "blaze_rod"), new LegacyBlock(370, "ghast_tear"),
new LegacyBlock(371, "gold_nugget"),
new LegacyBlock(372, "nether_stalk", "nether_wart"),
new LegacyBlock(373, "potion", "potion"), new LegacyBlock(374, "glass_bottle"),
new LegacyBlock(375, "spider_eye"), new LegacyBlock(376, "fermented_spider_eye"),
new LegacyBlock(377, "blaze_powder"), new LegacyBlock(378, "magma_cream"),
new LegacyBlock(379, "brewing_stand_item", "brewing_stand"),
new LegacyBlock(380, "cauldron_item", "cauldron"),
new LegacyBlock(381, "eye_of_ender", "ender_eye"),
new LegacyBlock(382, "speckled_melon"), new LegacyBlock(383, "monster_egg"),
new LegacyBlock(383, 4, "monster_egg", "elder_guardian_spawn_egg"),
new LegacyBlock(383, 5, "monster_egg", "wither_skeleton_spawn_egg"),
new LegacyBlock(383, 6, "monster_egg", "stray_spawn_egg"),
new LegacyBlock(383, 23, "monster_egg", "husk_spawn_egg"),
new LegacyBlock(383, 27, "monster_egg", "zombe_villager_spawn_egg"),
new LegacyBlock(383, 28, "monster_egg", "skeleton_horse_spawn_egg"),
new LegacyBlock(383, 29, "monster_egg", "zombie_horse_spawn_egg"),
new LegacyBlock(383, 31, "monster_egg", "donkey_spawn_egg"),
new LegacyBlock(383, 32, "monster_egg", "mule_spawn_egg"),
new LegacyBlock(383, 34, "monster_egg", "evocation_illager_spawn_egg"),
new LegacyBlock(383, 35, "monster_egg", "vex_spawn_egg"),
new LegacyBlock(383, 36, "monster_egg", "vindication_illager_spawn_egg"),
new LegacyBlock(383, 50, "monster_egg", "creeper_spawn_egg"),
new LegacyBlock(383, 51, "monster_egg", "skeleton_spawn_egg"),
new LegacyBlock(383, 52, "monster_egg", "spider_spawn_egg"),
new LegacyBlock(383, 54, "monster_egg", "zombie_spawn_egg"),
new LegacyBlock(383, 55, "monster_egg", "slime_spawn_egg"),
new LegacyBlock(383, 56, "monster_egg", "ghast_spawn_egg"),
new LegacyBlock(383, 57, "monster_egg", "zombie_pigman_spawn_egg"),
new LegacyBlock(383, 58, "monster_egg", "enderman_spawn_egg"),
new LegacyBlock(383, 59, "monster_egg", "cave_spider_spawn_egg"),
new LegacyBlock(383, 60, "monster_egg", "silverfish_spawn_egg"),
new LegacyBlock(383, 61, "monster_egg", "blaze_spawn_egg"),
new LegacyBlock(383, 62, "monster_egg", "magma_cube_spawn_egg"),
new LegacyBlock(383, 65, "monster_egg", "bat_spawn_egg"),
new LegacyBlock(383, 66, "monster_egg", "witch_spawn_egg"),
new LegacyBlock(383, 67, "monster_egg", "endermite_spawn_egg"),
new LegacyBlock(383, 68, "monster_egg", "guardian_spawn_egg"),
new LegacyBlock(383, 69, "monster_egg", "shulker_spawn_egg"),
new LegacyBlock(383, 90, "monster_egg", "pig_spawn_egg"),
new LegacyBlock(383, 91, "monster_egg", "sheep_spawn_egg"),
new LegacyBlock(383, 92, "monster_egg", "cow_spawn_egg"),
new LegacyBlock(383, 93, "monster_egg", "chicken_spawn_egg"),
new LegacyBlock(383, 94, "monster_egg", "squid_spawn_egg"),
new LegacyBlock(383, 95, "monster_egg", "wolf_spawn_egg"),
new LegacyBlock(383, 96, "monster_egg", "mooshroom_spawn_egg"),
new LegacyBlock(383, 98, "monster_egg", "ocelot_spawn_egg"),
new LegacyBlock(383, 100, "monster_egg", "horse_spawn_egg"),
new LegacyBlock(383, 101, "monster_egg", "rabbit_spawn_egg"),
new LegacyBlock(383, 102, "monster_egg", "polar_bear_spawn_egg"),
new LegacyBlock(383, 103, "monster_egg", "llama_spawn_egg"),
new LegacyBlock(383, 120, "monster_egg", "villager_spawn_egg"),
new LegacyBlock(384, "exp_bottle", "experience_bottle"),
new LegacyBlock(385, "fireball", "fire_charge"),
new LegacyBlock(386, "book_and_quill", "writable_book"),
new LegacyBlock(387, "written_book"), new LegacyBlock(388, "emerald"),
new LegacyBlock(389, "item_frame"),
new LegacyBlock(390, "flower_pot_item", "flower_pot"),
new LegacyBlock(391, "carrot_item", "carrot"),
new LegacyBlock(392, "potato_item", "potato"), new LegacyBlock(393, "baked_potato"),
new LegacyBlock(394, "poisonous_potato"), new LegacyBlock(395, "empty_map", "map"),
new LegacyBlock(396, "golden_carrot"),
new LegacyBlock(397, "skull_item", "skeleton_skull"),
new LegacyBlock(397, 1, "skull_item", "wither_skeleton_skull"),
new LegacyBlock(397, 2, "skull_item", "zombie_head"),
new LegacyBlock(397, 3, "skull_item", "player_head"),
new LegacyBlock(397, 4, "skull_item", "creeper_head"),
new LegacyBlock(397, 5, "skull_item", "dragon_head"),
new LegacyBlock(398, "carrot_stick"), new LegacyBlock(399, "nether_star"),
new LegacyBlock(400, "pumpkin_pie"),
new LegacyBlock(401, "firework", "firework_rocket"),
new LegacyBlock(402, "firework_charge", "firework_star"),
new LegacyBlock(403, "enchanted_book"),
new LegacyBlock(404, "redstone_comparator", "comparator"),
new LegacyBlock(405, "nether_brick_item", "nether_brick"),
new LegacyBlock(406, "quartz"),
new LegacyBlock(407, "explosive_minecart", "tnt_minecart"),
new LegacyBlock(408, "hopper_minecart"), new LegacyBlock(409, "prismarine_shard"),
new LegacyBlock(410, "prismarine_crystals"), new LegacyBlock(411, "rabbit"),
new LegacyBlock(412, "cooked_rabbit"), new LegacyBlock(413, "rabbit_stew"),
new LegacyBlock(414, "rabbit_foot"), new LegacyBlock(415, "rabbit_hide"),
new LegacyBlock(416, "armor_stand"),
new LegacyBlock(417, "iron_barding", "iron_horse_armor"),
new LegacyBlock(418, "gold_barding", "gold_horse_armor"),
new LegacyBlock(419, "diamond_barding", "diamond_horse_armor"),
new LegacyBlock(420, "leash", "lead"), new LegacyBlock(421, "name_tag"),
new LegacyBlock(422, "command_minecart", "command_block_minecart"),
new LegacyBlock(423, "mutton"), new LegacyBlock(424, "cooked_mutton"),
new LegacyBlock(425, "banner", "white_banner"),
new LegacyBlock(425, 1, "banner", "orange_banner"),
new LegacyBlock(425, 2, "banner", "magenta_banner"),
new LegacyBlock(425, 3, "banner", "light_blue_banner"),
new LegacyBlock(425, 4, "banner", "yellow_banner"),
new LegacyBlock(425, 5, "banner", "lime_banner"),
new LegacyBlock(425, 6, "banner", "pink_banner"),
new LegacyBlock(425, 7, "banner", "gray_banner"),
new LegacyBlock(425, 8, "banner", "light_gray_banner"),
new LegacyBlock(425, 9, "banner", "cyan_banner"),
new LegacyBlock(425, 10, "banner", "purple_banner"),
new LegacyBlock(425, 11, "banner", "blue_banner"),
new LegacyBlock(425, 12, "banner", "brown_banner"),
new LegacyBlock(425, 13, "banner", "green_banner"),
new LegacyBlock(425, 14, "banner", "red_banner"),
new LegacyBlock(425, 15, "banner", "black_banner"), new LegacyBlock(426, "end_crystal"),
new LegacyBlock(427, "spruce_door_item", "spruce_door"),
new LegacyBlock(428, "birch_door_item", "birch_door"),
new LegacyBlock(429, "jungle_door_item", "jungle_door"),
new LegacyBlock(430, "acacia_door_item", "acacia_door"),
new LegacyBlock(431, "dark_oak_door_item", "dark_oak_door"),
new LegacyBlock(432, "chorus_fruit"), new LegacyBlock(433, "chorus_fruit_popped"),
new LegacyBlock(434, "beetroot"), new LegacyBlock(435, "beetroot_seeds"),
new LegacyBlock(436, "beetroot_soup"),
new LegacyBlock(437, "dragons_breath", "dragon_breath"),
new LegacyBlock(438, "splash_potion"), new LegacyBlock(439, "spectral_arrow"),
new LegacyBlock(440, "tipped_arrow"), new LegacyBlock(441, "lingering_potion"),
new LegacyBlock(442, "shield"), new LegacyBlock(443, "elytra"),
new LegacyBlock(444, "boat_spruce", "spruce_boat"),
new LegacyBlock(445, "boat_birch", "birch_boat"),
new LegacyBlock(446, "boat_jungle", "jungle_boat"),
new LegacyBlock(447, "boat_acacia", "acacia_boat"),
new LegacyBlock(448, "boat_dark_oak", "dark_oak_boat"),
new LegacyBlock(449, "totem", "totem_of_undying"),
new LegacyBlock(450, "shulker_shell"), new LegacyBlock(452, "iron_nugget"),
new LegacyBlock(453, "knowledge_book"),
new LegacyBlock(2256, "gold_record", "music_disc_13"),
new LegacyBlock(2257, "green_record", "music_disc_cat"),
new LegacyBlock(2258, "record_3", "music_disc_blocks"),
new LegacyBlock(2259, "record_4", "music_disc_chirp"),
new LegacyBlock(2260, "record_5", "music_disc_far"),
new LegacyBlock(2261, "record_6", "music_disc_mall"),
new LegacyBlock(2262, "record_7", "music_disc_mellohi"),
new LegacyBlock(2263, "record_8", "music_disc_stal"),
new LegacyBlock(2264, "record_9", "music_disc_strad"),
new LegacyBlock(2265, "record_10", "music_disc_ward"),
new LegacyBlock(2266, "record_11", "music_disc_11"),
new LegacyBlock(2267, "record_12", "music_disc_wait")};
// private static final Map<Integer, PlotBlock> LEGACY_ID_TO_STRING_PLOT_BLOCK = new HashMap<>();
private static final Map<IdDataPair, PlotBlock> LEGACY_ID_AND_DATA_TO_STRING_PLOT_BLOCK =
new HashMap<>();
private static final Map<String, PlotBlock> NEW_STRING_TO_LEGACY_PLOT_BLOCK = new HashMap<>();
private static final Map<String, PlotBlock> OLD_STRING_TO_STRING_PLOT_BLOCK = new HashMap<>();
public BukkitLegacyMappings() {
this.addAll(Arrays.asList(BLOCKS));
// Make sure to add new blocks as well
final List<LegacyBlock> missing = new ArrayList<>();
for (final Material material : Material.values()) {
final String materialName = material.name().toLowerCase(Locale.ENGLISH);
if (OLD_STRING_TO_STRING_PLOT_BLOCK.get(materialName) == null) {
final LegacyBlock missingBlock =
new LegacyBlock(material.getId(), materialName, materialName);
missing.add(missingBlock);
}
}
addAll(missing);
}
private void addAll(@NonNull final Collection<LegacyBlock> blocks) {
for (final LegacyBlock legacyBlock : blocks) {
// LEGACY_ID_TO_STRING_PLOT_BLOCK
// .put(legacyBlock.getNumericalId(), legacyBlock.toStringPlotBlock());
/*if (legacyBlock.getDataValue() != 0) {
LEGACY_ID_AND_DATA_TO_STRING_PLOT_BLOCK
.put(new IdDataPair(legacyBlock.getNumericalId(), legacyBlock.getDataValue()),
legacyBlock.toStringPlotBlock());
} */
LEGACY_ID_AND_DATA_TO_STRING_PLOT_BLOCK
.put(new IdDataPair(legacyBlock.getNumericalId(), legacyBlock.getDataValue()),
legacyBlock.toStringPlotBlock());
NEW_STRING_TO_LEGACY_PLOT_BLOCK
.put(legacyBlock.getLegacyName(), legacyBlock.toStringPlotBlock());
OLD_STRING_TO_STRING_PLOT_BLOCK
.put(legacyBlock.getNewName(), legacyBlock.toLegacyPlotBlock());
Material material;
try {
material = Material.valueOf(legacyBlock.getNewName());
} catch (final Exception e) {
material = Material.getMaterial(legacyBlock.getLegacyName(), true);
}
legacyBlock.material = material;
}
}
public Collection<PlotBlock> getPlotBlocks() {
return Arrays.stream(BLOCKS).map(block -> PlotBlock.get(block.getNewName()))
.collect(Collectors.toList());
}
public StringComparison<PlotBlock>.ComparisonResult getClosestsMatch(
@NonNull final String string) {
final StringComparison<PlotBlock> comparison =
new StringComparison<>(string, getPlotBlocks());
return comparison.getBestMatchAdvanced();
}
/**
* Try to find a legacy plot block by any means possible.
* Strategy:
* - Check if the name contains a namespace, if so, strip it
* - Check if there's a (new) material matching the name
* - Check if there's a legacy material matching the name
* - Check if there's a numerical ID matching the name
* - Return null if everything else fails
*
* @param string String ID
* @return LegacyBlock if found, else null
*/
public PlotBlock fromAny(@NonNull final String string) {
if (string.isEmpty()) {
return StringPlotBlock.EVERYTHING;
}
String workingString = string;
String[] parts = null;
if (string.contains(":")) {
parts = string.split(":");
if (parts.length > 1) {
if (parts[0].equalsIgnoreCase("minecraft")) {
workingString = parts[1];
} else {
workingString = parts[0];
}
}
}
PlotBlock plotBlock;
if (NEW_STRING_TO_LEGACY_PLOT_BLOCK.keySet().contains(workingString.toLowerCase())) {
return PlotBlock.get(workingString);
} else if ((plotBlock = fromLegacyToString(workingString)) != null) {
return plotBlock;
} else {
try {
if (parts != null && parts.length > 1) {
final int id = Integer.parseInt(parts[0]);
final int data = Integer.parseInt(parts[1]);
return fromLegacyToString(id, data);
} else {
return fromLegacyToString(Integer.parseInt(workingString), 0);
}
} catch (final Throwable exception) {
return null;
}
}
}
public PlotBlock fromLegacyToString(final int id, final int data) {
return LEGACY_ID_AND_DATA_TO_STRING_PLOT_BLOCK.get(new IdDataPair(id, data));
}
public PlotBlock fromLegacyToString(final String id) {
return NEW_STRING_TO_LEGACY_PLOT_BLOCK.get(id);
}
public PlotBlock fromStringToLegacy(final String id) {
return OLD_STRING_TO_STRING_PLOT_BLOCK.get(id.toLowerCase(Locale.ENGLISH));
}
@Getter @EqualsAndHashCode @ToString @RequiredArgsConstructor
private static final class IdDataPair {
private final int id;
private final int data;
}
@Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public static final class LegacyBlock {
private final int numericalId;
private final int dataValue;
private final String legacyName;
private final String newName;
private Material material;
LegacyBlock(final int numericalId, final int dataValue, @NonNull final String legacyName) {
this(numericalId, dataValue, legacyName, legacyName);
}
LegacyBlock(final int numericalId, @NonNull final String legacyName,
@NonNull final String newName) {
this(numericalId, 0, legacyName, newName);
}
LegacyBlock(final int numericalId, @NonNull final String legacyName) {
this(numericalId, legacyName, legacyName);
}
PlotBlock toStringPlotBlock() {
return StringPlotBlock.get(newName);
}
PlotBlock toLegacyPlotBlock() {
return LegacyPlotBlock.get(numericalId, dataValue);
}
@Override public String toString() {
return this.newName;
}
}
}

View File

@ -0,0 +1,201 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.object.schematic.StateWrapper;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.RegionWrapper;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BaseBlock;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.stream.IntStream;
/**
* Schematic Handler.
*/
public class BukkitSchematicHandler extends SchematicHandler {
@Override public void getCompoundTag(final String world, final Set<RegionWrapper> regions,
final RunnableVal<CompoundTag> whenDone) {
// async
TaskManager.runTaskAsync(new Runnable() {
@Override public void run() {
// Main positions
Location[] corners = MainUtil.getCorners(world, regions);
final Location bot = corners[0];
final Location top = corners[1];
CuboidRegion cuboidRegion =
new CuboidRegion(BukkitUtil.IMP.getWeWorld(world), bot.getBlockVector3(),
top.getBlockVector3());
final int width = cuboidRegion.getWidth();
int height = cuboidRegion.getHeight();
final int length = cuboidRegion.getLength();
Map<String, Tag> schematic = new HashMap<>();
schematic.put("Version", new IntTag(1));
Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(0));
metadata.put("WEOffsetY", new IntTag(0));
metadata.put("WEOffsetZ", new IntTag(0));
schematic.put("Metadata", new CompoundTag(metadata));
schematic.put("Width", new ShortTag((short) width));
schematic.put("Height", new ShortTag((short) height));
schematic.put("Length", new ShortTag((short) length));
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
schematic.put("Offset", new IntArrayTag(new int[] {0, 0, 0,}));
Map<String, Integer> palette = new HashMap<>();
List<CompoundTag> tileEntities = new ArrayList<>();
ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length);
// Queue
final ArrayDeque<RegionWrapper> queue = new ArrayDeque<>(regions);
TaskManager.runTask(new Runnable() {
@Override public void run() {
if (queue.isEmpty()) {
TaskManager.runTaskAsync(() -> {
schematic.put("PaletteMax", new IntTag(palette.size()));
Map<String, Tag> paletteTag = new HashMap<>();
palette.forEach(
(key, value) -> paletteTag.put(key, new IntTag(value)));
schematic.put("Palette", new CompoundTag(paletteTag));
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
schematic.put("TileEntities",
new ListTag(CompoundTag.class, tileEntities));
whenDone.value = new CompoundTag(schematic);
TaskManager.runTask(whenDone);
});
return;
}
final Runnable regionTask = this;
RegionWrapper region = queue.poll();
Location pos1 = new Location(world, region.minX, region.minY, region.minZ);
Location pos2 = new Location(world, region.maxX, region.maxY, region.maxZ);
final int p1x = pos1.getX();
final int sy = pos1.getY();
final int p1z = pos1.getZ();
final int p2x = pos2.getX();
final int p2z = pos2.getZ();
final int ey = pos2.getY();
Iterator<Integer> yiter = IntStream.range(sy, ey + 1).iterator();
final Runnable yTask = new Runnable() {
@Override public void run() {
long ystart = System.currentTimeMillis();
while (yiter.hasNext()
&& System.currentTimeMillis() - ystart < 20) {
final int y = yiter.next();
Iterator<Integer> ziter =
IntStream.range(p1z, p2z + 1).iterator();
final Runnable zTask = new Runnable() {
@Override public void run() {
long zstart = System.currentTimeMillis();
while (ziter.hasNext()
&& System.currentTimeMillis() - zstart < 20) {
final int z = ziter.next();
Iterator<Integer> xiter =
IntStream.range(p1x, p2x + 1).iterator();
final Runnable xTask = new Runnable() {
@Override public void run() {
long xstart = System.currentTimeMillis();
final int ry = y - sy;
final int rz = z - p1z;
while (xiter.hasNext()
&& System.currentTimeMillis() - xstart
< 20) {
final int x = xiter.next();
final int rx = x - p1x;
BlockVector3 point =
BlockVector3.at(x, y, z);
BaseBlock block =
cuboidRegion.getWorld()
.getFullBlock(point);
if (block.getNbtData() != null) {
Map<String, Tag> values =
new HashMap<>();
for (Map.Entry<String, Tag> entry : block
.getNbtData().getValue()
.entrySet()) {
values.put(entry.getKey(),
entry.getValue());
}
// Remove 'id' if it exists. We want 'Id'
values.remove("id");
// Positions are kept in NBT, we don't want that.
values.remove("x");
values.remove("y");
values.remove("z");
values.put("Id", new StringTag(
block.getNbtId()));
values.put("Pos", new IntArrayTag(
new int[] {rx, ry, rz}));
tileEntities
.add(new CompoundTag(values));
}
String blockKey =
block.toImmutableState()
.getAsString();
int blockId;
if (palette.containsKey(blockKey)) {
blockId = palette.get(blockKey);
} else {
blockId = palette.size();
palette
.put(blockKey, palette.size());
}
while ((blockId & -128) != 0) {
buffer.write(blockId & 127 | 128);
blockId >>>= 7;
}
buffer.write(blockId);
}
if (xiter.hasNext()) {
this.run();
}
}
};
xTask.run();
}
if (ziter.hasNext()) {
this.run();
}
}
};
zTask.run();
}
if (yiter.hasNext()) {
TaskManager.runTaskLater(this, 1);
} else {
regionTask.run();
}
}
};
yTask.run();
}
});
}
});
}
@Override
public boolean restoreTile(LocalBlockQueue queue, CompoundTag ct, int x, int y, int z) {
return new StateWrapper(ct).restoreTag(queue.getWorld(), x, y, z);
}
}

View File

@ -1,18 +1,17 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.ConfigurationNode;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
import org.bukkit.Bukkit;
import org.bukkit.World;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.github.intellectualsites.plotsquared.configuration.ConfigurationSection;
import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.ConfigurationNode;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.object.PlotArea;
import com.github.intellectualsites.plotsquared.plot.object.SetupObject;
import com.github.intellectualsites.plotsquared.plot.util.SetupUtils;
import org.bukkit.*;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;
@ -24,50 +23,75 @@ import java.util.Objects;
public class BukkitSetupUtils extends SetupUtils {
@Override
public void updateGenerators() {
@Override public void updateGenerators() {
if (!SetupUtils.generators.isEmpty()) {
return;
}
String testWorld = "CheckingPlotSquaredGenerator";
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
ChunkGenerator generator = plugin.getDefaultWorldGenerator(testWorld, "");
if (generator != null) {
PS.get().removePlotAreas(testWorld);
String name = plugin.getDescription().getName();
GeneratorWrapper<?> wrapped;
if (generator instanceof GeneratorWrapper<?>) {
wrapped = (GeneratorWrapper<?>) generator;
} else {
wrapped = new BukkitPlotGenerator(testWorld, generator);
try {
if (plugin.isEnabled()) {
ChunkGenerator generator = plugin.getDefaultWorldGenerator(testWorld, "");
if (generator != null) {
PlotSquared.get().removePlotAreas(testWorld);
String name = plugin.getDescription().getName();
GeneratorWrapper<?> wrapped;
if (generator instanceof GeneratorWrapper<?>) {
wrapped = (GeneratorWrapper<?>) generator;
} else {
wrapped = new BukkitPlotGenerator(testWorld, generator);
}
SetupUtils.generators.put(name, wrapped);
}
SetupUtils.generators.put(name, wrapped);
}
} catch (Throwable e) { // Recover from third party generator error
e.printStackTrace();
}
}
}
@Override
public String setupWorld(SetupObject object) {
@Override public void unload(String worldName, boolean save) {
World world = Bukkit.getWorld(worldName);
if (world == null) {
return;
}
World dw = Bukkit.getWorlds().get(0);
for (Player player : world.getPlayers()) {
player.teleport(dw.getSpawnLocation());
}
if (save) {
for (Chunk chunk : world.getLoadedChunks()) {
chunk.unload(true, false);
}
} else {
for (Chunk chunk : world.getLoadedChunks()) {
chunk.unload(false, false);
}
}
Bukkit.unloadWorld(world, false);
}
@Override public String setupWorld(SetupObject object) {
SetupUtils.manager.updateGenerators();
ConfigurationNode[] steps = object.step == null ? new ConfigurationNode[0] : object.step;
String world = object.world;
int type = object.type;
String worldPath = "worlds." + object.world;
if (!PS.get().worlds.contains(worldPath)) {
PS.get().worlds.createSection(worldPath);
}
ConfigurationSection worldSection = PS.get().worlds.getConfigurationSection(worldPath);
switch (type) {
case 2: {
if (object.id != null) {
if (!PlotSquared.get().worlds.contains(worldPath)) {
PlotSquared.get().worlds.createSection(worldPath);
}
ConfigurationSection worldSection =
PlotSquared.get().worlds.getConfigurationSection(worldPath);
String areaName = object.id + "-" + object.min + "-" + object.max;
String areaPath = "areas." + areaName;
if (!worldSection.contains(areaPath)) {
worldSection.createSection(areaPath);
}
ConfigurationSection areaSection = worldSection.getConfigurationSection(areaPath);
ConfigurationSection areaSection =
worldSection.getConfigurationSection(areaPath);
HashMap<String, Object> options = new HashMap<>();
for (ConfigurationNode step : steps) {
options.put(step.getConstant(), step.getValue());
@ -75,7 +99,8 @@ public class BukkitSetupUtils extends SetupUtils {
options.put("generator.type", object.type);
options.put("generator.terrain", object.terrain);
options.put("generator.plugin", object.plotManager);
if (object.setupGenerator != null && !object.setupGenerator.equals(object.plotManager)) {
if (object.setupGenerator != null && !object.setupGenerator
.equals(object.plotManager)) {
options.put("generator.init", object.setupGenerator);
}
for (Entry<String, Object> entry : options.entrySet()) {
@ -97,44 +122,64 @@ public class BukkitSetupUtils extends SetupUtils {
}
break;
}
case 1:
case 1: {
if (!PlotSquared.get().worlds.contains(worldPath)) {
PlotSquared.get().worlds.createSection(worldPath);
}
ConfigurationSection worldSection =
PlotSquared.get().worlds.getConfigurationSection(worldPath);
for (ConfigurationNode step : steps) {
worldSection.set(step.getConstant(), step.getValue());
}
PS.get().worlds.set("worlds." + world + ".generator.type", object.type);
PS.get().worlds.set("worlds." + world + ".generator.terrain", object.terrain);
PS.get().worlds.set("worlds." + world + ".generator.plugin", object.plotManager);
if (object.setupGenerator != null && !object.setupGenerator.equals(object.plotManager)) {
PS.get().worlds.set("worlds." + world + ".generator.init", object.setupGenerator);
PlotSquared.get().worlds.set("worlds." + world + ".generator.type", object.type);
PlotSquared.get().worlds
.set("worlds." + world + ".generator.terrain", object.terrain);
PlotSquared.get().worlds
.set("worlds." + world + ".generator.plugin", object.plotManager);
if (object.setupGenerator != null && !object.setupGenerator
.equals(object.plotManager)) {
PlotSquared.get().worlds
.set("worlds." + world + ".generator.init", object.setupGenerator);
}
GeneratorWrapper<?> gen = SetupUtils.generators.get(object.setupGenerator);
if (gen != null && gen.isFull()) {
object.setupGenerator = null;
}
break;
case 0:
for (ConfigurationNode step : steps) {
worldSection.set(step.getConstant(), step.getValue());
}
case 0: {
if (steps.length != 0) {
if (!PlotSquared.get().worlds.contains(worldPath)) {
PlotSquared.get().worlds.createSection(worldPath);
}
ConfigurationSection worldSection =
PlotSquared.get().worlds.getConfigurationSection(worldPath);
for (ConfigurationNode step : steps) {
worldSection.set(step.getConstant(), step.getValue());
}
}
break;
}
}
try {
PS.get().worlds.save(PS.get().worldsFile);
PlotSquared.get().worlds.save(PlotSquared.get().worldsFile);
} catch (IOException e) {
e.printStackTrace();
}
if (object.setupGenerator != null) {
if (Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null && Bukkit.getPluginManager().getPlugin("Multiverse-Core")
.isEnabled()) {
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv create " + world + " normal -g " + object.setupGenerator);
if (Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null && Bukkit
.getPluginManager().getPlugin("Multiverse-Core").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mv create " + world + " normal -g " + object.setupGenerator);
setGenerator(world, object.setupGenerator);
if (Bukkit.getWorld(world) != null) {
return world;
}
}
if (Bukkit.getPluginManager().getPlugin("MultiWorld") != null && Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + world + " plugin:" + object.setupGenerator);
if (Bukkit.getPluginManager().getPlugin("MultiWorld") != null && Bukkit
.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mw create " + world + " plugin:" + object.setupGenerator);
setGenerator(world, object.setupGenerator);
if (Bukkit.getWorld(world) != null) {
return world;
@ -143,23 +188,28 @@ public class BukkitSetupUtils extends SetupUtils {
WorldCreator wc = new WorldCreator(object.world);
wc.generator(object.setupGenerator);
wc.environment(Environment.NORMAL);
wc.type(WorldType.FLAT);
Bukkit.createWorld(wc);
setGenerator(world, object.setupGenerator);
} else {
if (Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null && Bukkit.getPluginManager().getPlugin("Multiverse-Core")
.isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv create " + world + " normal");
if (Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null && Bukkit
.getPluginManager().getPlugin("Multiverse-Core").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mv create " + world + " normal");
if (Bukkit.getWorld(world) != null) {
return world;
}
}
if (Bukkit.getPluginManager().getPlugin("MultiWorld") != null && Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + world);
if (Bukkit.getPluginManager().getPlugin("MultiWorld") != null && Bukkit
.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + world);
if (Bukkit.getWorld(world) != null) {
return world;
}
}
Bukkit.createWorld(new WorldCreator(object.world).environment(World.Environment.NORMAL));
World bw =
Bukkit.createWorld(new WorldCreator(object.world).environment(Environment.NORMAL));
}
return object.world;
}
@ -178,8 +228,7 @@ public class BukkitSetupUtils extends SetupUtils {
}
}
@Override
public String getGenerator(PlotArea plotArea) {
@Override public String getGenerator(PlotArea plotArea) {
if (SetupUtils.generators.isEmpty()) {
updateGenerators();
}

View File

@ -0,0 +1,50 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.BukkitMain;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import org.bukkit.Bukkit;
public class BukkitTaskManager extends TaskManager {
private final BukkitMain bukkitMain;
public BukkitTaskManager(BukkitMain bukkitMain) {
this.bukkitMain = bukkitMain;
}
@Override public int taskRepeat(Runnable runnable, int interval) {
return this.bukkitMain.getServer().getScheduler()
.scheduleSyncRepeatingTask(this.bukkitMain, runnable, interval, interval);
}
@SuppressWarnings("deprecation") @Override
public int taskRepeatAsync(Runnable runnable, int interval) {
return this.bukkitMain.getServer().getScheduler()
.scheduleAsyncRepeatingTask(this.bukkitMain, runnable, interval, interval);
}
@Override public void taskAsync(Runnable runnable) {
this.bukkitMain.getServer().getScheduler().runTaskAsynchronously(this.bukkitMain, runnable)
.getTaskId();
}
@Override public void task(Runnable runnable) {
this.bukkitMain.getServer().getScheduler().runTask(this.bukkitMain, runnable).getTaskId();
}
@Override public void taskLater(Runnable runnable, int delay) {
this.bukkitMain.getServer().getScheduler().runTaskLater(this.bukkitMain, runnable, delay)
.getTaskId();
}
@Override public void taskLaterAsync(Runnable runnable, int delay) {
this.bukkitMain.getServer().getScheduler()
.runTaskLaterAsynchronously(this.bukkitMain, runnable, delay);
}
@Override public void cancelTask(int task) {
if (task != -1) {
Bukkit.getScheduler().cancelTask(task);
}
}
}

View File

@ -0,0 +1,469 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.object.*;
import com.github.intellectualsites.plotsquared.plot.object.schematic.PlotItem;
import com.github.intellectualsites.plotsquared.plot.util.*;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.*;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
import java.util.*;
@SuppressWarnings({"unused", "WeakerAccess"}) public class BukkitUtil extends WorldUtil {
private static String lastString = null;
private static World lastWorld = null;
private static Player lastPlayer = null;
private static PlotPlayer lastPlotPlayer = null;
public static void removePlayer(String player) {
lastPlayer = null;
lastPlotPlayer = null;
}
public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) {
if (op.isOnline()) {
return getPlayer(op.getPlayer());
}
final Player player = OfflinePlayerUtil.loadPlayer(op);
player.loadData();
return new BukkitPlayer(player, true);
}
/**
* Get a plot based on the location.
*
* @param location the location to check
* @return plot if found, otherwise it creates a temporary plot
* @see Plot
*/
public static Plot getPlot(org.bukkit.Location location) {
if (location == null) {
return null;
}
return getLocation(location).getPlot();
}
/**
* Get a plot based on the player location.
*
* @param player the player to check
* @return plot if found, otherwise it creates a temporary plot
* @see #getPlot(org.bukkit.Location)
* @see Plot
*/
public static Plot getPlot(Player player) {
return getPlot(player.getLocation());
}
/**
* Get home location.
*
* @param plot Plot that you want to get the location for
* @return plot bottom location
* @see Plot
*/
public static org.bukkit.Location getHomeLocation(Plot plot) {
return BukkitUtil.getLocation(plot.getHome());
}
/**
* Get the PlotPlayer for an offline player.
*
* <p>Note that this will work if the player is offline, however not all
* functionality will work.
*
* @param player the player to wrap
* @return a {@code PlotPlayer}
* @see PlotPlayer#wrap(Object)
*/
public static PlotPlayer wrapPlayer(OfflinePlayer player) {
return PlotPlayer.wrap(player);
}
/**
* Gets the PlotPlayer for a player. The PlotPlayer is usually cached and
* will provide useful functions relating to players.
*
* @param player the player to wrap
* @return a {@code PlotPlayer}
* @see PlotPlayer#wrap(Object)
*/
public static PlotPlayer wrapPlayer(Player player) {
return PlotPlayer.wrap(player);
}
/**
* Gets the number of plots, which the player is able to build in.
*
* @param player player, for whom we're getting the plots
* @return the number of allowed plots
*/
public static int getAllowedPlots(Player player) {
PlotPlayer plotPlayer = PlotPlayer.wrap(player);
return plotPlayer.getAllowedPlots();
}
/**
* Check whether or not a player is in a plot.
*
* @param player who we're checking for
* @return true if the player is in a plot, false if not-
*/
public static boolean isInPlot(Player player) {
return getPlot(player) != null;
}
/**
* Gets a collection containing the players plots.
*
* @param world Specify the world we want to select the plots from
* @param player Player, for whom we're getting the plots
* @return a set containing the players plots
* @see Plot
*/
public static Set<Plot> getPlayerPlots(String world, Player player) {
if (world == null) {
return new HashSet<>();
}
return PlotPlayer.wrap(player).getPlots(world);
}
/**
* Send a message to a player. The message supports color codes.
*
* @param player the recipient of the message
* @param string the message
* @see MainUtil#sendMessage(PlotPlayer, String)
*/
public static void sendMessage(Player player, String string) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), string);
}
/**
* Gets the player plot count.
*
* @param world Specify the world we want to select the plots from
* @param player Player, for whom we're getting the plot count
* @return the number of plots the player has
*/
public static int getPlayerPlotCount(String world, Player player) {
if (world == null) {
return 0;
}
return BukkitUtil.getPlayer(player).getPlotCount(world);
}
/**
* Send a message to a player.
*
* @param player the recipient of the message
* @param caption the message
* @see MainUtil#sendMessage(PlotPlayer, C, String...)
*/
public static void sendMessage(Player player, C caption) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption);
}
public static PlotPlayer getPlayer(@NonNull final Player player) {
if (player == lastPlayer) {
return lastPlotPlayer;
}
final String name = player.getName();
final PlotPlayer plotPlayer = UUIDHandler.getPlayer(name);
if (plotPlayer != null) {
return plotPlayer;
}
lastPlotPlayer = new BukkitPlayer(player);
UUIDHandler.getPlayers().put(name, lastPlotPlayer);
lastPlayer = player;
return lastPlotPlayer;
}
public static Location getLocation(@NonNull final org.bukkit.Location location) {
return new Location(location.getWorld().getName(), MathMan.roundInt(location.getX()),
MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()));
}
public static org.bukkit.Location getLocation(@NonNull final Location location) {
return new org.bukkit.Location(getWorld(location.getWorld()), location.getX(),
location.getY(), location.getZ());
}
public static World getWorld(@NonNull final String string) {
return Bukkit.getWorld(string);
}
public static String getWorld(@NonNull final Entity entity) {
return entity.getWorld().getName();
}
public static List<Entity> getEntities(@NonNull final String worldName) {
World world = getWorld(worldName);
return world != null ? world.getEntities() : new ArrayList<Entity>();
}
public static Location getLocation(@NonNull final Entity entity) {
final org.bukkit.Location location = entity.getLocation();
String world = location.getWorld().getName();
return new Location(world, location.getBlockX(), location.getBlockY(),
location.getBlockZ());
}
public static Location getLocationFull(@NonNull final Entity entity) {
final org.bukkit.Location location = entity.getLocation();
return new Location(location.getWorld().getName(), MathMan.roundInt(location.getX()),
MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()), location.getYaw(),
location.getPitch());
}
public static BukkitLegacyMappings getBukkitLegacyMappings() {
return (BukkitLegacyMappings) PlotSquared.imp().getLegacyMappings();
}
public static Material getMaterial(@NonNull final PlotBlock plotBlock) {
if (plotBlock instanceof StringPlotBlock) {
return Material
.getMaterial(((StringPlotBlock) plotBlock).getItemId().toUpperCase(Locale.ENGLISH));
} else {
final LegacyPlotBlock legacyPlotBlock = (LegacyPlotBlock) plotBlock;
return getBukkitLegacyMappings()
.fromLegacyToString(legacyPlotBlock.getId(), legacyPlotBlock.getData())
.to(Material.class);
}
}
@Override public boolean isBlockSame(PlotBlock block1, PlotBlock block2) {
if (block1.equals(block2)) {
return true;
}
Material mat1 = getMaterial(block1), mat2 = getMaterial(block2);
return mat1 == mat2;
}
@Override public boolean isWorld(@NonNull final String worldName) {
return getWorld(worldName) != null;
}
@Override public String getBiome(String world, int x, int z) {
return getWorld(world).getBiome(x, z).name();
}
@Override @SuppressWarnings("deprecation")
public void setSign(@NonNull final String worldName, final int x, final int y, final int z,
@NonNull final String[] lines) {
final World world = getWorld(worldName);
final Block block = world.getBlockAt(x, y, z);
// block.setType(Material.AIR);
final Material type = block.getType();
if (type != Material.SIGN && type != Material.WALL_SIGN) {
BlockFace facing = BlockFace.EAST;
if (world.getBlockAt(x, y, z + 1).getType().isSolid())
facing = BlockFace.NORTH;
else if (world.getBlockAt(x + 1, y, z).getType().isSolid())
facing = BlockFace.WEST;
else if (world.getBlockAt(x, y, z - 1).getType().isSolid())
facing = BlockFace.SOUTH;
block.setType(Material.WALL_SIGN, false);
final WallSign sign = (WallSign) block.getBlockData();
sign.setFacing(facing);
block.setBlockData(sign, false);
}
final BlockState blockstate = block.getState();
if (blockstate instanceof Sign) {
final Sign sign = (Sign) blockstate;
for (int i = 0; i < lines.length; i++) {
sign.setLine(i, lines[i]);
}
sign.update(true);
}
}
@Override @Nullable public String[] getSign(@NonNull final Location location) {
Block block = getWorld(location.getWorld())
.getBlockAt(location.getX(), location.getY(), location.getZ());
if (block != null) {
if (block.getState() instanceof Sign) {
Sign sign = (Sign) block.getState();
return sign.getLines();
}
}
return null;
}
@Override public Location getSpawn(@NonNull final PlotPlayer player) {
return getLocation(((BukkitPlayer) player).player.getBedSpawnLocation());
}
@Override public Location getSpawn(@NonNull final String world) {
final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
return new Location(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(),
temp.getYaw(), temp.getPitch());
}
@Override public void setSpawn(@NonNull final Location location) {
final World world = getWorld(location.getWorld());
if (world != null) {
world.setSpawnLocation(location.getX(), location.getY(), location.getZ());
}
}
@Override public void saveWorld(@NonNull final String worldName) {
final World world = getWorld(worldName);
if (world != null) {
world.save();
}
}
@Override public int getHighestBlock(@NonNull final String world, final int x, final int z) {
final World bukkitWorld = getWorld(world);
// Skip top and bottom block
int air = 1;
for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) {
Block block = bukkitWorld.getBlockAt(x, y, z);
if (block != null) {
Material type = block.getType();
if (type.isSolid()) {
if (air > 1)
return y;
air = 0;
} else {
switch (type) {
case WATER:
case LAVA:
return y;
}
air++;
}
}
}
return bukkitWorld.getMaxHeight() - 1;
}
@Override public int getBiomeFromString(@NonNull final String biomeString) {
try {
final Biome biome = Biome.valueOf(biomeString.toUpperCase());
return Arrays.asList(Biome.values()).indexOf(biome);
} catch (IllegalArgumentException ignored) {
return -1;
}
}
@Override public String[] getBiomeList() {
final Biome[] biomes = Biome.values();
final String[] list = new String[biomes.length];
for (int i = 0; i < biomes.length; i++) {
list[i] = biomes[i].name();
}
return list;
}
@Override
public boolean addItems(@NonNull final String worldName, @NonNull final PlotItem items) {
final World world = getWorld(worldName);
final Block block = world.getBlockAt(items.x, items.y, items.z);
if (block == null) {
return false;
}
final BlockState state = block.getState();
if (state instanceof InventoryHolder) {
InventoryHolder holder = (InventoryHolder) state;
Inventory inv = holder.getInventory();
for (int i = 0; i < items.types.length; i++) {
// ItemStack item = new ItemStack(LegacyMappings.fromLegacyId(items.id[i]).getMaterial(), items.amount[i], items.data[i]);
ItemStack item = new ItemStack(items.types[i].to(Material.class), items.amount[i]);
inv.addItem(item);
}
state.update(true);
return true;
}
return false;
}
@Override public boolean isBlockSolid(@NonNull final PlotBlock block) {
try {
Material material = getMaterial(block);
if (material.isLegacy()) {
material = getBukkitLegacyMappings().fromLegacyToString(material.name())
.to(Material.class);
}
if (material.isBlock() && material.isSolid() && !material.hasGravity()) {
String name = material.name().toLowerCase(Locale.ENGLISH);
if (material.isOccluding() || name.contains("stairs") || name.contains("slab")
|| name.contains("wool")) {
switch (material) {
case NOTE_BLOCK:
case SPAWNER:
return false;
default:
return true;
}
}
}
return false;
} catch (Exception ignored) {
return false;
}
}
@Override public String getClosestMatchingName(@NonNull final PlotBlock block) {
try {
return getMaterial(block).name();
} catch (Exception ignored) {
return null;
}
}
@Override @Nullable
public StringComparison<PlotBlock>.ComparisonResult getClosestBlock(String name) {
final PlotBlock plotBlock = BukkitUtil.getBukkitLegacyMappings().fromAny(name);
if (plotBlock != null) {
return new StringComparison<PlotBlock>().new ComparisonResult(1, plotBlock);
}
return BukkitUtil.getBukkitLegacyMappings().getClosestsMatch(name);
}
@Override
public void setBiomes(@NonNull final String worldName, @NonNull final RegionWrapper region,
@NonNull final String biomeString) {
final World world = getWorld(worldName);
final Biome biome = Biome.valueOf(biomeString.toUpperCase());
for (int x = region.minX; x <= region.maxX; x++) {
for (int z = region.minZ; z <= region.maxZ; z++) {
world.setBiome(x, z, biome);
}
}
}
public com.sk89q.worldedit.world.World getWeWorld(String world) {
return new BukkitWorld(Bukkit.getWorld(world));
}
@Override public PlotBlock getBlock(@NonNull final Location location) {
final World world = getWorld(location.getWorld());
final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ());
if (block == null) {
return StringPlotBlock.EVERYTHING;
}
return PlotBlock.get(block.getType().name());
}
@Override public String getMainWorld() {
return Bukkit.getWorlds().get(0).getName();
}
}

View File

@ -0,0 +1,7 @@
package com.github.intellectualsites.plotsquared.bukkit.util;
public class BukkitVersion {
public static int[] v1_13_2 = {1, 13, 2};
public static int[] v1_13_1 = {1, 13, 1};
public static int[] v1_13_0 = {1, 13, 0};
}

View File

@ -1,4 +1,4 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.google.common.base.Splitter;
import com.google.common.collect.BiMap;
@ -6,38 +6,16 @@ import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.io.ByteSink;
import com.google.common.io.ByteSource;
import com.google.common.io.Closeables;
import com.google.common.io.Files;
import com.google.common.primitives.Primitives;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.ItemStack;
import java.io.BufferedInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.AbstractList;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@ -77,13 +55,16 @@ public class NbtFactory {
ClassLoader loader = NbtFactory.class.getClassLoader();
String packageName = getPackageName();
String craftpackageName = getCraftPackageName();
Class<?> offlinePlayer = loader.loadClass(packageName + ".CraftOfflinePlayer");
// Prepare NBT
this.COMPOUND_CLASS = getMethod(0, Modifier.STATIC, offlinePlayer, "getData").getReturnType();
this.BASE_CLASS = this.COMPOUND_CLASS.getSuperclass();
this.COMPOUND_CLASS =
getMethod(0, Modifier.STATIC, offlinePlayer, "getData").getReturnType();
this.BASE_CLASS = loader.loadClass(craftpackageName + ".NBTBase");
this.NBT_GET_TYPE = getMethod(0, Modifier.STATIC, this.BASE_CLASS, "getTypeId");
this.NBT_CREATE_TAG = getMethod(Modifier.STATIC, 0, this.BASE_CLASS, "createTag", byte.class);
this.NBT_CREATE_TAG =
getMethod(Modifier.STATIC, 0, this.BASE_CLASS, "createTag", byte.class);
// Prepare CraftItemStack
this.CRAFT_STACK = loader.loadClass(packageName + ".inventory.CraftItemStack");
@ -95,11 +76,14 @@ public class NbtFactory {
initializeNMS(loader, nmsPackage);
if (this.READ_LIMITER_CLASS != null) {
this.LOAD_COMPOUND = new LoadMethodSkinUpdate(this.STREAM_TOOLS, this.READ_LIMITER_CLASS);
this.LOAD_COMPOUND =
new LoadMethodSkinUpdate(this.STREAM_TOOLS, this.READ_LIMITER_CLASS);
} else {
this.LOAD_COMPOUND = new LoadMethodWorldUpdate(this.STREAM_TOOLS);
}
this.SAVE_COMPOUND = getMethod(Modifier.STATIC, 0, this.STREAM_TOOLS, null, this.BASE_CLASS, DataOutput.class);
this.SAVE_COMPOUND =
getMethod(Modifier.STATIC, 0, this.STREAM_TOOLS, null, this.BASE_CLASS,
DataOutput.class);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Unable to find offline player.", e);
@ -109,6 +93,7 @@ public class NbtFactory {
/**
* Retrieve or construct a shared NBT factory.
*
* @return The factory.
*/
private static NbtFactory get() {
@ -120,6 +105,7 @@ public class NbtFactory {
/**
* Construct a new NBT list of an unspecified type.
*
* @return The NBT list.
*/
public static NbtList createList(Object... content) {
@ -128,6 +114,7 @@ public class NbtFactory {
/**
* Construct a new NBT list of an unspecified type.
*
* @return The NBT list.
*/
public static NbtList createList(Iterable<? extends Object> iterable) {
@ -151,6 +138,7 @@ public class NbtFactory {
/**
* Construct a new NBT wrapper from a list.
*
* @param nmsList - the NBT list.
* @return The wrapper.
*/
@ -161,19 +149,17 @@ public class NbtFactory {
/**
* Load the content of a file from a stream.
*
* Use {@link Files#newInputStreamSupplier(File)} to provide a stream from a file.
* @param stream - the stream supplier.
* @param input - the stream.
* @param option - whether or not to decompress the input stream.
* @return The decoded NBT compound.
* @throws IOException If anything went wrong.
*/
public static NbtCompound fromStream(ByteSource stream, StreamOptions option) throws IOException {
InputStream input = null;
public static NbtCompound fromStream(InputStream input, StreamOptions option)
throws IOException {
DataInputStream data = null;
boolean suppress = true;
try {
input = stream.openStream();
if (option == StreamOptions.GZIP_COMPRESSION) {
data = new DataInputStream(new BufferedInputStream(new GZIPInputStream(input)));
} else {
@ -196,20 +182,21 @@ public class NbtFactory {
/**
* Save the content of a NBT compound to a stream.
*
* Use {@link Files#newOutputStreamSupplier(File)} to provide a stream supplier to a file.
* @param source - the NBT compound to save.
* @param stream - the stream.
* @param option - whether or not to compress the output.
* @throws IOException If anything went wrong.
*/
public static void saveStream(NbtCompound source, ByteSink stream, StreamOptions option) throws IOException {
public static void saveStream(NbtCompound source, ByteSink stream, StreamOptions option)
throws IOException {
OutputStream output = null;
DataOutputStream data = null;
boolean suppress = true;
try {
output = stream.openStream();
data = new DataOutputStream(option == StreamOptions.GZIP_COMPRESSION ? new GZIPOutputStream(output) : output);
data = new DataOutputStream(
option == StreamOptions.GZIP_COMPRESSION ? new GZIPOutputStream(output) : output);
invokeMethod(get().SAVE_COMPOUND, null, source.getHandle(), data);
suppress = false;
@ -225,6 +212,7 @@ public class NbtFactory {
/**
* Construct a new NBT wrapper from a compound.
*
* @param nmsCompound - the NBT compound.
* @return The wrapper.
*/
@ -235,7 +223,8 @@ public class NbtFactory {
/**
* Set the NBT compound tag of a given item stack.
* <p>
* @param stack - the item stack, cannot be air.
*
* @param stack - the item stack, cannot be air.
* @param compound - the new NBT compound, or NULL to remove it.
* @throws IllegalArgumentException If the stack is not a CraftItemStack, or it represents air.
*/
@ -253,6 +242,7 @@ public class NbtFactory {
* material, damage value or count.
* <p>
* The item stack must be a wrapper for a CraftItemStack.
*
* @param stack - the item stack.
* @return A wrapper for its NBT tag.
*/
@ -272,6 +262,7 @@ public class NbtFactory {
/**
* Retrieve a CraftItemStack version of the stack.
*
* @param stack - the stack to convert.
* @return The CraftItemStack version.
*/
@ -286,12 +277,14 @@ public class NbtFactory {
caller.setAccessible(true);
return (ItemStack) caller.newInstance(stack);
} catch (Exception ignored) {
throw new IllegalStateException("Unable to convert " + stack + " + to a CraftItemStack.");
throw new IllegalStateException(
"Unable to convert " + stack + " + to a CraftItemStack.");
}
}
/**
* Ensure that the given stack can store arbitrary NBT information.
*
* @param stack - the stack to check.
*/
private static void checkItemStack(ItemStack stack) {
@ -302,12 +295,14 @@ public class NbtFactory {
throw new IllegalArgumentException("Stack must be a CraftItemStack.");
}
if (stack.getType() == Material.AIR) {
throw new IllegalArgumentException("ItemStacks representing air cannot store NMS information.");
throw new IllegalArgumentException(
"ItemStacks representing air cannot store NMS information.");
}
}
/**
* Invoke a method on the given target instance using the provided parameters.
*
* @param method - the method to invoke.
* @param target - the target.
* @param params - the parameters to supply.
@ -339,22 +334,23 @@ public class NbtFactory {
/**
* Search for the first publicly and privately defined method of the given name and parameter count.
*
* @param requireMod - modifiers that are required.
* @param bannedMod - modifiers that are banned.
* @param clazz - a class to start with.
* @param bannedMod - modifiers that are banned.
* @param clazz - a class to start with.
* @param methodName - the method name, or NULL to skip.
* @param params - the expected parameters.
* @param params - the expected parameters.
* @return The first method by this name.
* @throws IllegalStateException If we cannot find this method.
*/
private static Method getMethod(int requireMod, int bannedMod, Class<?> clazz, String methodName,
Class<?>... params) {
private static Method getMethod(int requireMod, int bannedMod, Class<?> clazz,
String methodName, Class<?>... params) {
for (Method method : clazz.getDeclaredMethods()) {
// Limitation: Doesn't handle overloads
if (((method.getModifiers() & requireMod) == requireMod)
&& ((method.getModifiers() & bannedMod) == 0)
&& ((methodName == null) || method.getName().equals(methodName))
&& Arrays.equals(method.getParameterTypes(), params)) {
if (((method.getModifiers() & requireMod) == requireMod) && (
(method.getModifiers() & bannedMod) == 0) && ((methodName == null) || method
.getName().equals(methodName)) && Arrays
.equals(method.getParameterTypes(), params)) {
method.setAccessible(true);
return method;
@ -364,13 +360,15 @@ public class NbtFactory {
if (clazz.getSuperclass() != null) {
return getMethod(requireMod, bannedMod, clazz.getSuperclass(), methodName, params);
}
throw new IllegalStateException(String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params)));
throw new IllegalStateException(
String.format("Unable to find method %s (%s).", methodName, Arrays.asList(params)));
}
/**
* Search for the first publicly and privately defined field of the given name.
* @param instance - an instance of the class with the field.
* @param clazz - an optional class to start with, or NULL to deduce it from instance.
*
* @param instance - an instance of the class with the field.
* @param clazz - an optional class to start with, or NULL to deduce it from instance.
* @param fieldName - the field name.
* @return The first field by this name.
* @throws IllegalStateException If we cannot find this field.
@ -397,7 +395,8 @@ public class NbtFactory {
try {
this.STREAM_TOOLS = loader.loadClass(nmsPackage + ".NBTCompressedStreamTools");
this.READ_LIMITER_CLASS = loader.loadClass(nmsPackage + ".NBTReadLimiter");
} catch (ClassNotFoundException ignored) {}
} catch (ClassNotFoundException ignored) {
}
}
private String getPackageName() {
@ -408,22 +407,28 @@ public class NbtFactory {
return name;
} else {
// Fallback
return "org.bukkit.craftbukkit.v1_7_R3";
return "org.bukkit.craftbukkit.v1_13_R1";
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getDataMap(Object handle) {
return (Map<String, Object>) getFieldValue(getDataField(NbtType.TAG_COMPOUND, handle), handle);
private String getCraftPackageName() {
String version =
Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
return "net.minecraft.server." + version;
}
@SuppressWarnings("unchecked")
private List<Object> getDataList(Object handle) {
@SuppressWarnings("unchecked") private Map<String, Object> getDataMap(Object handle) {
return (Map<String, Object>) getFieldValue(getDataField(NbtType.TAG_COMPOUND, handle),
handle);
}
@SuppressWarnings("unchecked") private List<Object> getDataList(Object handle) {
return (List<Object>) getFieldValue(getDataField(NbtType.TAG_LIST, handle), handle);
}
/**
* Convert wrapped List and Map objects into their respective NBT counterparts.
*
* @param value - the value of the element to create. Can be a List or a Map.
* @return The NBT element.
*/
@ -445,8 +450,8 @@ public class NbtFactory {
/**
* Convert a given NBT element to a primitive wrapper or List/Map equivalent.
* <p>
* All changes to any mutable objects will be reflected in the underlying NBT element(s).
* <p> All changes to any mutable objects will be reflected in the underlying NBT element(s).
*
* @param nms - the NBT element.
* @return The wrapper equivalent.
*/
@ -473,7 +478,8 @@ public class NbtFactory {
/**
* Construct a new NMS NBT tag initialized with the given value.
* @param type - the NBT type.
*
* @param type - the NBT type.
* @param value - the value, or NULL to keep the original value.
* @return The created tag.
*/
@ -488,8 +494,9 @@ public class NbtFactory {
/**
* Retrieve the field where the NBT class stores its value.
*
* @param type - the NBT type.
* @param nms - the NBT class instance.
* @param nms - the NBT class instance.
* @return The corresponding field.
*/
private Field getDataField(NbtType type, Object nms) {
@ -501,6 +508,7 @@ public class NbtFactory {
/**
* Retrieve the NBT type from a given NMS NBT tag.
*
* @param nms - the native NBT tag.
* @return The corresponding type.
*/
@ -511,40 +519,38 @@ public class NbtFactory {
/**
* Retrieve the nearest NBT type for a given primitive type.
*
* @param primitive - the primitive type.
* @return The corresponding type.
*/
private NbtType getPrimitiveType(Object primitive) {
NbtType type = NBT_ENUM.get(NBT_CLASS.inverse().get(Primitives.unwrap(primitive.getClass())));
NbtType type =
NBT_ENUM.get(NBT_CLASS.inverse().get(Primitives.unwrap(primitive.getClass())));
// Display the illegal value at least
if (type == null) {
throw new IllegalArgumentException(String.format("Illegal type: %s (%s)", primitive.getClass(), primitive));
throw new IllegalArgumentException(
String.format("Illegal type: %s (%s)", primitive.getClass(), primitive));
}
return type;
}
/**
* Whether or not to enable stream compression.
*
* @author Kristian
*/
public enum StreamOptions {
NO_COMPRESSION, GZIP_COMPRESSION,
}
private enum NbtType {
TAG_END(0, Void.class),
TAG_BYTE(1, byte.class),
TAG_SHORT(2, short.class),
TAG_INT(3, int.class),
TAG_LONG(4, long.class),
TAG_FLOAT(5, float.class),
TAG_DOUBLE(6, double.class),
TAG_BYTE_ARRAY(7, byte[].class),
TAG_INT_ARRAY(11, int[].class),
TAG_STRING(8, String.class),
TAG_LIST(9, List.class),
TAG_COMPOUND(10, Map.class);
TAG_END(0, Void.class), TAG_BYTE(1, byte.class), TAG_SHORT(2, short.class), TAG_INT(3,
int.class), TAG_LONG(4, long.class), TAG_FLOAT(5, float.class), TAG_DOUBLE(6,
double.class), TAG_BYTE_ARRAY(7, byte[].class), TAG_INT_ARRAY(11,
int[].class), TAG_STRING(8, String.class), TAG_LIST(9, List.class), TAG_COMPOUND(10,
Map.class);
// Unique NBT type
public final int id;
@ -566,21 +572,26 @@ public class NbtFactory {
}
}
/**
* Represents an object that provides a view of a native NMS class.
*
* @author Kristian
*/
public interface Wrapper {
/**
* Retrieve the underlying native NBT tag.
*
* @return The underlying NBT.
*/
Object getHandle();
}
/**
* Represents a method for loading an NBT compound.
*
* @author Kristian
*/
private static abstract class LoadCompoundMethod {
@ -594,27 +605,29 @@ public class NbtFactory {
/**
* Load an NBT compound from a given stream.
*
* @param input - the input stream.
* @return The loaded NBT compound.
*/
public abstract Object loadNbt(DataInput input);
}
/**
* Load an NBT compound from the NBTCompressedStreamTools static method in 1.7.2 - 1.7.5
*/
private static class LoadMethodWorldUpdate extends LoadCompoundMethod {
public LoadMethodWorldUpdate(Class<?> streamClass) {
LoadMethodWorldUpdate(Class<?> streamClass) {
setMethod(getMethod(Modifier.STATIC, 0, streamClass, null, DataInput.class));
}
@Override
public Object loadNbt(DataInput input) {
@Override public Object loadNbt(DataInput input) {
return invokeMethod(this.staticMethod, null, input);
}
}
/**
* Load an NBT compound from the NBTCompressedStreamTools static method in 1.7.8
*/
@ -622,8 +635,9 @@ public class NbtFactory {
private Object readLimiter;
public LoadMethodSkinUpdate(Class<?> streamClass, Class<?> readLimiterClass) {
setMethod(getMethod(Modifier.STATIC, 0, streamClass, null, DataInput.class, readLimiterClass));
LoadMethodSkinUpdate(Class<?> streamClass, Class<?> readLimiterClass) {
setMethod(getMethod(Modifier.STATIC, 0, streamClass, null, DataInput.class,
readLimiterClass));
// Find the unlimited read limiter
for (Field field : readLimiterClass.getDeclaredFields()) {
@ -637,28 +651,28 @@ public class NbtFactory {
}
}
@Override
public Object loadNbt(DataInput input) {
@Override public Object loadNbt(DataInput input) {
return invokeMethod(this.staticMethod, null, input, this.readLimiter);
}
}
/**
* Represents a root NBT compound.
* <p>
* All changes to this map will be reflected in the underlying NBT compound. Values may only be one of the following:
* <p> All changes to this map will be reflected in the underlying NBT compound. Values may only be one of the following:
* <ul>
* <li>Primitive types</li>
* <li>{@link String String}</li>
* <li>{@link NbtList}</li>
* <li>{@link NbtCompound}</li>
* <li>Primitive types</li>
* <li>{@link String String}</li>
* <li>{@link NbtList}</li>
* <li>{@link NbtCompound}</li>
* </ul>
* <p>
* See also:
* <ul>
* <li>{@link NbtFactory#createCompound()}</li>
* <li>{@link NbtFactory#fromCompound(Object)}</li>
* <li>{@link NbtFactory#createCompound()}</li>
* <li>{@link NbtFactory#fromCompound(Object)}</li>
* </ul>
*
* @author Kristian
*/
public final class NbtCompound extends ConvertedMap {
@ -706,7 +720,8 @@ public class NbtFactory {
/**
* Retrieve the list by the given name.
* @param key - the name of the list.
*
* @param key - the name of the list.
* @param createNew - whether or not to create a new list if its missing.
* @return An existing list, a new list or NULL.
*/
@ -721,7 +736,8 @@ public class NbtFactory {
/**
* Retrieve the map by the given name.
* @param key - the name of the map.
*
* @param key - the name of the map.
* @param createNew - whether or not to create a new map if its missing.
* @return An existing map, a new map or NULL.
*/
@ -736,7 +752,8 @@ public class NbtFactory {
* <p>
* Every element of the path (except the end) are assumed to be compounds, and will
* be created if they are missing.
* @param path - the path to the entry.
*
* @param path - the path to the entry.
* @param value - the new value of this entry.
* @return This compound, for chaining.
*/
@ -753,11 +770,11 @@ public class NbtFactory {
* <p>
* Every element of the path (except the end) are assumed to be compounds. The
* retrieval operation will be cancelled if any of them are missing.
*
* @param path - path to the entry.
* @return The value, or NULL if not found.
*/
@SuppressWarnings("unchecked")
public <T> T getPath(String path) {
@SuppressWarnings("unchecked") public <T> T getPath(String path) {
List<String> entries = getPathElements(path);
NbtCompound map = getMap(entries.subList(0, entries.size() - 1), false);
@ -769,8 +786,7 @@ public class NbtFactory {
/**
* Save the content of a NBT compound to a stream.
* <p>
* Use {@link Files#newOutputStreamSupplier(File)} to provide a stream supplier to a file.
*
* @param stream - the output stream.
* @param option - whether or not to compress the output.
* @throws IOException If anything went wrong.
@ -781,7 +797,8 @@ public class NbtFactory {
/**
* Retrieve a map from a given path.
* @param path - path of compounds to look up.
*
* @param path - path of compounds to look up.
* @param createNew - whether or not to create new compounds on the way.
* @return The map at this location.
*/
@ -804,6 +821,7 @@ public class NbtFactory {
/**
* Split the path into separate elements.
*
* @param path - the path to split.
* @return The elements.
*/
@ -812,13 +830,15 @@ public class NbtFactory {
}
}
/**
* Represents a root NBT list.
* See also:
* <ul>
* <li>{@link NbtFactory#createList(Iterable)}}</li>
* <li>{@link NbtFactory#fromList(Object)}</li>
* <li>{@link NbtFactory#createList(Iterable)}}</li>
* <li>{@link NbtFactory#fromList(Object)}</li>
* </ul>
*
* @author Kristian
*/
public final class NbtList extends ConvertedList {
@ -828,8 +848,10 @@ public class NbtFactory {
}
}
/**
* Represents a class for caching wrappers.
*
* @author Kristian
*/
private final class CachedNativeWrapper {
@ -852,9 +874,11 @@ public class NbtFactory {
}
}
/**
* Represents a map that wraps another map and automatically
* converts entries of its type and another exposed type.
*
* @author Kristian
*/
private class ConvertedMap extends AbstractMap<String, Object> implements Wrapper {
@ -879,32 +903,26 @@ public class NbtFactory {
}
// Modification
@Override
public Object put(String key, Object value) {
@Override public Object put(String key, Object value) {
return wrapOutgoing(this.original.put(key, unwrapIncoming(value)));
}
// Performance
@Override
public Object get(Object key) {
@Override public Object get(Object key) {
return wrapOutgoing(this.original.get(key));
}
@Override
public Object remove(Object key) {
@Override public Object remove(Object key) {
return wrapOutgoing(this.original.remove(key));
}
@Override
public boolean containsKey(Object key) {
@Override public boolean containsKey(Object key) {
return this.original.containsKey(key);
}
@Override
public Set<Entry<String, Object>> entrySet() {
@Override public Set<Entry<String, Object>> entrySet() {
return new AbstractSet<Entry<String, Object>>() {
@Override
public boolean add(Entry<String, Object> e) {
@Override public boolean add(Entry<String, Object> e) {
String key = e.getKey();
Object value = e.getValue();
@ -912,13 +930,11 @@ public class NbtFactory {
return true;
}
@Override
public int size() {
@Override public int size() {
return ConvertedMap.this.original.size();
}
@Override
public Iterator<Entry<String, Object>> iterator() {
@Override public Iterator<Entry<String, Object>> iterator() {
return ConvertedMap.this.iterator();
}
};
@ -928,34 +944,33 @@ public class NbtFactory {
final Iterator<Entry<String, Object>> proxy = this.original.entrySet().iterator();
return new Iterator<Entry<String, Object>>() {
@Override
public boolean hasNext() {
@Override public boolean hasNext() {
return proxy.hasNext();
}
@Override
public Entry<String, Object> next() {
@Override public Entry<String, Object> next() {
Entry<String, Object> entry = proxy.next();
return new SimpleEntry<String, Object>(entry.getKey(), wrapOutgoing(entry.getValue()));
return new SimpleEntry<String, Object>(entry.getKey(),
wrapOutgoing(entry.getValue()));
}
@Override
public void remove() {
@Override public void remove() {
proxy.remove();
}
};
}
@Override
public Object getHandle() {
@Override public Object getHandle() {
return this.handle;
}
}
/**
* Represents a list that wraps another list and converts elements
* of its type and another exposed type.
*
* @author Kristian
*/
private class ConvertedList extends AbstractList<Object> implements Wrapper {
@ -981,44 +996,38 @@ public class NbtFactory {
return unwrapValue(wrapped);
}
@Override
public Object get(int index) {
@Override public Object get(int index) {
return wrapOutgoing(this.original.get(index));
}
@Override
public int size() {
@Override public int size() {
return this.original.size();
}
@Override
public Object set(int index, Object element) {
@Override public Object set(int index, Object element) {
return wrapOutgoing(this.original.set(index, unwrapIncoming(element)));
}
@Override
public void add(int index, Object element) {
@Override public void add(int index, Object element) {
Object nbt = unwrapIncoming(element);
// Set the list type if its the first element
if (size() == 0) {
setFieldValue(NbtFactory.this.NBT_LIST_TYPE, this.handle, (byte) getNbtType(nbt).id);
setFieldValue(NbtFactory.this.NBT_LIST_TYPE, this.handle,
(byte) getNbtType(nbt).id);
}
this.original.add(index, nbt);
}
@Override
public Object remove(int index) {
@Override public Object remove(int index) {
return wrapOutgoing(this.original.remove(index));
}
@Override
public boolean remove(Object o) {
@Override public boolean remove(Object o) {
return this.original.remove(unwrapIncoming(o));
}
@Override
public Object getHandle() {
@Override public Object getHandle() {
return this.handle;
}
}

View File

@ -1,12 +1,4 @@
package com.plotsquared.bukkit.util;
import static com.intellectualcrafters.plot.util.ReflectionUtils.callConstructor;
import static com.intellectualcrafters.plot.util.ReflectionUtils.callMethod;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getCbClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getNmsClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getUtilClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.makeConstructor;
import static com.intellectualcrafters.plot.util.ReflectionUtils.makeMethod;
package com.github.intellectualsites.plotsquared.bukkit.util;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@ -17,6 +9,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.UUID;
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.*;
public class OfflinePlayerUtil {
public static Player loadPlayer(String name) {
@ -43,10 +37,12 @@ public class OfflinePlayerUtil {
Object worldServer = getWorldServer();
Object profile = newGameProfile(id, name);
Class<?> entityPlayerClass = getNmsClass("EntityPlayer");
Constructor entityPlayerConstructor = makeConstructor(entityPlayerClass, getNmsClass("MinecraftServer"), getNmsClass("WorldServer"),
getUtilClass("com.mojang.authlib.GameProfile"),
Constructor entityPlayerConstructor =
makeConstructor(entityPlayerClass, getNmsClass("MinecraftServer"),
getNmsClass("WorldServer"), getUtilClass("com.mojang.authlib.GameProfile"),
getNmsClass("PlayerInteractManager"));
Object entityPlayer = callConstructor(entityPlayerConstructor, server, worldServer, profile, interactManager);
Object entityPlayer =
callConstructor(entityPlayerConstructor, server, worldServer, profile, interactManager);
return (Player) getBukkitEntity(entityPlayer);
}
@ -55,7 +51,8 @@ public class OfflinePlayerUtil {
if (gameProfileClass == null) { //Before uuids
return name;
}
Constructor gameProfileConstructor = makeConstructor(gameProfileClass, UUID.class, String.class);
Constructor gameProfileConstructor =
makeConstructor(gameProfileClass, UUID.class, String.class);
if (gameProfileConstructor == null) { //Version has string constructor
gameProfileConstructor = makeConstructor(gameProfileClass, String.class, String.class);
return callConstructor(gameProfileConstructor, id.toString(), name);

View File

@ -1,19 +1,17 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.ChunkLoc;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.Plot;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefClass;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefConstructor;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefField;
import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.RefMethod;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
@ -25,10 +23,11 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
/**
* An utility that can be used to send chunks, rather than using bukkit code to do so (uses heavy NMS)
*
import static com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils.getRefClass;
/**
* An utility that can be used to send chunks, rather than using bukkit code
* to do so (uses heavy NMS).
*/
public class SendChunk {
@ -40,7 +39,7 @@ public class SendChunk {
private final RefMethod methodInitLighting;
/**
* Constructor
* Constructor.
*/
public SendChunk() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException {
RefConstructor tempMapChunk;
@ -51,16 +50,7 @@ public class SendChunk {
RefClass classChunk = getRefClass("{nms}.Chunk");
this.methodInitLighting = classChunk.getMethod("initLighting");
RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 4)) {
//this works for 1.9.4 and 1.10
tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(),int.class);
} else {
try {
tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), boolean.class, int.class);
} catch (NoSuchMethodException ignored) {
tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(),boolean.class, int.class, int.class);
}
}
tempMapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), int.class);
this.mapChunk = tempMapChunk;
RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
this.connection = classEntityPlayer.getField("playerConnection");
@ -90,7 +80,7 @@ public class SendChunk {
Location location = null;
String world;
if (plot != null) {
world = plot.getArea().worldname;
world = plot.getWorldName();
} else {
location = pp.getLocation();
world = location.getWorld();
@ -117,39 +107,30 @@ public class SendChunk {
chunks.remove(chunk);
Object con = this.connection.of(entity).get();
Object packet = null;
if (PS.get().checkVersion(PS.get().IMP.getServerVersion(), 1, 9, 4)) {
try {
packet = this.mapChunk.create(c,65535);
} catch (Exception ignored) {}
} else {
try {
packet = this.mapChunk.create(c, true, 65535);
} catch (ReflectiveOperationException | IllegalArgumentException e) {
try {
packet = this.mapChunk.create(c, true, 65535, 5);
} catch (ReflectiveOperationException | IllegalArgumentException e1) {
e1.printStackTrace();
}
}
try {
packet = this.mapChunk.create(c, 65535);
} catch (Exception ignored) {
}
if (packet == null) {
PS.debug("Error with PacketPlayOutMapChunk reflection.");
PlotSquared.debug("Error with PacketPlayOutMapChunk reflection.");
}
this.send.of(con).call(packet);
}
}
for (final Chunk chunk : chunks) {
TaskManager.runTask(new Runnable() {
@Override
public void run() {
@Override public void run() {
try {
chunk.unload(true, false);
} catch (Throwable ignored) {
String worldName = chunk.getWorld().getName();
PS.debug("$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";" + chunk.getZ());
PS.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
PS.debug("$3 - $4" + worldName + "/level.dat or " + worldName
+ "/level_old.dat may be corrupt (try repairing or removing these)");
PlotSquared.debug(
"$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";"
+ chunk.getZ());
PlotSquared
.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
PlotSquared.debug("$3 - $4" + worldName + "/level.dat or " + worldName
+ "/level_old.dat may be corrupt (try repairing or removing these)");
}
}
});

View File

@ -1,9 +1,9 @@
package com.plotsquared.bukkit.util;
package com.github.intellectualsites.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.plotsquared.bukkit.generator.BukkitAugmentedGenerator;
import com.github.intellectualsites.plotsquared.bukkit.generator.BukkitAugmentedGenerator;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper;
import com.github.intellectualsites.plotsquared.plot.util.SetupUtils;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
@ -16,7 +16,7 @@ public class SetGenCB {
public static void setGenerator(World world) throws Exception {
SetupUtils.manager.updateGenerators();
PS.get().removePlotAreas(world.getName());
PlotSquared.get().removePlotAreas(world.getName());
ChunkGenerator gen = world.getGenerator();
if (gen == null) {
return;
@ -52,6 +52,7 @@ public class SetGenCB {
}
}
}
PS.get().loadWorld(world.getName(), PS.get().IMP.getGenerator(world.getName(), null));
PlotSquared.get()
.loadWorld(world.getName(), PlotSquared.get().IMP.getGenerator(world.getName(), null));
}
}

View File

@ -0,0 +1,261 @@
package com.github.intellectualsites.plotsquared.bukkit.util.block;
import com.github.intellectualsites.plotsquared.bukkit.object.schematic.StateWrapper;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.LegacyPlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import com.github.intellectualsites.plotsquared.plot.object.StringPlotBlock;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.github.intellectualsites.plotsquared.plot.util.block.BasicLocalBlockQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock;
import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Locale;
public class BukkitLocalQueue<T> extends BasicLocalBlockQueue<T> {
private Field fieldNeighbors;
private Method chunkGetHandle;
public BukkitLocalQueue(String world) {
super(world);
}
@Override public LocalChunk<T> getLocalChunk(int x, int z) {
return (LocalChunk<T>) new BasicLocalChunk(this, x, z) {
// Custom stuff?
};
}
@Override public void optimize() {
}
@Override public PlotBlock getBlock(int x, int y, int z) {
World worldObj = Bukkit.getWorld(getWorld());
Block block = worldObj.getBlockAt(x, y, z);
if (block == null) {
return PlotBlock.get(0, 0);
}
// int id = block.getTypeId();
// if (id == 0) {
// return PlotBlock.get(0, 0);
// }
// return PlotBlock.get(id, block.getData());
return PlotBlock.get(block.getType().toString());
}
@Override public void refreshChunk(int x, int z) {
World worldObj = Bukkit.getWorld(getWorld());
worldObj.refreshChunk(x, z);
}
@Override public void fixChunkLighting(int x, int z) {
// Do nothing
}
@Override public final void regenChunk(int x, int z) {
World worldObj = Bukkit.getWorld(getWorld());
worldObj.regenerateChunk(x, z);
}
@Override public final void setComponents(LocalChunk<T> lc) {
if (isBaseBlocks()) {
setBaseBlocks(lc);
} else {
setBlocks(lc);
}
}
public World getBukkitWorld() {
return Bukkit.getWorld(getWorld());
}
public Chunk getChunk(int x, int z) {
return getBukkitWorld().getChunkAt(x, z);
}
public void setBlocks(LocalChunk<T> lc) {
World worldObj = Bukkit.getWorld(getWorld());
Chunk chunk = worldObj.getChunkAt(lc.getX(), lc.getZ());
chunk.load(true);
for (int layer = 0; layer < lc.blocks.length; layer++) {
PlotBlock[] blocksLayer = (PlotBlock[]) lc.blocks[layer];
if (blocksLayer != null) {
for (int j = 0; j < blocksLayer.length; j++) {
if (blocksLayer[j] != null) {
PlotBlock block = blocksLayer[j];
int x = MainUtil.x_loc[layer][j];
int y = MainUtil.y_loc[layer][j];
int z = MainUtil.z_loc[layer][j];
Block existing = chunk.getBlock(x, y, z);
if (equals(block, existing)) {
continue;
}
setMaterial(block, existing);
}
}
}
}
}
public void setBaseBlocks(LocalChunk<T> lc) {
World worldObj = Bukkit.getWorld(getWorld());
Chunk chunk = worldObj.getChunkAt(lc.getX(), lc.getZ());
chunk.load(true);
for (int layer = 0; layer < lc.baseblocks.length; layer++) {
BaseBlock[] blocksLayer = lc.baseblocks[layer];
if (blocksLayer != null) {
for (int j = 0; j < blocksLayer.length; j++) {
if (blocksLayer[j] != null) {
BaseBlock block = blocksLayer[j];
int x = MainUtil.x_loc[layer][j];
int y = MainUtil.y_loc[layer][j];
int z = MainUtil.z_loc[layer][j];
Block existing = chunk.getBlock(x, y, z);
if (equals(PlotBlock.get(block), existing) && existing.getBlockData()
.matches(BukkitAdapter.adapt(block))) {
continue;
}
existing.setType(BukkitAdapter.adapt(block.getBlockType()), false);
existing.setBlockData(BukkitAdapter.adapt(block), false);
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(worldObj.getName(), existing.getX(), existing.getY(),
existing.getZ());
}
}
}
}
}
}
private void setMaterial(@NonNull final PlotBlock plotBlock, @NonNull final Block block) {
final Material material;
if (plotBlock instanceof StringPlotBlock) {
material = Material
.getMaterial(((StringPlotBlock) plotBlock).getItemId().toUpperCase(Locale.ENGLISH));
if (material == null) {
throw new IllegalStateException(String
.format("Could not find material that matches %s",
((StringPlotBlock) plotBlock).getItemId()));
}
} else {
final LegacyPlotBlock legacyPlotBlock = (LegacyPlotBlock) plotBlock;
material = PlotSquared.get().IMP.getLegacyMappings()
.fromLegacyToString(legacyPlotBlock.getId(), legacyPlotBlock.getData())
.to(Material.class);
if (material == null) {
throw new IllegalStateException(String
.format("Could not find material that matches %s", legacyPlotBlock.toString()));
}
}
block.setType(material, false);
}
private boolean equals(@NonNull final PlotBlock plotBlock, @NonNull final Block block) {
if (plotBlock instanceof StringPlotBlock) {
return ((StringPlotBlock) plotBlock).idEquals(block.getType().name());
}
final LegacyPlotBlock legacyPlotBlock = (LegacyPlotBlock) plotBlock;
return Material.getMaterial(PlotSquared.get().IMP.getLegacyMappings()
.fromLegacyToString(((LegacyPlotBlock) plotBlock).id,
((LegacyPlotBlock) plotBlock).data).toString()) == block.getType() && (
legacyPlotBlock.id == 0 || legacyPlotBlock.data == block.getData());
}
public void setBiomes(LocalChunk<T> lc) {
if (lc.biomes != null) {
World worldObj = Bukkit.getWorld(getWorld());
int bx = lc.getX() << 4;
int bz = lc.getX() << 4;
String last = null;
Biome biome = null;
for (int x = 0; x < lc.biomes.length; x++) {
String[] biomes2 = lc.biomes[x];
if (biomes2 != null) {
for (int y = 0; y < biomes2.length; y++) {
String biomeStr = biomes2[y];
if (biomeStr != null) {
if (last == null || !StringMan.isEqual(last, biomeStr)) {
biome = Biome.valueOf(biomeStr.toUpperCase());
}
worldObj.setBiome(bx, bz, biome);
}
}
}
}
}
}
/**
* Exploiting a bug in the vanilla lighting algorithm for faster block placement
* - Could have been achieved without reflection by force unloading specific chunks
* - Much faster just setting the variable manually though
*
* @param chunk
* @return
*/
protected Object[] disableLighting(Chunk chunk) {
try {
if (chunkGetHandle == null) {
chunkGetHandle = chunk.getClass().getDeclaredMethod("getHandle");
chunkGetHandle.setAccessible(true);
}
Object nmsChunk = chunkGetHandle.invoke(chunk);
if (fieldNeighbors == null) {
fieldNeighbors = nmsChunk.getClass().getDeclaredField("neighbors");
fieldNeighbors.setAccessible(true);
}
Object value = fieldNeighbors.get(nmsChunk);
fieldNeighbors.set(nmsChunk, 0);
return new Object[] {nmsChunk, value};
} catch (Throwable ignore) {
}
return null;
}
protected void disableLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], 0);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
protected void resetLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], disableResult[1]);
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
}
protected void enableLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], 0x739C0);
} catch (Throwable ignore) {
}
}
}
}

View File

@ -0,0 +1,184 @@
package com.github.intellectualsites.plotsquared.bukkit.util.block;
import com.github.intellectualsites.plotsquared.bukkit.util.BukkitUtil;
import com.github.intellectualsites.plotsquared.plot.object.ChunkWrapper;
import com.github.intellectualsites.plotsquared.plot.object.Location;
import com.github.intellectualsites.plotsquared.plot.object.PlotBlock;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import java.util.Arrays;
public class GenChunk extends ScopedLocalBlockQueue {
public final Biome[] biomes;
public PlotBlock[][] result;
public BiomeGrid grid;
public Chunk chunk;
public String world;
public int cx;
public int cz;
@Getter @Setter private ChunkData cd = null;
public GenChunk(Chunk chunk, ChunkWrapper wrap) {
super(null, new Location(null, 0, 0, 0), new Location(null, 15, 255, 15));
this.biomes = Biome.values();
}
public void setChunk(Chunk chunk) {
this.chunk = chunk;
}
public Chunk getChunk() {
if (chunk == null) {
World worldObj = BukkitUtil.getWorld(world);
if (worldObj != null) {
this.chunk = worldObj.getChunkAt(cx, cz);
}
}
return chunk;
}
public void setChunk(ChunkWrapper wrap) {
chunk = null;
world = wrap.world;
cx = wrap.x;
cz = wrap.z;
}
@Override public void fillBiome(String biomeName) {
if (grid == null) {
return;
}
Biome biome = Biome.valueOf(biomeName.toUpperCase());
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
this.grid.setBiome(x, z, biome);
}
}
}
@Override public void setCuboid(Location pos1, Location pos2, PlotBlock block) {
if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15
&& pos2.getZ() == 15) {
for (int y = pos1.getY(); y <= pos2.getY(); y++) {
int layer = y >> 4;
PlotBlock[] data = result[layer];
if (data == null) {
result[layer] = data = new PlotBlock[4096];
}
int start = y << 8;
int end = start + 256;
Arrays.fill(data, start, end, block);
}
}
int minx = Math.min(pos1.getX(), pos2.getX());
int miny = Math.min(pos1.getY(), pos2.getY());
int minz = Math.min(pos1.getZ(), pos2.getZ());
int maxx = Math.max(pos1.getX(), pos2.getX());
int maxy = Math.max(pos1.getY(), pos2.getY());
int maxz = Math.max(pos1.getZ(), pos2.getZ());
cd.setRegion(minx, miny, minz, maxx, maxy, maxz, block.to(Material.class));
}
@Override public boolean setBiome(int x, int z, String biome) {
return setBiome(x, z, Biome.valueOf(biome.toUpperCase()));
}
public boolean setBiome(int x, int z, Biome biome) {
if (this.grid != null) {
this.grid.setBiome(x, z, biome);
return true;
}
return false;
}
@Override public boolean setBlock(int x, int y, int z, PlotBlock id) {
if (this.result == null) {
this.cd.setBlock(x, y, z, id.to(Material.class));
return true;
}
this.cd.setBlock(x, y, z, id.to(Material.class));
this.storeCache(x, y, z, id);
return true;
}
private void storeCache(final int x, final int y, final int z, final PlotBlock id) {
int i = MainUtil.CACHE_I[y][x][z];
PlotBlock[] v = this.result[i];
if (v == null) {
this.result[i] = v = new PlotBlock[4096];
}
int j = MainUtil.CACHE_J[y][x][z];
v[j] = id;
}
@Override public boolean setBlock(int x, int y, int z, BaseBlock id) {
if (this.result == null) {
this.cd.setBlock(x, y, z, BukkitAdapter.adapt(id));
return true;
}
this.cd.setBlock(x, y, z, BukkitAdapter.adapt(id));
this.storeCache(x, y, z, PlotBlock.get(id.getBlockType().getId()));
return true;
}
@Override public PlotBlock getBlock(int x, int y, int z) {
int i = MainUtil.CACHE_I[y][x][z];
if (result == null) {
return PlotBlock.get(cd.getType(x, y, z));
}
PlotBlock[] array = result[i];
if (array == null) {
return PlotBlock.get("");
}
int j = MainUtil.CACHE_J[y][x][z];
return array[j];
}
public int getX() {
return chunk == null ? cx : chunk.getX();
}
public int getZ() {
return chunk == null ? cz : chunk.getZ();
}
@Override public String getWorld() {
return chunk == null ? world : chunk.getWorld().getName();
}
@Override public Location getMax() {
return new Location(getWorld(), 15 + (getX() << 4), 255, 15 + (getZ() << 4));
}
@Override public Location getMin() {
return new Location(getWorld(), getX() << 4, 0, getZ() << 4);
}
public GenChunk clone() {
GenChunk toReturn =
new GenChunk(chunk, new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ()));
if (this.result != null) {
for (int i = 0; i < this.result.length; i++) {
PlotBlock[] matrix = this.result[i];
if (matrix != null) {
toReturn.result[i] = new PlotBlock[matrix.length];
System.arraycopy(matrix, 0, toReturn.result[i], 0, matrix.length);
}
}
}
toReturn.cd = this.cd;
return toReturn;
}
}

View File

@ -1,12 +1,11 @@
package com.plotsquared.bukkit.uuid;
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import java.io.File;
import java.io.FilenameFilter;
public class DatFileFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
@Override public boolean accept(File dir, String name) {
return name.endsWith(".dat");
}
}

View File

@ -0,0 +1,43 @@
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitOfflinePlayer;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitPlayer;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
public class DefaultUUIDWrapper extends UUIDWrapper {
@Override public UUID getUUID(PlotPlayer player) {
return ((BukkitPlayer) player).player.getUniqueId();
}
@Override public UUID getUUID(OfflinePlotPlayer player) {
return player.getUUID();
}
@Override public OfflinePlotPlayer getOfflinePlayer(UUID uuid) {
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(uuid));
}
@Override public UUID getUUID(String name) {
return Bukkit.getOfflinePlayer(name).getUniqueId();
}
@Override public OfflinePlotPlayer[] getOfflinePlayers() {
OfflinePlayer[] ops = Bukkit.getOfflinePlayers();
BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length];
for (int i = 0; i < ops.length; i++) {
toReturn[i] = new BukkitOfflinePlayer(ops[i]);
}
return toReturn;
}
@Override public OfflinePlotPlayer getOfflinePlayer(String name) {
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name));
}
}

View File

@ -1,22 +1,25 @@
package com.plotsquared.bukkit.uuid;
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import com.github.intellectualsites.plotsquared.bukkit.util.NbtFactory;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.StringWrapper;
import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandlerImplementation;
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Sets;
import com.google.common.io.ByteSource;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.expiry.ExpireManager;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.util.NbtFactory;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@ -24,8 +27,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.World;
public class FileUUIDHandler extends UUIDHandlerImplementation {
@ -33,8 +34,7 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
super(wrapper);
}
@Override
public boolean startCaching(Runnable whenDone) {
@Override public boolean startCaching(Runnable whenDone) {
return super.startCaching(whenDone) && cache(whenDone);
}
@ -48,13 +48,13 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
world = worlds.get(0).getName();
}
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
PS.debug(C.PREFIX + "&6Starting player data caching for: " + world);
File uuidFile = new File(PS.get().IMP.getDirectory(), "uuids.txt");
@Override public void run() {
PlotSquared.debug(C.PREFIX + "&6Starting player data caching for: " + world);
File uuidFile = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt");
if (uuidFile.exists()) {
try {
List<String> lines = Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8);
List<String> lines =
Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8);
for (String line : lines) {
try {
line = line.trim();
@ -64,7 +64,8 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", "");
String[] split = line.split("\\|");
String name = split[0];
if (name.isEmpty() || (name.length() > 16) || !StringMan.isAlphanumericUnd(name)) {
if (name.isEmpty() || (name.length() > 16) || !StringMan
.isAlphanumericUnd(name)) {
continue;
}
UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name);
@ -80,11 +81,13 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
e.printStackTrace();
}
}
HashBiMap<StringWrapper, UUID> toAdd =
HashBiMap.create(new HashMap<StringWrapper, UUID>());
if (Settings.UUID.NATIVE_UUID_PROVIDER) {
HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
HashSet<UUID> all = UUIDHandler.getAllUUIDS();
PS.debug("&aFast mode UUID caching enabled!");
File playerDataFolder = new File(container, world + File.separator + "playerdata");
PlotSquared.debug("&aFast mode UUID caching enabled!");
File playerDataFolder =
new File(container, world + File.separator + "playerdata");
String[] dat = playerDataFolder.list(new DatFileFilter());
boolean check = all.isEmpty();
if (dat != null) {
@ -94,23 +97,28 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
UUID uuid = UUID.fromString(s);
if (check || all.remove(uuid)) {
File file = new File(playerDataFolder, current);
ByteSource is = com.google.common.io.Files.asByteSource(file);
NbtFactory.NbtCompound compound = NbtFactory.fromStream(is, NbtFactory.StreamOptions.GZIP_COMPRESSION);
NbtFactory.NbtCompound compound = NbtFactory
.fromStream(new FileInputStream(file),
NbtFactory.StreamOptions.GZIP_COMPRESSION);
if (!compound.containsKey("bukkit")) {
PS.debug("ERROR: Player data does not contain the the key \"bukkit\"");
PlotSquared.debug("ERROR: Player data (" + uuid.toString()
+ ".dat) does not contain the the key \"bukkit\"");
} else {
NbtFactory.NbtCompound bukkit = (NbtFactory.NbtCompound) compound.get("bukkit");
NbtFactory.NbtCompound bukkit =
(NbtFactory.NbtCompound) compound.get("bukkit");
String name = (String) bukkit.get("lastKnownName");
long last = (long) bukkit.get("lastPlayed");
long first = (long) bukkit.get("firstPlayed");
if (ExpireManager.IMP != null) {
ExpireManager.IMP.storeDate(uuid, last);
ExpireManager.IMP.storeAccountAge(uuid, last - first);
}
toAdd.put(new StringWrapper(name), uuid);
}
}
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
PS.debug(C.PREFIX + "Invalid playerdata: " + current);
PlotSquared.debug(C.PREFIX + "Invalid playerdata: " + current);
}
}
}
@ -121,17 +129,18 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
}
return;
} else {
PS.debug("Failed to cache: " + all.size() + " uuids - slowly processing all files");
PlotSquared.debug("Failed to cache: " + all.size()
+ " uuids - slowly processing all files");
}
}
HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
HashSet<String> worlds = Sets.newHashSet(world, "world");
HashSet<UUID> uuids = new HashSet<>();
HashSet<String> names = new HashSet<>();
File playerDataFolder = null;
for (String worldName : worlds) {
// Getting UUIDs
playerDataFolder = new File(container, worldName + File.separator + "playerdata");
playerDataFolder =
new File(container, worldName + File.separator + "playerdata");
String[] dat = playerDataFolder.list(new DatFileFilter());
if ((dat != null) && (dat.length != 0)) {
for (String current : dat) {
@ -140,7 +149,7 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
UUID uuid = UUID.fromString(s);
uuids.add(uuid);
} catch (Exception ignored) {
PS.debug(C.PREFIX + "Invalid PlayerData: " + current);
PlotSquared.debug(C.PREFIX + "Invalid PlayerData: " + current);
}
}
break;
@ -157,34 +166,45 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
}
for (UUID uuid : uuids) {
try {
File file = new File(playerDataFolder + File.separator + uuid.toString() + ".dat");
File file =
new File(playerDataFolder + File.separator + uuid.toString() + ".dat");
if (!file.exists()) {
continue;
}
ByteSource is = com.google.common.io.Files.asByteSource(file);
NbtFactory.NbtCompound compound = NbtFactory.fromStream(is, NbtFactory.StreamOptions.GZIP_COMPRESSION);
NbtFactory.NbtCompound compound = NbtFactory
.fromStream(new FileInputStream(file),
NbtFactory.StreamOptions.GZIP_COMPRESSION);
if (!compound.containsKey("bukkit")) {
PS.debug("ERROR: Player data does not contain the the key \"bukkit\"");
PlotSquared.debug("ERROR: Player data (" + uuid.toString()
+ ".dat) does not contain the the key \"bukkit\"");
} else {
NbtFactory.NbtCompound bukkit = (NbtFactory.NbtCompound) compound.get("bukkit");
NbtFactory.NbtCompound bukkit =
(NbtFactory.NbtCompound) compound.get("bukkit");
String name = (String) bukkit.get("lastKnownName");
long last = (long) bukkit.get("lastPlayed");
if (Settings.UUID.OFFLINE) {
if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase().equals(name)) {
uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name);
} else {
long most = (long) compound.get("UUIDMost");
long least = (long) compound.get("UUIDLeast");
uuid = new UUID(most, least);
StringWrapper wrap = new StringWrapper(name);
if (!toAdd.containsKey(wrap)) {
long last = (long) bukkit.get("lastPlayed");
long first = (long) bukkit.get("firstPlayed");
if (Settings.UUID.OFFLINE) {
if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase()
.equals(name)) {
uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name);
} else {
long most = (long) compound.get("UUIDMost");
long least = (long) compound.get("UUIDLeast");
uuid = new UUID(most, least);
}
}
if (ExpireManager.IMP != null) {
ExpireManager.IMP.storeDate(uuid, last);
ExpireManager.IMP.storeAccountAge(uuid, last - first);
}
toAdd.put(wrap, uuid);
}
if (ExpireManager.IMP != null) {
ExpireManager.IMP.storeDate(uuid, last);
}
toAdd.put(new StringWrapper(name), uuid);
}
} catch (Exception ignored) {
PS.debug(C.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat");
PlotSquared
.debug(C.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat");
}
}
for (String name : names) {
@ -194,15 +214,18 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
}
if (getUUIDMap().isEmpty()) {
for (OfflinePlotPlayer op : FileUUIDHandler.this.uuidWrapper.getOfflinePlayers()) {
for (OfflinePlotPlayer op : FileUUIDHandler.this.uuidWrapper
.getOfflinePlayers()) {
long last = op.getLastPlayed();
if (last != 0) {
String name = op.getName();
StringWrapper wrap = new StringWrapper(name);
UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(op);
toAdd.put(wrap, uuid);
if (ExpireManager.IMP != null) {
ExpireManager.IMP.storeDate(uuid, last);
if (!toAdd.containsKey(wrap)) {
UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(op);
toAdd.put(wrap, uuid);
if (ExpireManager.IMP != null) {
ExpireManager.IMP.storeDate(uuid, last);
}
}
}
}
@ -216,11 +239,9 @@ public class FileUUIDHandler extends UUIDHandlerImplementation {
return true;
}
@Override
public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
@Override public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name);
TaskManager.runTask(ifFetch);
}

View File

@ -0,0 +1,32 @@
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.google.common.base.Charsets;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
public class LowerOfflineUUIDWrapper extends OfflineUUIDWrapper {
@Override public UUID getUUID(PlotPlayer player) {
return UUID.nameUUIDFromBytes(
("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
}
@Override public UUID getUUID(OfflinePlotPlayer player) {
return UUID.nameUUIDFromBytes(
("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
}
@Override public UUID getUUID(OfflinePlayer player) {
return UUID.nameUUIDFromBytes(
("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
}
@Override public UUID getUUID(String name) {
return UUID
.nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8));
}
}

View File

@ -1,14 +1,14 @@
package com.plotsquared.bukkit.uuid;
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import com.github.intellectualsites.plotsquared.bukkit.object.BukkitOfflinePlayer;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.object.OfflinePlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer;
import com.github.intellectualsites.plotsquared.plot.object.StringWrapper;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.google.common.base.Charsets;
import com.google.common.collect.BiMap;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
@ -32,22 +32,22 @@ public class OfflineUUIDWrapper extends UUIDWrapper {
}
}
@Override
public UUID getUUID(PlotPlayer player) {
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
@Override public UUID getUUID(PlotPlayer player) {
return UUID
.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
}
@Override
public UUID getUUID(OfflinePlotPlayer player) {
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
@Override public UUID getUUID(OfflinePlotPlayer player) {
return UUID
.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
}
public UUID getUUID(OfflinePlayer player) {
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
return UUID
.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
}
@Override
public OfflinePlotPlayer getOfflinePlayer(UUID uuid) {
@Override public OfflinePlotPlayer getOfflinePlayer(UUID uuid) {
BiMap<UUID, StringWrapper> map = UUIDHandler.getUuidMap().inverse();
String name = null;
if (map.containsKey(uuid)) {
@ -77,24 +77,23 @@ public class OfflineUUIDWrapper extends UUIDWrapper {
if (players instanceof Player[]) {
return (Player[]) players;
} else {
@SuppressWarnings("unchecked") Collection<? extends Player> p = (Collection<? extends Player>) players;
@SuppressWarnings("unchecked") Collection<? extends Player> p =
(Collection<? extends Player>) players;
return p.toArray(new Player[p.size()]);
}
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ignored) {
PS.debug("Failed to resolve online players");
PlotSquared.debug("Failed to resolve online players");
this.getOnline = null;
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
return onlinePlayers.toArray(new Player[onlinePlayers.size()]);
}
}
@Override
public UUID getUUID(String name) {
@Override public UUID getUUID(String name) {
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8));
}
@Override
public OfflinePlotPlayer[] getOfflinePlayers() {
@Override public OfflinePlotPlayer[] getOfflinePlayers() {
OfflinePlayer[] ops = Bukkit.getOfflinePlayers();
BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length];
for (int i = 0; i < ops.length; i++) {
@ -103,8 +102,7 @@ public class OfflineUUIDWrapper extends UUIDWrapper {
return toReturn;
}
@Override
public OfflinePlotPlayer getOfflinePlayer(String name) {
@Override public OfflinePlotPlayer getOfflinePlayer(String name) {
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name));
}
}

View File

@ -1,18 +1,24 @@
package com.plotsquared.bukkit.uuid;
package com.github.intellectualsites.plotsquared.bukkit.uuid;
import com.github.intellectualsites.plotsquared.plot.PlotSquared;
import com.github.intellectualsites.plotsquared.plot.config.C;
import com.github.intellectualsites.plotsquared.plot.config.Settings;
import com.github.intellectualsites.plotsquared.plot.database.SQLite;
import com.github.intellectualsites.plotsquared.plot.object.RunnableVal;
import com.github.intellectualsites.plotsquared.plot.object.StringWrapper;
import com.github.intellectualsites.plotsquared.plot.util.MainUtil;
import com.github.intellectualsites.plotsquared.plot.util.TaskManager;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandlerImplementation;
import com.github.intellectualsites.plotsquared.plot.uuid.UUIDWrapper;
import com.google.common.collect.HashBiMap;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.SQLite;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.StringWrapper;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
@ -25,22 +31,20 @@ import java.util.ArrayDeque;
import java.util.Collections;
import java.util.HashMap;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class SQLUUIDHandler extends UUIDHandlerImplementation {
final int MAX_REQUESTS = 500;
private final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
private final String PROFILE_URL =
"https://sessionserver.mojang.com/session/minecraft/profile/";
private final int INTERVAL = 12000;
private final JSONParser jsonParser = new JSONParser();
private final SQLite sqlite;
public SQLUUIDHandler(UUIDWrapper wrapper) {
super(wrapper);
this.sqlite = new SQLite(MainUtil.getFile(PS.get().IMP.getDirectory(), "usercache.db"));
this.sqlite =
new SQLite(MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db"));
try {
this.sqlite.openConnection();
} catch (ClassNotFoundException | SQLException e) {
@ -48,8 +52,8 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
}
try (PreparedStatement stmt = getConnection().prepareStatement(
"CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username)"
+ ')')) {
"CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username)"
+ ')')) {
stmt.execute();
} catch (SQLException e) {
e.printStackTrace();
@ -63,20 +67,21 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
}
}
@Override
public boolean startCaching(final Runnable whenDone) {
@Override public boolean startCaching(final Runnable whenDone) {
if (!super.startCaching(whenDone)) {
return false;
}
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
try {
HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
try (PreparedStatement statement = getConnection().prepareStatement("SELECT `uuid`, `username` FROM `usercache`");
ResultSet resultSet = statement.executeQuery()) {
HashBiMap<StringWrapper, UUID> toAdd =
HashBiMap.create(new HashMap<StringWrapper, UUID>());
try (PreparedStatement statement = getConnection()
.prepareStatement("SELECT `uuid`, `username` FROM `usercache`");
ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
StringWrapper username = new StringWrapper(resultSet.getString("username"));
StringWrapper username =
new StringWrapper(resultSet.getString("username"));
UUID uuid = UUID.fromString(resultSet.getString("uuid"));
toAdd.put(new StringWrapper(username.value), uuid);
}
@ -95,10 +100,10 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
}
return;
}
FileUUIDHandler fileHandler = new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper);
FileUUIDHandler fileHandler =
new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper);
fileHandler.startCaching(new Runnable() {
@Override
public void run() {
@Override public void run() {
// If the file based UUID handler didn't cache it, then we can't cache offline mode
// Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does
if (Settings.UUID.OFFLINE) {
@ -109,31 +114,46 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
}
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
try {
if (toFetch.isEmpty()) {
if (whenDone != null) {
whenDone.run();
@Override public void run() {
while (!toFetch.isEmpty()) {
try {
for (int i = 0;
i < Math.min(500, toFetch.size()); i++) {
UUID uuid = toFetch.pop();
HttpURLConnection connection =
(HttpURLConnection) new URL(
SQLUUIDHandler.this.PROFILE_URL + uuid
.toString().replace("-", ""))
.openConnection();
try (InputStream con = connection
.getInputStream()) {
InputStreamReader reader =
new InputStreamReader(con);
JSONObject response =
(JSONObject) SQLUUIDHandler.this.jsonParser
.parse(reader);
String name = (String) response.get("name");
if (name != null) {
add(new StringWrapper(name), uuid);
}
}
connection.disconnect();
}
return;
} catch (IOException | ParseException e) {
PlotSquared.debug(
"Invalid response from Mojang: Some UUIDs will be cached later. (`unknown` until then or player joins)");
}
for (int i = 0; i < Math.min(500, toFetch.size()); i++) {
UUID uuid = toFetch.pop();
HttpURLConnection connection =
(HttpURLConnection) new URL(SQLUUIDHandler.this.PROFILE_URL + uuid.toString().replace("-", ""))
.openConnection();
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
JSONObject response = (JSONObject) SQLUUIDHandler.this.jsonParser.parse(reader);
String name = (String) response.get("name");
if (name != null) {
add(new StringWrapper(name), uuid);
}
try {
Thread.sleep(INTERVAL * 50);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
TaskManager.runTaskLaterAsync(this, SQLUUIDHandler.this.INTERVAL);
if (whenDone != null) {
whenDone.run();
}
return;
}
});
}
@ -146,15 +166,14 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
return true;
}
@Override
public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
PS.debug(C.PREFIX + "UUID for '" + name + "' was null. We'll cache this from the Mojang servers!");
@Override public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
PlotSquared.debug(C.PREFIX + "UUID for '" + name
+ "' was null. We'll cache this from the Mojang servers!");
if (ifFetch == null) {
return;
}
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
@Override public void run() {
try {
URL url = new URL(SQLUUIDHandler.this.PROFILE_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@ -168,13 +187,14 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
stream.write(body.getBytes());
stream.flush();
stream.close();
JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser.parse(new InputStreamReader(connection.getInputStream()));
JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser
.parse(new InputStreamReader(connection.getInputStream()));
JSONObject jsonProfile = (JSONObject) array.get(0);
String id = (String) jsonProfile.get("id");
String name = (String) jsonProfile.get("name");
ifFetch.value = UUID.fromString(
id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) + '-' + id.substring(16, 20) + '-' + id
.substring(20, 32));
id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16)
+ '-' + id.substring(16, 20) + '-' + id.substring(20, 32));
} catch (IOException | ParseException e) {
e.printStackTrace();
}
@ -183,8 +203,7 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
});
}
@Override
public void handleShutdown() {
@Override public void handleShutdown() {
super.handleShutdown();
try {
getConnection().close();
@ -193,18 +212,18 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
}
}
@Override
public boolean add(final StringWrapper name, final UUID uuid) {
@Override public boolean add(final StringWrapper name, final UUID uuid) {
// Ignoring duplicates
if (super.add(name, uuid)) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
try (PreparedStatement statement = getConnection().prepareStatement("REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) {
@Override public void run() {
try (PreparedStatement statement = getConnection().prepareStatement(
"REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) {
statement.setString(1, uuid.toString());
statement.setString(2, name.toString());
statement.execute();
PS.debug(C.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'");
PlotSquared
.debug(C.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'");
} catch (SQLException e) {
e.printStackTrace();
}
@ -218,17 +237,17 @@ public class SQLUUIDHandler extends UUIDHandlerImplementation {
/**
* This is useful for name changes
*/
@Override
public void rename(final UUID uuid, final StringWrapper name) {
@Override public void rename(final UUID uuid, final StringWrapper name) {
super.rename(uuid, name);
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
try (PreparedStatement statement = getConnection().prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) {
@Override public void run() {
try (PreparedStatement statement = getConnection()
.prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) {
statement.setString(1, name.value);
statement.setString(2, uuid.toString());
statement.execute();
PS.debug(C.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\'');
PlotSquared.debug(
C.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\'');
} catch (SQLException e) {
e.printStackTrace();
}

View File

@ -1,732 +0,0 @@
package com.intellectualcrafters.plot.api;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.commands.SubCommand;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
/**
* PlotSquared API.
*
* <p>Useful classes:
* <ul>
* <li>{@link BukkitUtil}</li>
* <li>{@link PlotPlayer}</li>
* <li>{@link Plot}</li>
* <li>{@link com.intellectualcrafters.plot.object.Location}</li>
* <li>{@link PlotArea}</li>
* <li>{@link PS}</li>
* </ul>
* @version 3.3.3
*/
public class PlotAPI {
/**
* Deprecated, does nothing.
* @param plugin not needed
* @deprecated Not needed
*/
@Deprecated
public PlotAPI(JavaPlugin plugin) {}
public PlotAPI(){}
/**
* Get all plots.
*
* @return all plots
*
* @see PS#getPlots()
*/
public Set<Plot> getAllPlots() {
return PS.get().getPlots();
}
/**
* Return all plots for a player.
*
* @param player Player, whose plots to search for
*
* @return all plots that a player owns
*/
public Set<Plot> getPlayerPlots(Player player) {
return PS.get().getPlots(BukkitUtil.getPlayer(player));
}
/**
* Add a plot world.
*
* @param plotArea Plot World Object
* @see PS#addPlotArea(PlotArea)
*/
public void addPlotArea(PlotArea plotArea) {
PS.get().addPlotArea(plotArea);
}
/**
* Returns the PlotSquared configurations file.
* @return main configuration
*
* @see PS#config
*/
public YamlConfiguration getConfig() {
return PS.get().config;
}
/**
* Get the PlotSquared storage file.
* @return storage configuration
*
* @see PS#storage
*/
public YamlConfiguration getStorage() {
return PS.get().storage;
}
/**
* Get the main class for this plugin. Only use this if you really need it.
*
* @return PlotSquared PlotSquared Main Class
*
* @see PS
*/
public PS getMain() {
return PS.get();
}
/**
* ChunkManager class contains several useful methods.
* <ul>
* <li>Chunk deletion</li>
* <li>Moving or copying regions</li>
* <li>Plot swapping</li>
* <li>Entity Tracking</li>
* <li>Region Regeneration</li>
* </ul>
*
* @return ChunkManager
*
* @see ChunkManager
*/
public ChunkManager getChunkManager() {
return ChunkManager.manager;
}
/**
* Get the block/biome set queue
* @return GlobalBlockQueue.IMP
*/
public GlobalBlockQueue getBlockQueue() {
return GlobalBlockQueue.IMP;
}
/**
* UUIDWrapper class has basic methods for getting UUIDS. It's recommended
* to use the UUIDHandler class instead.
*
* @return UUIDWrapper
*
* @see UUIDWrapper
*/
public UUIDWrapper getUUIDWrapper() {
return UUIDHandler.getUUIDWrapper();
}
/**
* Do not use this. Instead use FlagManager.[method] in your code.
* - Flag related stuff
*
* @return FlagManager
*
* @deprecated Use {@link FlagManager} directly
*/
@Deprecated
public FlagManager getFlagManager() {
return new FlagManager();
}
/**
* Do not use this. Instead use MainUtil.[method] in your code.
*
* @return MainUtil
* @deprecated Use {@link MainUtil} directly
*/
@Deprecated
public MainUtil getMainUtil() {
return new MainUtil();
}
/**
* Do not use this. Instead use C.PERMISSION_[method] in your code.
*
* @return Array of strings
*
* @see Permissions
* @deprecated Use {@link C} to list all the permissions
*/
@Deprecated
public String[] getPermissions() {
ArrayList<String> perms = new ArrayList<>();
for (C caption : C.values()) {
if ("static.permissions".equals(caption.getCategory())) {
perms.add(caption.s());
}
}
return perms.toArray(new String[perms.size()]);
}
/**
* SchematicHandler class contains methods related to pasting, reading
* and writing schematics.
*
* @return SchematicHandler
*
* @see SchematicHandler
*/
public SchematicHandler getSchematicHandler() {
return SchematicHandler.manager;
}
/**
* Use C.[caption] instead
*
* @return C
* @deprecated Use {@link C}
*/
@Deprecated
public C[] getCaptions() {
return C.values();
}
/**
* Get the plot manager for a world. Most of these methods can be accessed
* through the MainUtil.
*
* @param world the world to retrieve the manager from
*
* @return PlotManager
*
* @see PlotManager
* @see PS#getPlotManager(Plot)
*/
@SuppressWarnings("deprecation")
@Deprecated
public PlotManager getPlotManager(World world) {
if (world == null) {
return null;
}
return getPlotManager(world.getName());
}
/**
* Get a list of PlotAreas in the world.
* @param world The world to check for plot areas
* @return A set of PlotAreas
*/
public Set<PlotArea> getPlotAreas(World world) {
if (world == null) {
return Collections.emptySet();
}
return PS.get().getPlotAreas(world.getName());
}
/**
* Get the plot manager for a world. Contains useful low level methods for
* plot merging, clearing, and tessellation.
*
* @param world The world
*
* @return PlotManager
*
* @see PS#getPlotManager(Plot)
* @see PlotManager
*/
@Deprecated
public PlotManager getPlotManager(String world) {
Set<PlotArea> areas = PS.get().getPlotAreas(world);
switch (areas.size()) {
case 0:
return null;
case 1:
return areas.iterator().next().manager;
default:
PS.debug("PlotAPI#getPlotManager(org.bukkit.World) is deprecated and doesn't support multi plot area worlds.");
return null;
}
}
/**
* Get the settings for a world (settings bundled in PlotArea class). You
* will need to downcast for the specific settings a Generator has. e.g.
* DefaultPlotWorld class implements PlotArea
*
* @param world The World
*
* @return The {@link PlotArea} for the world or null if not in plotworld
*
* @see #getPlotAreas(World)
* @see PlotArea
*/
@SuppressWarnings("deprecation")
@Deprecated
public PlotArea getWorldSettings(World world) {
if (world == null) {
return null;
}
return getWorldSettings(world.getName());
}
/**
* Get the settings for a world.
*
* @param world the world to retrieve settings from
*
* @return The {@link PlotArea} for the world or null if not in plotworld
*
* @see PS#getPlotArea(String, String)
* @see PlotArea
*/
@Deprecated
public PlotArea getWorldSettings(String world) {
if (world == null) {
return null;
}
Set<PlotArea> areas = PS.get().getPlotAreas(world);
switch (areas.size()) {
case 0:
return null;
case 1:
return areas.iterator().next();
default:
PS.debug("PlotAPI#getWorldSettings(org.bukkit.World) is deprecated and doesn't support multi plot area worlds.");
return null;
}
}
/**
* Send a message to a player.
*
* @param player the recipient of the message
* @param caption the message
*
* @see MainUtil#sendMessage(PlotPlayer, C, String...)
*/
public void sendMessage(Player player, C caption) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption);
}
/**
* Send a message to a player. The message supports color codes.
*
* @param player the recipient of the message
* @param string the message
*
* @see MainUtil#sendMessage(PlotPlayer, String)
*/
public void sendMessage(Player player, String string) {
MainUtil.sendMessage(BukkitUtil.getPlayer(player), string);
}
/**
* Send a message to the console. The message supports color codes.
*
* @param message the message
*
* @see MainUtil#sendConsoleMessage(C, String...)
*/
public void sendConsoleMessage(String message) {
PS.log(message);
}
/**
* Send a message to the console.
*
* @param caption the message
*
* @see #sendConsoleMessage(String)
* @see C
*/
public void sendConsoleMessage(C caption) {
sendConsoleMessage(caption.s());
}
/**
* Register a flag for use in plots.
*
* @param flag the flag being registered
*
*/
public void addFlag(Flag<?> flag) {
Flags.registerFlag(flag);
}
/**
* Get a plot based on the ID.
*
* @param world the world the plot is located in
* @param x The PlotID x coordinate
* @param z The PlotID y coordinate
*
* @return plot, null if ID is wrong
*
* @see PlotArea#getPlot(PlotId)
*/
@SuppressWarnings("deprecation")
@Deprecated
public Plot getPlot(World world, int x, int z) {
if (world == null) {
return null;
}
PlotArea area = getWorldSettings(world);
if (area == null) {
return null;
}
return area.getPlot(new PlotId(x, z));
}
/**
* Get a plot based on the location.
*
* @param location the location to check
*
* @return plot if found, otherwise it creates a temporary plot
*
* @see Plot
*/
public Plot getPlot(Location location) {
if (location == null) {
return null;
}
return BukkitUtil.getLocation(location).getPlot();
}
/**
* Get a plot based on the player location.
*
* @param player the player to check
*
* @return plot if found, otherwise it creates a temporary plot
*
* @see #getPlot(Location)
* @see Plot
*/
public Plot getPlot(Player player) {
return this.getPlot(player.getLocation());
}
/**
* Check whether or not a player has a plot.
*
* @param player Player that you want to check for
* @param world The world to check
* @return true if player has a plot, false if not.
*
* @see #getPlots(World, Player, boolean)
*/
@SuppressWarnings("deprecation")
@Deprecated
public boolean hasPlot(World world, Player player) {
return getPlots(world, player, true).length > 0;
}
/**
* Get all plots for the player.
*
* @param world The world to retrieve plots from
* @param player The player to search for
* @param justOwner should we just search for owner? Or with rights?
* @return An array of plots for the player
*/
@Deprecated
public Plot[] getPlots(World world, Player player, boolean justOwner) {
ArrayList<Plot> pPlots = new ArrayList<>();
UUID uuid = BukkitUtil.getPlayer(player).getUUID();
for (Plot plot : PS.get().getPlots(world.getName())) {
if (justOwner) {
if (plot.hasOwner() && plot.isOwner(uuid)) {
pPlots.add(plot);
}
} else if (plot.isAdded(uuid)) {
pPlots.add(plot);
}
}
return pPlots.toArray(new Plot[pPlots.size()]);
}
/**
* Get all plots for the world.
*
* @param world to get plots of
*
* @return Plot[] - array of plot objects in world
*
* @see PS#getPlots(String)
* @see Plot
*/
@Deprecated
public Plot[] getPlots(World world) {
if (world == null) {
return new Plot[0];
}
Collection<Plot> plots = PS.get().getPlots(world.getName());
return plots.toArray(new Plot[plots.size()]);
}
/**
* Get all plot worlds.
*
* @return World[] - array of plot worlds
*
*/
@SuppressWarnings("deprecation")
@Deprecated
public String[] getPlotWorlds() {
Set<String> plotWorldStrings = PS.get().getPlotWorldStrings();
return plotWorldStrings.toArray(new String[plotWorldStrings.size()]);
}
/**
* Get if plotworld.
*
* @param world The world to check
*
* @return boolean (if plot world or not)
*
* @see PS#hasPlotArea(String)
*/
@Deprecated
public boolean isPlotWorld(World world) {
return PS.get().hasPlotArea(world.getName());
}
/**
* Get plot locations.
*
* @param plot Plot to get the locations for
*
* @return [0] = bottomLc, [1] = topLoc, [2] = home
*
* @deprecated As merged plots may not have a rectangular shape
*
* @see Plot
*/
@SuppressWarnings("deprecation")
@Deprecated
public Location[] getLocations(Plot plot) {
Location bukkitBottom = BukkitUtil.getLocation(plot.getCorners()[0]);
Location bukkitTop = BukkitUtil.getLocation(plot.getCorners()[1]);
Location bukkitHome = BukkitUtil.getLocation(plot.getHome());
return new Location[]{bukkitBottom, bukkitTop, bukkitHome};
}
/**
* Get home location.
*
* @param plot Plot that you want to get the location for
*
* @return plot bottom location
*
* @see Plot
*/
public Location getHomeLocation(Plot plot) {
return BukkitUtil.getLocation(plot.getHome());
}
/**
* Get Bottom Location (min, min, min).
*
* @param plot Plot that you want to get the location for
*
* @return plot bottom location
*
* @deprecated As merged plots may not have a rectangular shape
*
* @see Plot
*/
@SuppressWarnings("deprecation")
@Deprecated
public Location getBottomLocation(Plot plot) {
return BukkitUtil.getLocation(plot.getCorners()[0]);
}
/**
* Get Top Location (max, max, max).
*
* @param plot Plot that you want to get the location for
*
* @return plot top location
*
* @deprecated As merged plots may not have a rectangular shape
*
* @see Plot
*/
@SuppressWarnings("deprecation")
@Deprecated
public Location getTopLocation(Plot plot) {
return BukkitUtil.getLocation(plot.getCorners()[1]);
}
/**
* Check whether or not a player is in a plot.
*
* @param player who we're checking for
*
* @return true if the player is in a plot, false if not-
*
*/
public boolean isInPlot(Player player) {
return getPlot(player) != null;
}
/**
* Register a subcommand.
* @deprecated Command registration is done on object creation
* @param c SubCommand, that we want to register
* @see SubCommand
*/
@Deprecated
public void registerCommand(SubCommand c) {
PS.debug("SubCommands are now registered on creation");
}
/**
* Get the PlotSquared class.
*
* @return PlotSquared Class
*
* @see PS
*/
public PS getPlotSquared() {
return PS.get();
}
/**
* Get the player plot count.
*
* @param world Specify the world we want to select the plots from
* @param player Player, for whom we're getting the plot count
*
* @return the number of plots the player has
*
*/
public int getPlayerPlotCount(World world, Player player) {
if (world == null) {
return 0;
}
return BukkitUtil.getPlayer(player).getPlotCount(world.getName());
}
/**
* Get a collection containing the players plots.
*
* @param world Specify the world we want to select the plots from
* @param player Player, for whom we're getting the plots
*
* @return a set containing the players plots
*
* @see PS#getPlots(String, PlotPlayer)
*
* @see Plot
*/
public Set<Plot> getPlayerPlots(World world, Player player) {
if (world == null) {
return new HashSet<>();
}
return PlotPlayer.wrap(player).getPlots(world.getName());
}
/**
* Get the numbers of plots, which the player is able to build in.
*
* @param player player, for whom we're getting the plots
*
* @return the number of allowed plots
*
*/
public int getAllowedPlots(Player player) {
PlotPlayer plotPlayer = PlotPlayer.wrap(player);
return plotPlayer.getAllowedPlots();
}
/**
* Get the PlotPlayer for a player. The PlotPlayer is usually cached and
* will provide useful functions relating to players.
*
* @see PlotPlayer#wrap(Object)
*
* @param player the player to wrap
* @return a {@code PlotPlayer}
*/
public PlotPlayer wrapPlayer(Player player) {
return PlotPlayer.wrap(player);
}
/**
* Get the PlotPlayer for a UUID.
*
* <p><i>Please note that PlotSquared can be configured to provide
* different UUIDs than bukkit</i>
*
* @see PlotPlayer#wrap(Object)
*
* @param uuid the uuid of the player to wrap
* @return a {@code PlotPlayer}
*/
public PlotPlayer wrapPlayer(UUID uuid) {
return PlotPlayer.wrap(uuid);
}
/**
* Get the PlotPlayer for a username.
*
* @see PlotPlayer#wrap(Object)
*
* @param player the player to wrap
* @return a {@code PlotPlayer}
*/
public PlotPlayer wrapPlayer(String player) {
return PlotPlayer.wrap(player);
}
/**
* Get the PlotPlayer for an offline player.
*
* <p>Note that this will work if the player is offline, however not all
* functionality will work.
*
* @see PlotPlayer#wrap(Object)
*
* @param player the player to wrap
* @return a {@code PlotPlayer}
*/
public PlotPlayer wrapPlayer(OfflinePlayer player) {
return PlotPlayer.wrap(player);
}
}

View File

@ -1,667 +0,0 @@
package com.plotsquared.bukkit;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.plot.IPlotMain;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.ConfigurationNode;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.AbstractTitle;
import com.intellectualcrafters.plot.util.ChatManager;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.ConsoleColors;
import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.QueueProvider;
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector;
import com.plotsquared.bukkit.database.plotme.LikePlotMeConverter;
import com.plotsquared.bukkit.database.plotme.PlotMeConnector_017;
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.plotsquared.bukkit.listeners.ChunkListener;
import com.plotsquared.bukkit.listeners.ForceFieldListener;
import com.plotsquared.bukkit.listeners.PlayerEvents;
import com.plotsquared.bukkit.listeners.PlayerEvents183;
import com.plotsquared.bukkit.listeners.PlayerEvents_1_8;
import com.plotsquared.bukkit.listeners.PlayerEvents_1_9;
import com.plotsquared.bukkit.listeners.PlotPlusListener;
import com.plotsquared.bukkit.listeners.WorldEvents;
import com.plotsquared.bukkit.titles.DefaultTitle_19;
import com.plotsquared.bukkit.util.BukkitChatManager;
import com.plotsquared.bukkit.util.BukkitChunkManager;
import com.plotsquared.bukkit.util.BukkitCommand;
import com.plotsquared.bukkit.util.BukkitEconHandler;
import com.plotsquared.bukkit.util.BukkitEventUtil;
import com.plotsquared.bukkit.util.BukkitHybridUtils;
import com.plotsquared.bukkit.util.BukkitInventoryUtil;
import com.plotsquared.bukkit.util.BukkitPlainChatManager;
import com.plotsquared.bukkit.util.BukkitSchematicHandler;
import com.plotsquared.bukkit.util.BukkitSetupUtils;
import com.plotsquared.bukkit.util.BukkitTaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.Metrics;
import com.plotsquared.bukkit.util.SendChunk;
import com.plotsquared.bukkit.util.SetGenCB;
import com.plotsquared.bukkit.util.block.BukkitLocalQueue;
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_7;
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8;
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8_3;
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_9;
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
import com.plotsquared.bukkit.uuid.FileUUIDHandler;
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
import com.plotsquared.bukkit.uuid.SQLUUIDHandler;
import com.sk89q.worldedit.WorldEdit;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain {
public static WorldEdit worldEdit;
private int[] version;
@Override
public int[] getServerVersion() {
if (this.version == null) {
try {
this.version = new int[3];
String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\.");
this.version[0] = Integer.parseInt(split[0]);
this.version[1] = Integer.parseInt(split[1]);
if (split.length == 3) {
this.version[2] = Integer.parseInt(split[2]);
}
} catch (NumberFormatException e) {
e.printStackTrace();
PS.debug(StringMan.getString(Bukkit.getBukkitVersion()));
PS.debug(StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\.")));
return new int[]{1, 9, 2};
}
}
return this.version;
}
@Override
public void onEnable() {
new PS(this, "Bukkit");
}
@Override
public void onDisable() {
PS.get().disable();
Bukkit.getScheduler().cancelTasks(this);
}
@Override
public void log(String message) {
try {
message = C.color(message);
if (!Settings.Chat.CONSOLE_COLOR) {
message = ChatColor.stripColor(message);
}
this.getServer().getConsoleSender().sendMessage(message);
} catch (Throwable ignored) {
System.out.println(ConsoleColors.fromString(message));
}
}
@Override
public void disable() {
onDisable();
}
@Override
public int[] getPluginVersion() {
String ver = getDescription().getVersion();
if (ver.contains("-")) {
ver = ver.split("-")[0];
}
String[] split = ver.split("\\.");
return new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])};
}
@Override
public void registerCommands() {
BukkitCommand bukkitCommand = new BukkitCommand();
PluginCommand plotCommand = getCommand("plots");
plotCommand.setExecutor(bukkitCommand);
plotCommand.setAliases(Arrays.asList("p", "ps", "plotme", "plot"));
plotCommand.setTabCompleter(bukkitCommand);
}
@Override
public File getDirectory() {
return getDataFolder();
}
@Override
public File getWorldContainer() {
return Bukkit.getWorldContainer();
}
@Override
public TaskManager getTaskManager() {
return new BukkitTaskManager(this);
}
@Override
public void runEntityTask() {
PS.log(C.PREFIX + "KillAllEntities started.");
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
PS.get().foreachPlotArea(new RunnableVal<PlotArea>() {
@Override
public void run(PlotArea plotArea) {
World world = Bukkit.getWorld(plotArea.worldname);
try {
if (world == null) {
return;
}
List<Entity> entities = world.getEntities();
Iterator<Entity> iterator = entities.iterator();
while (iterator.hasNext()) {
Entity entity = iterator.next();
switch (entity.getType()) {
case EGG:
case ENDER_CRYSTAL:
case COMPLEX_PART:
case FISHING_HOOK:
case ENDER_SIGNAL:
case LINGERING_POTION:
case AREA_EFFECT_CLOUD:
case EXPERIENCE_ORB:
case LEASH_HITCH:
case FIREWORK:
case WEATHER:
case LIGHTNING:
case WITHER_SKULL:
case UNKNOWN:
case PLAYER:
// non moving / unmovable
continue;
case THROWN_EXP_BOTTLE:
case SPLASH_POTION:
case SNOWBALL:
case SHULKER_BULLET:
case SPECTRAL_ARROW:
case TIPPED_ARROW:
case ENDER_PEARL:
case ARROW:
// managed elsewhere | projectile
continue;
case ITEM_FRAME:
case PAINTING:
// Not vehicles
continue;
case ARMOR_STAND:
// Tempirarily classify as vehicle
case MINECART:
case MINECART_CHEST:
case MINECART_COMMAND:
case MINECART_FURNACE:
case MINECART_HOPPER:
case MINECART_MOB_SPAWNER:
case MINECART_TNT:
case BOAT: {
if (!Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
continue;
}
com.intellectualcrafters.plot.object.Location location = BukkitUtil.getLocation(entity.getLocation());
Plot plot = location.getPlot();
if (plot == null) {
if (location.isPlotArea()) {
iterator.remove();
entity.remove();
}
continue;
}
List<MetadataValue> meta = entity.getMetadata("plot");
if (meta.isEmpty()) {
continue;
}
Plot origin = (Plot) meta.get(0).value();
if (!plot.equals(origin.getBasePlot(false))) {
iterator.remove();
entity.remove();
}
continue;
}
case SMALL_FIREBALL:
case FIREBALL:
case DRAGON_FIREBALL:
case DROPPED_ITEM:
// dropped item
continue;
case PRIMED_TNT:
case FALLING_BLOCK:
// managed elsewhere
continue;
case BAT:
case BLAZE:
case CAVE_SPIDER:
case CHICKEN:
case COW:
case CREEPER:
case ENDERMAN:
case ENDERMITE:
case ENDER_DRAGON:
case GHAST:
case GIANT:
case GUARDIAN:
case HORSE:
case IRON_GOLEM:
case MAGMA_CUBE:
case MUSHROOM_COW:
case OCELOT:
case PIG:
case PIG_ZOMBIE:
case RABBIT:
case SHEEP:
case SILVERFISH:
case SKELETON:
case SLIME:
case SNOWMAN:
case SPIDER:
case SQUID:
case VILLAGER:
case WITCH:
case WITHER:
case WOLF:
case ZOMBIE:
case SHULKER:
default:
if (!Settings.Enabled_Components.KILL_ROAD_MOBS) {
continue;
}
Location location = entity.getLocation();
if (BukkitUtil.getLocation(location).isPlotRoad()) {
if (entity instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) entity;
if (!livingEntity.isLeashed() || !entity.hasMetadata("keep")) {
Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
iterator.remove();
entity.remove();
}
}
} else {
Entity passenger = entity.getPassenger();
if (!(passenger instanceof Player) && entity.getMetadata("keep").isEmpty()) {
iterator.remove();
entity.remove();
}
}
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
});
}
}, 20);
}
@Override
public final ChunkGenerator getDefaultWorldGenerator(String world, String id) {
HybridGen result = new HybridGen();
if (!PS.get().setupPlotWorld(world, id, result)) {
return null;
}
return (ChunkGenerator) result.specify();
}
@Override
public void registerPlayerEvents() {
PlayerEvents main = new PlayerEvents();
getServer().getPluginManager().registerEvents(main, this);
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
try {
getServer().getPluginManager().registerEvents(new PlayerEvents_1_8(), this);
} catch (Throwable e) {
e.printStackTrace();
}
}
if (PS.get().checkVersion(getServerVersion(), 1, 8, 3)) {
try {
getServer().getPluginManager().registerEvents(new PlayerEvents183(), this);
} catch (Throwable e) {
e.printStackTrace();
}
}
if (PS.get().checkVersion(getServerVersion(), 1, 9, 0)) {
try {
getServer().getPluginManager().registerEvents(new PlayerEvents_1_9(main), this);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
@Override
public void registerInventoryEvents() {
// Part of PlayerEvents - can be moved if necessary
}
@Override
public void registerPlotPlusEvents() {
PlotPlusListener.startRunnable(this);
getServer().getPluginManager().registerEvents(new PlotPlusListener(), this);
}
@Override
public void registerForceFieldEvents() {
getServer().getPluginManager().registerEvents(new ForceFieldListener(), this);
}
@Override
public boolean initWorldEdit() {
if (getServer().getPluginManager().getPlugin("WorldEdit") != null) {
worldEdit = WorldEdit.getInstance();
return true;
}
return false;
}
@Override
public EconHandler getEconomyHandler() {
try {
BukkitEconHandler econ = new BukkitEconHandler();
if (econ.init()) {
return econ;
}
} catch (Throwable ignored) {
PS.debug("No economy detected!");
}
return null;
}
@Override
public QueueProvider initBlockQueue() {
try {
new SendChunk();
MainUtil.canSendChunk = true;
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
if (PS.get().checkVersion(getServerVersion(), 1, 9, 0)) {
return QueueProvider.of(BukkitLocalQueue_1_9.class, BukkitLocalQueue.class);
}
if (PS.get().checkVersion(getServerVersion(), 1, 8, 3)) {
return QueueProvider.of(BukkitLocalQueue_1_8_3.class, BukkitLocalQueue.class);
}
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
return QueueProvider.of(BukkitLocalQueue_1_8.class, BukkitLocalQueue.class);
}
return QueueProvider.of(BukkitLocalQueue_1_7.class, BukkitLocalQueue.class);
}
@Override
public WorldUtil initWorldUtil() {
return new BukkitUtil();
}
@Override
public boolean initPlotMeConverter() {
TaskManager.runTaskLaterAsync(new Runnable() {
@Override
public void run() {
if (new LikePlotMeConverter("PlotMe").run(new ClassicPlotMeConnector())) {
return;
}
if (new LikePlotMeConverter("PlotMe").run(new PlotMeConnector_017())) {
return;
}
}
}, 20);
return Bukkit.getPluginManager().getPlugin("PlotMe") != null;
}
@Override
public GeneratorWrapper<?> getGenerator(String world, String name) {
if (name == null) {
return null;
}
Plugin genPlugin = Bukkit.getPluginManager().getPlugin(name);
if (genPlugin != null && genPlugin.isEnabled()) {
ChunkGenerator gen = genPlugin.getDefaultWorldGenerator(world, "");
if (gen instanceof GeneratorWrapper<?>) {
return (GeneratorWrapper<?>) gen;
}
return new BukkitPlotGenerator(world, gen);
} else {
return new BukkitPlotGenerator(new HybridGen());
}
}
@Override
public HybridUtils initHybridUtils() {
return new BukkitHybridUtils();
}
@Override
public SetupUtils initSetupUtils() {
return new BukkitSetupUtils();
}
@Override
public UUIDHandlerImplementation initUUIDHandler() {
boolean checkVersion = PS.get().checkVersion(getServerVersion(), 1, 7, 6);
UUIDWrapper wrapper;
if (Settings.UUID.OFFLINE) {
if (Settings.UUID.FORCE_LOWERCASE) {
wrapper = new LowerOfflineUUIDWrapper();
} else {
wrapper = new OfflineUUIDWrapper();
}
Settings.UUID.OFFLINE = true;
} else if (checkVersion) {
wrapper = new DefaultUUIDWrapper();
Settings.UUID.OFFLINE = false;
} else {
if (Settings.UUID.FORCE_LOWERCASE) {
wrapper = new LowerOfflineUUIDWrapper();
} else {
wrapper = new OfflineUUIDWrapper();
}
Settings.UUID.OFFLINE = true;
}
if (!checkVersion) {
PS.log(C.PREFIX + " &c[WARN] Titles are disabled - please update your version of Bukkit to support this feature.");
Settings.TITLES = false;
} else {
AbstractTitle.TITLE_CLASS = new DefaultTitle_19();
if (wrapper instanceof DefaultUUIDWrapper || wrapper.getClass() == OfflineUUIDWrapper.class && !Bukkit.getOnlineMode()) {
Settings.UUID.NATIVE_UUID_PROVIDER = true;
}
}
if (Settings.UUID.OFFLINE) {
PS.log(C.PREFIX
+ " &6PlotSquared is using Offline Mode UUIDs either because of user preference, or because you are using an old version of "
+ "Bukkit");
} else {
PS.log(C.PREFIX + " &6PlotSquared is using online UUIDs");
}
if (Settings.UUID.USE_SQLUUIDHANDLER) {
return new SQLUUIDHandler(wrapper);
} else {
return new FileUUIDHandler(wrapper);
}
}
@Override
public ChunkManager initChunkManager() {
return new BukkitChunkManager();
}
@Override
public EventUtil initEventUtil() {
return new BukkitEventUtil();
}
@Override
public void unregister(PlotPlayer player) {
BukkitUtil.removePlayer(player.getName());
}
@Override
public void registerChunkProcessor() {
getServer().getPluginManager().registerEvents(new ChunkListener(), this);
}
@Override
public void registerWorldEvents() {
getServer().getPluginManager().registerEvents(new WorldEvents(), this);
}
@Override
public InventoryUtil initInventoryUtil() {
return new BukkitInventoryUtil();
}
@Override
public String getServerName() {
return Bukkit.getServerName();
}
@Override
public void startMetrics() {
Metrics metrics = new Metrics(this);
metrics.start();
PS.log(C.PREFIX + "&6Metrics enabled.");
}
@Override
public void setGenerator(String worldName) {
World world = BukkitUtil.getWorld(worldName);
if (world == null) {
// create world
ConfigurationSection worldConfig = PS.get().worlds.getConfigurationSection("worlds." + worldName);
String manager = worldConfig.getString("generator.plugin", "PlotSquared");
SetupObject setup = new SetupObject();
setup.plotManager = manager;
setup.setupGenerator = worldConfig.getString("generator.init", manager);
setup.type = worldConfig.getInt("generator.type");
setup.terrain = worldConfig.getInt("generator.terrain");
setup.step = new ConfigurationNode[0];
setup.world = worldName;
SetupUtils.manager.setupWorld(setup);
} else {
try {
if (!PS.get().hasPlotArea(worldName)) {
SetGenCB.setGenerator(BukkitUtil.getWorld(worldName));
}
} catch (Exception ignored) {
PS.log("Failed to reload world: " + world);
Bukkit.getServer().unloadWorld(world, false);
}
}
world = Bukkit.getWorld(worldName);
ChunkGenerator gen = world.getGenerator();
if (gen instanceof BukkitPlotGenerator) {
PS.get().loadWorld(worldName, (BukkitPlotGenerator) gen);
} else if (gen != null) {
PS.get().loadWorld(worldName, new BukkitPlotGenerator(worldName, gen));
} else if (PS.get().worlds.contains("worlds." + worldName)) {
PS.get().loadWorld(worldName, null);
}
}
@Override
public SchematicHandler initSchematicHandler() {
return new BukkitSchematicHandler();
}
@Override
public AbstractTitle initTitleManager() {
// Already initialized in UUID handler
return AbstractTitle.TITLE_CLASS;
}
@Override
public PlotPlayer wrapPlayer(Object player) {
if (player instanceof Player) {
return BukkitUtil.getPlayer((Player) player);
}
if (player instanceof OfflinePlayer) {
return BukkitUtil.getPlayer((OfflinePlayer) player);
}
if (player instanceof String) {
return UUIDHandler.getPlayer((String) player);
}
if (player instanceof UUID) {
return UUIDHandler.getPlayer((UUID) player);
}
return null;
}
@Override
public String getNMSPackage() {
String name = Bukkit.getServer().getClass().getPackage().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
@Override
public ChatManager<?> initChatManager() {
if (Settings.Chat.INTERACTIVE) {
return new BukkitChatManager();
} else {
return new BukkitPlainChatManager();
}
}
@Override
public GeneratorWrapper<?> wrapPlotGenerator(IndependentPlotGenerator generator) {
return new BukkitPlotGenerator(generator);
}
@Override
public List<String> getPluginIds() {
ArrayList<String> names = new ArrayList<>();
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
names.add(plugin.getName() + ';' + plugin.getDescription().getVersion() + ':' + plugin.isEnabled());
}
return names;
}
}

View File

@ -1,111 +0,0 @@
package com.plotsquared.bukkit.chat;
import org.apache.commons.lang.Validate;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
/**
* Represents a wrapper around an array class of an arbitrary reference type,
* which properly implements "value" hash code and equality functions.
* <p>
* This class is intended for use as a key to a map.
* </p>
*
* @param <E> The type of elements in the array.
* @author Glen Husman
* @see Arrays
*/
public final class ArrayWrapper<E> {
/**
* Creates an array wrapper with some elements.
*
* @param elements The elements of the array.
*/
public ArrayWrapper(E... elements) {
setArray(elements);
}
private E[] _array;
/**
* Retrieves a reference to the wrapped array instance.
*
* @return The array wrapped by this instance.
*/
public E[] getArray() {
return _array;
}
/**
* Set this wrapper to wrap a new array instance.
*
* @param array The new wrapped array.
*/
public void setArray(E[] array) {
Validate.notNull(array, "The array must not be null.");
_array = array;
}
/**
* Determines if this object has a value equivalent to another object.
*
* @see Arrays#equals(Object[], Object[])
*/
@SuppressWarnings("rawtypes")
@Override
public boolean equals(Object other) {
if (!(other instanceof ArrayWrapper)) {
return false;
}
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
}
/**
* Gets the hash code represented by this objects value.
*
* @return This object's hash code.
* @see Arrays#hashCode(Object[])
*/
@Override
public int hashCode() {
return Arrays.hashCode(_array);
}
/**
* Converts an iterable element collection to an array of elements.
* The iteration order of the specified object will be used as the array element order.
*
* @param list The iterable of objects which will be converted to an array.
* @param c The type of the elements of the array.
* @return An array of elements in the specified iterable.
*/
@SuppressWarnings("unchecked")
public static <T> T[] toArray(Iterable<? extends T> list, Class<T> c) {
int size = -1;
if (list instanceof Collection<?>) {
@SuppressWarnings("rawtypes")
Collection coll = (Collection) list;
size = coll.size();
}
if (size < 0) {
size = 0;
// Ugly hack: Count it ourselves
for (@SuppressWarnings("unused") T element : list) {
size++;
}
}
T[] result = (T[]) Array.newInstance(c, size);
int i = 0;
for (T element : list) { // Assumes iteration order is consistent
result[i++] = element; // Assign array element at index THEN increment counter
}
return result;
}
}

View File

@ -1,887 +0,0 @@
package com.plotsquared.bukkit.chat;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.Achievement;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.Statistic.Type;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import static com.plotsquared.bukkit.chat.TextualComponent.rawText;
/**
* Represents a formattable message. Such messages can use elements such as colors, formatting codes, hover and click data, and other features provided by the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Tellraw#Raw_JSON_Text">JSON message formatter</a>.
* This class allows plugins to emulate the functionality of the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Commands#tellraw">tellraw command</a>.
* <p>
* This class follows the builder pattern, allowing for method chaining.
* It is set up such that invocations of property-setting methods will affect the current editing component,
* and a call to {@link #then()} or {@link #then(String)} will append a new editing component to the end of the message,
* optionally initializing it with text. Further property-setting method calls will affect that editing component.
* </p>
*/
public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<MessagePart>, ConfigurationSerializable {
static {
ConfigurationSerialization.registerClass(FancyMessage.class);
}
private List<MessagePart> messageParts;
private String jsonString;
private boolean dirty;
private static Constructor<?> nmsPacketPlayOutChatConstructor;
@Override
public FancyMessage clone() throws CloneNotSupportedException {
FancyMessage instance = (FancyMessage) super.clone();
instance.messageParts = new ArrayList<MessagePart>(messageParts.size());
for (int i = 0; i < messageParts.size(); i++) {
instance.messageParts.add(i, messageParts.get(i).clone());
}
instance.dirty = false;
instance.jsonString = null;
return instance;
}
/**
* Creates a JSON message with text.
*
* @param firstPartText The existing text in the message.
*/
public FancyMessage(final String firstPartText) {
this(rawText(firstPartText));
}
public FancyMessage(final com.plotsquared.bukkit.chat.TextualComponent firstPartText) {
messageParts = new ArrayList<MessagePart>();
messageParts.add(new MessagePart(firstPartText));
jsonString = null;
dirty = false;
if (nmsPacketPlayOutChatConstructor == null) {
try {
nmsPacketPlayOutChatConstructor = com.plotsquared.bukkit.chat.Reflection.getNMSClass("PacketPlayOutChat").getDeclaredConstructor(com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent"));
nmsPacketPlayOutChatConstructor.setAccessible(true);
} catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not find Minecraft method or constructor.", e);
} catch (SecurityException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access constructor.", e);
}
}
}
/**
* Creates a JSON message without text.
*/
public FancyMessage() {
this((com.plotsquared.bukkit.chat.TextualComponent) null);
}
/**
* Sets the text of the current editing component to a value.
*
* @param text The new text of the current editing component.
* @return This builder instance.
*/
public FancyMessage text(String text) {
MessagePart latest = latest();
latest.text = rawText(text);
dirty = true;
return this;
}
/**
* Sets the text of the current editing component to a value.
*
* @param text The new text of the current editing component.
* @return This builder instance.
*/
public FancyMessage text(com.plotsquared.bukkit.chat.TextualComponent text) {
MessagePart latest = latest();
latest.text = text;
dirty = true;
return this;
}
/**
* Sets the color of the current editing component to a value.
*
* @param color The new color of the current editing component.
* @return This builder instance.
* @throws IllegalArgumentException If the specified {@code ChatColor} enumeration value is not a color (but a format value).
*/
public FancyMessage color(final ChatColor color) {
if (!color.isColor()) {
throw new IllegalArgumentException(color.name() + " is not a color");
}
latest().color = color;
dirty = true;
return this;
}
/**
* Sets the stylization of the current editing component.
*
* @param styles The array of styles to apply to the editing component.
* @return This builder instance.
* @throws IllegalArgumentException If any of the enumeration values in the array do not represent formatters.
*/
public FancyMessage style(ChatColor... styles) {
for (final ChatColor style : styles) {
if (!style.isFormat()) {
throw new IllegalArgumentException(style.name() + " is not a style");
}
}
latest().styles.addAll(Arrays.asList(styles));
dirty = true;
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to open a file on the client side filesystem when the currently edited part of the {@code FancyMessage} is clicked.
*
* @param path The path of the file on the client filesystem.
* @return This builder instance.
*/
public FancyMessage file(final String path) {
onClick("open_file", path);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to open a webpage in the client's web browser when the currently edited part of the {@code FancyMessage} is clicked.
*
* @param url The URL of the page to open when the link is clicked.
* @return This builder instance.
*/
public FancyMessage link(final String url) {
onClick("open_url", url);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to replace the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is clicked.
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
*
* @param command The text to display in the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage suggest(final String command) {
onClick("suggest_command", command);
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to append the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is SHIFT-CLICKED.
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
*
* @param command The text to append to the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage insert(final String command) {
latest().insertionData = command;
dirty = true;
return this;
}
/**
* Set the behavior of the current editing component to instruct the client to send the specified string to the server as a chat message when the currently edited part of the {@code FancyMessage} is clicked.
* The client <b>will</b> immediately send the command to the server to be executed when the editing component is clicked.
*
* @param command The text to display in the chat bar of the client.
* @return This builder instance.
*/
public FancyMessage command(final String command) {
onClick("run_command", command);
return this;
}
/**
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param name The name of the achievement to display, excluding the "achievement." prefix.
* @return This builder instance.
*/
public FancyMessage achievementTooltip(final String name) {
onHover("show_achievement", new JsonString("achievement." + name));
return this;
}
/**
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The achievement to display.
* @return This builder instance.
*/
public FancyMessage achievementTooltip(final Achievement which) {
try {
Object achievement = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class).invoke(null, which);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Achievement"), "name").get(achievement));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a parameterless statistic when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied.
*/
public FancyMessage statisticTooltip(final Statistic which) {
Type type = which.getType();
if (type != Type.UNTYPED) {
throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic", Statistic.class).invoke(null, which);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a statistic parameter with a material when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @param item The sole material parameter to the statistic.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
*/
public FancyMessage statisticTooltip(final Statistic which, Material item) {
Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if ((type == Type.BLOCK && item.isBlock()) || type == Type.ENTITY) {
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getMaterialStatistic", Statistic.class, Material.class).invoke(null, which, item);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about a statistic parameter with an entity type when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param which The statistic to display.
* @param entity The sole entity type parameter to the statistic.
* @return This builder instance.
* @throws IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
*/
public FancyMessage statisticTooltip(final Statistic which, EntityType entity) {
Type type = which.getType();
if (type == Type.UNTYPED) {
throw new IllegalArgumentException("That statistic needs no additional parameter!");
}
if (type != Type.ENTITY) {
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
}
try {
Object statistic = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic", Statistic.class, EntityType.class).invoke(null, which, entity);
return achievementTooltip((String) com.plotsquared.bukkit.chat.Reflection.getField(com.plotsquared.bukkit.chat.Reflection.getNMSClass("Statistic"), "name").get(statistic));
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
return this;
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
return this;
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
return this;
}
}
/**
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param itemJSON A string representing the JSON-serialized NBT data tag of an {@link ItemStack}.
* @return This builder instance.
*/
public FancyMessage itemTooltip(final String itemJSON) {
onHover("show_item", new JsonString(itemJSON)); // Seems a bit hacky, considering we have a JSON object as a parameter
return this;
}
/**
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param itemStack The stack for which to display information.
* @return This builder instance.
*/
public FancyMessage itemTooltip(final ItemStack itemStack) {
try {
Object nmsItem = com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class).invoke(null, itemStack);
return itemTooltip(com.plotsquared.bukkit.chat.Reflection.getMethod(com.plotsquared.bukkit.chat.Reflection.getNMSClass("ItemStack"), "save", com.plotsquared.bukkit.chat.Reflection.getNMSClass("NBTTagCompound")).invoke(nmsItem, com.plotsquared.bukkit.chat.Reflection.getNMSClass("NBTTagCompound").newInstance()).toString());
} catch (Exception e) {
e.printStackTrace();
return this;
}
}
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param text The text, which supports newlines, which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage tooltip(final String text) {
onHover("show_text", new JsonString(text));
return this;
}
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
* @return This builder instance.
*/
public FancyMessage tooltip(final Iterable<String> lines) {
tooltip(com.plotsquared.bukkit.chat.ArrayWrapper.toArray(lines, String.class));
return this;
}
/**
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage tooltip(final String... lines) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
builder.append(lines[i]);
if (i != lines.length - 1) {
builder.append('\n');
}
}
tooltip(builder.toString());
return this;
}
/**
* Set the behavior of the current editing component to display formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param text The formatted text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(FancyMessage text) {
for (MessagePart component : text.messageParts) {
if (component.clickActionData != null && component.clickActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have click data.");
} else if (component.hoverActionData != null && component.hoverActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
}
}
onHover("show_text", text);
return this;
}
/**
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of formatted text which will be displayed to the client upon hovering.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(FancyMessage... lines) {
if (lines.length < 1) {
onHover(null, null); // Clear tooltip
return this;
}
FancyMessage result = new FancyMessage();
result.messageParts.clear(); // Remove the one existing text component that exists by default, which destabilizes the object
for (int i = 0; i < lines.length; i++) {
try {
for (MessagePart component : lines[i]) {
if (component.clickActionData != null && component.clickActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have click data.");
} else if (component.hoverActionData != null && component.hoverActionName != null) {
throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
}
if (component.hasText()) {
result.messageParts.add(component.clone());
}
}
if (i != lines.length - 1) {
result.messageParts.add(new MessagePart(rawText("\n")));
}
} catch (CloneNotSupportedException e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to clone object", e);
return this;
}
}
return formattedTooltip(result.messageParts.isEmpty() ? null : result); // Throws NPE if size is 0, intended
}
/**
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
*
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
* @return This builder instance.
*/
public FancyMessage formattedTooltip(final Iterable<FancyMessage> lines) {
return formattedTooltip(com.plotsquared.bukkit.chat.ArrayWrapper.toArray(lines, FancyMessage.class));
}
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final String... replacements) {
for (String str : replacements) {
latest().translationReplacements.add(new JsonString(str));
}
dirty = true;
return this;
}
/*
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/ /* ------------
public FancyMessage translationReplacements(final Iterable<? extends CharSequence> replacements){
for(CharSequence str : replacements){
latest().translationReplacements.add(new JsonString(str));
}
return this;
}
*/
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final FancyMessage... replacements) {
for (FancyMessage str : replacements) {
latest().translationReplacements.add(str);
}
dirty = true;
return this;
}
/**
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
*
* @param replacements The replacements, in order, that will be used in the language-specific message.
* @return This builder instance.
*/
public FancyMessage translationReplacements(final Iterable<FancyMessage> replacements) {
return translationReplacements(com.plotsquared.bukkit.chat.ArrayWrapper.toArray(replacements, FancyMessage.class));
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @param text The text which will populate the new message component.
* @return This builder instance.
*/
public FancyMessage then(final String text) {
return then(rawText(text));
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @param text The text which will populate the new message component.
* @return This builder instance.
*/
public FancyMessage then(final com.plotsquared.bukkit.chat.TextualComponent text) {
if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text");
}
messageParts.add(new MessagePart(text));
dirty = true;
return this;
}
/**
* Terminate construction of the current editing component, and begin construction of a new message component.
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
*
* @return This builder instance.
*/
public FancyMessage then() {
if (!latest().hasText()) {
throw new IllegalStateException("previous message part has no text");
}
messageParts.add(new MessagePart());
dirty = true;
return this;
}
@Override
public void writeJson(JsonWriter writer) throws IOException {
if (messageParts.size() == 1) {
latest().writeJson(writer);
} else {
writer.beginObject().name("text").value("").name("extra").beginArray();
for (final MessagePart part : this) {
part.writeJson(writer);
}
writer.endArray().endObject();
}
}
/**
* Serialize this fancy message, converting it into syntactically-valid JSON using a {@link JsonWriter}.
* This JSON should be compatible with vanilla formatter commands such as {@code /tellraw}.
*
* @return The JSON string representing this object.
*/
public String toJSONString() {
if (!dirty && jsonString != null) {
return jsonString;
}
StringWriter string = new StringWriter();
JsonWriter json = new JsonWriter(string);
try {
writeJson(json);
json.close();
} catch (IOException e) {
throw new RuntimeException("invalid message");
}
jsonString = string.toString();
dirty = false;
return jsonString;
}
/**
* Sends this message to a player. The player will receive the fully-fledged formatted display of this message.
*
* @param player The player who will receive the message.
*/
public void send(Player player) {
send(player, toJSONString());
}
private void send(CommandSender sender, String jsonString) {
if (!(sender instanceof Player)) {
sender.sendMessage(toOldMessageFormat());
return;
}
Player player = (Player) sender;
try {
Object handle = com.plotsquared.bukkit.chat.Reflection.getHandle(player);
Object connection = com.plotsquared.bukkit.chat.Reflection.getField(handle.getClass(), "playerConnection").get(handle);
com.plotsquared.bukkit.chat.Reflection.getMethod(connection.getClass(), "sendPacket", com.plotsquared.bukkit.chat.Reflection.getNMSClass("Packet")).invoke(connection, createChatPacket(jsonString));
} catch (IllegalArgumentException e) {
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
} catch (IllegalAccessException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
} catch (InstantiationException e) {
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
} catch (InvocationTargetException e) {
Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e);
} catch (NoSuchMethodException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
} catch (ClassNotFoundException e) {
Bukkit.getLogger().log(Level.WARNING, "Could not find class.", e);
}
}
// The ChatSerializer's instance of Gson
private static Object nmsChatSerializerGsonInstance;
private static Method fromJsonMethod;
private Object createChatPacket(String json) throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
if (nmsChatSerializerGsonInstance == null) {
// Find the field and its value, completely bypassing obfuscation
Class<?> chatSerializerClazz;
// Get the three parts of the version string (major version is currently unused)
// vX_Y_RZ
// X = major
// Y = minor
// Z = revision
final String version = com.plotsquared.bukkit.chat.Reflection.getVersion();
String[] split = version.substring(1, version.length() - 1).split("_"); // Remove trailing dot
//int majorVersion = Integer.parseInt(split[0]);
int minorVersion = Integer.parseInt(split[1]);
int revisionVersion = Integer.parseInt(split[2].substring(1)); // Substring to ignore R
if (minorVersion < 8 || (minorVersion == 8 && revisionVersion == 1)) {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("ChatSerializer");
} else {
chatSerializerClazz = com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
}
if (chatSerializerClazz == null) {
throw new ClassNotFoundException("Can't find the ChatSerializer class");
}
for (Field declaredField : chatSerializerClazz.getDeclaredFields()) {
if (Modifier.isFinal(declaredField.getModifiers()) && Modifier.isStatic(declaredField.getModifiers()) && declaredField.getType().getName().endsWith("Gson")) {
// We've found our field
declaredField.setAccessible(true);
nmsChatSerializerGsonInstance = declaredField.get(null);
fromJsonMethod = nmsChatSerializerGsonInstance.getClass().getMethod("fromJson", String.class, Class.class);
break;
}
}
}
// Since the method is so simple, and all the obfuscated methods have the same name, it's easier to reimplement 'IChatBaseComponent a(String)' than to reflectively call it
// Of course, the implementation may change, but fuzzy matches might break with signature changes
Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json, com.plotsquared.bukkit.chat.Reflection.getNMSClass("IChatBaseComponent"));
return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
}
/**
* Sends this message to a command sender.
* If the sender is a player, they will receive the fully-fledged formatted display of this message.
* Otherwise, they will receive a version of this message with less formatting.
*
* @param sender The command sender who will receive the message.
* @see #toOldMessageFormat()
*/
public void send(CommandSender sender) {
send(sender, toJSONString());
}
/**
* Sends this message to multiple command senders.
*
* @param senders The command senders who will receive the message.
* @see #send(CommandSender)
*/
public void send(final Iterable<? extends CommandSender> senders) {
String string = toJSONString();
for (final CommandSender sender : senders) {
send(sender, string);
}
}
/**
* Convert this message to a human-readable string with limited formatting.
* This method is used to send this message to clients without JSON formatting support.
* <p>
* Serialization of this message by using this message will include (in this order for each message part):
* <ol>
* <li>The color of each message part.</li>
* <li>The applicable stylizations for each message part.</li>
* <li>The core text of the message part.</li>
* </ol>
* The primary omissions are tooltips and clickable actions. Consequently, this method should be used only as a last resort.
* </p>
* <p>
* Color and formatting can be removed from the returned string by using {@link ChatColor#stripColor(String)}.</p>
*
* @return A human-readable string representing limited formatting in addition to the core text of this message.
*/
public String toOldMessageFormat() {
StringBuilder result = new StringBuilder();
for (MessagePart part : this) {
result.append(part.color == null ? "" : part.color);
for (ChatColor formatSpecifier : part.styles) {
result.append(formatSpecifier);
}
result.append(part.text);
}
return result.toString();
}
private MessagePart latest() {
return messageParts.get(messageParts.size() - 1);
}
private void onClick(final String name, final String data) {
final MessagePart latest = latest();
latest.clickActionName = name;
latest.clickActionData = data;
dirty = true;
}
private void onHover(final String name, final JsonRepresentedObject data) {
final MessagePart latest = latest();
latest.hoverActionName = name;
latest.hoverActionData = data;
dirty = true;
}
// Doc copied from interface
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("messageParts", messageParts);
// map.put("JSON", toJSONString());
return map;
}
/**
* Deserializes a JSON-represented message from a mapping of key-value pairs.
* This is called by the Bukkit serialization API.
* It is not intended for direct public API consumption.
*
* @param serialized The key-value mapping which represents a fancy message.
*/
@SuppressWarnings("unchecked")
public static FancyMessage deserialize(Map<String, Object> serialized) {
FancyMessage msg = new FancyMessage();
msg.messageParts = (List<MessagePart>) serialized.get("messageParts");
msg.jsonString = serialized.containsKey("JSON") ? serialized.get("JSON").toString() : null;
msg.dirty = !serialized.containsKey("JSON");
return msg;
}
/**
* <b>Internally called method. Not for API consumption.</b>
*/
public Iterator<MessagePart> iterator() {
return messageParts.iterator();
}
private static JsonParser _stringParser = new JsonParser();
/**
* Deserializes a fancy message from its JSON representation. This JSON representation is of the format of
* that returned by {@link #toJSONString()}, and is compatible with vanilla inputs.
*
* @param json The JSON string which represents a fancy message.
* @return A {@code FancyMessage} representing the parameterized JSON message.
*/
public static FancyMessage deserialize(String json) {
JsonObject serialized = _stringParser.parse(json).getAsJsonObject();
JsonArray extra = serialized.getAsJsonArray("extra"); // Get the extra component
FancyMessage returnVal = new FancyMessage();
returnVal.messageParts.clear();
for (JsonElement mPrt : extra) {
MessagePart component = new MessagePart();
JsonObject messagePart = mPrt.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
// Deserialize text
if (com.plotsquared.bukkit.chat.TextualComponent.isTextKey(entry.getKey())) {
// The map mimics the YAML serialization, which has a "key" field and one or more "value" fields
Map<String, Object> serializedMapForm = new HashMap<String, Object>(); // Must be object due to Bukkit serializer API compliance
serializedMapForm.put("key", entry.getKey());
if (entry.getValue().isJsonPrimitive()) {
// Assume string
serializedMapForm.put("value", entry.getValue().getAsString());
} else {
// Composite object, but we assume each element is a string
for (Map.Entry<String, JsonElement> compositeNestedElement : entry.getValue().getAsJsonObject().entrySet()) {
serializedMapForm.put("value." + compositeNestedElement.getKey(), compositeNestedElement.getValue().getAsString());
}
}
component.text = com.plotsquared.bukkit.chat.TextualComponent.deserialize(serializedMapForm);
} else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
if (entry.getValue().getAsBoolean()) {
component.styles.add(MessagePart.stylesToNames.inverse().get(entry.getKey()));
}
} else if (entry.getKey().equals("color")) {
component.color = ChatColor.valueOf(entry.getValue().getAsString().toUpperCase());
} else if (entry.getKey().equals("clickEvent")) {
JsonObject object = entry.getValue().getAsJsonObject();
component.clickActionName = object.get("action").getAsString();
component.clickActionData = object.get("value").getAsString();
} else if (entry.getKey().equals("hoverEvent")) {
JsonObject object = entry.getValue().getAsJsonObject();
component.hoverActionName = object.get("action").getAsString();
if (object.get("value").isJsonPrimitive()) {
// Assume string
component.hoverActionData = new JsonString(object.get("value").getAsString());
} else {
// Assume composite type
// The only composite type we currently store is another FancyMessage
// Therefore, recursion time!
component.hoverActionData = deserialize(object.get("value").toString() /* This should properly serialize the JSON object as a JSON string */);
}
} else if (entry.getKey().equals("insertion")) {
component.insertionData = entry.getValue().getAsString();
} else if (entry.getKey().equals("with")) {
for (JsonElement object : entry.getValue().getAsJsonArray()) {
if (object.isJsonPrimitive()) {
component.translationReplacements.add(new JsonString(object.getAsString()));
} else {
// Only composite type stored in this array is - again - FancyMessages
// Recurse within this function to parse this as a translation replacement
component.translationReplacements.add(deserialize(object.toString()));
}
}
}
}
returnVal.messageParts.add(component);
}
return returnVal;
}
}

View File

@ -1,19 +0,0 @@
package com.plotsquared.bukkit.chat;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
/**
* Represents an object that can be serialized to a JSON writer instance.
*/
interface JsonRepresentedObject {
/**
* Writes the JSON representation of this object to the specified writer.
* @param writer The JSON writer which will receive the object.
* @throws IOException If an error occurs writing to the stream.
*/
public void writeJson(JsonWriter writer) throws IOException;
}

View File

@ -1,47 +0,0 @@
package com.plotsquared.bukkit.chat;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.stream.JsonWriter;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
/**
* Represents a JSON string value.
* Writes by this object will not write name values nor begin/end objects in the JSON stream.
* All writes merely write the represented string value.
*/
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
private String _value;
public JsonString(CharSequence value) {
_value = value == null ? null : value.toString();
}
@Override
public void writeJson(JsonWriter writer) throws IOException {
writer.value(getValue());
}
public String getValue() {
return _value;
}
public Map<String, Object> serialize() {
HashMap<String, Object> theSingleValue = new HashMap<String, Object>();
theSingleValue.put("stringValue", _value);
return theSingleValue;
}
public static JsonString deserialize(Map<String, Object> map) {
return new JsonString(map.get("stringValue").toString());
}
@Override
public String toString() {
return _value;
}
}

View File

@ -1,155 +0,0 @@
package com.plotsquared.bukkit.chat;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.gson.stream.JsonWriter;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
/**
* Internal class: Represents a component of a JSON-serializable {@link FancyMessage}.
*/
final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<ChatColor>();
String clickActionName = null, clickActionData = null, hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<JsonRepresentedObject>();
MessagePart(final TextualComponent text) {
this.text = text;
}
MessagePart() {
this.text = null;
}
boolean hasText() {
return text != null;
}
@Override
@SuppressWarnings("unchecked")
public MessagePart clone() throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
}
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj;
}
static final BiMap<ChatColor, String> stylesToNames;
static {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) {
continue;
}
String styleName;
switch (style) {
case MAGIC:
styleName = "obfuscated";
break;
case UNDERLINE:
styleName = "underlined";
break;
default:
styleName = style.name().toLowerCase();
break;
}
builder.put(style, styleName);
}
stylesToNames = builder.build();
}
public void writeJson(JsonWriter json) {
try {
json.beginObject();
text.writeJson(json);
json.name("color").value(color.name().toLowerCase());
for (final ChatColor style : styles) {
json.name(stylesToNames.get(style)).value(true);
}
if (clickActionName != null && clickActionData != null) {
json.name("clickEvent")
.beginObject()
.name("action").value(clickActionName)
.name("value").value(clickActionData)
.endObject();
}
if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent")
.beginObject()
.name("action").value(hoverActionName)
.name("value");
hoverActionData.writeJson(json);
json.endObject();
}
if (insertionData != null) {
json.name("insertion").value(insertionData);
}
if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e);
}
}
public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("text", text);
map.put("styles", styles);
map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData);
map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements);
return map;
}
@SuppressWarnings("unchecked")
public static MessagePart deserialize(Map<String, Object> serialized) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
part.color = ChatColor.getByChar(serialized.get("color").toString());
part.hoverActionName = (String) serialized.get("hoverActionName");
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
part.clickActionName = (String) serialized.get("clickActionName");
part.clickActionData = (String) serialized.get("clickActionData");
part.insertionData = (String) serialized.get("insertion");
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
return part;
}
static {
ConfigurationSerialization.registerClass(MessagePart.class);
}
}

View File

@ -1,218 +0,0 @@
package com.plotsquared.bukkit.chat;
import org.bukkit.Bukkit;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* A class containing static utility methods and caches which are intended as reflective conveniences.
* Unless otherwise noted, upon failure methods will return {@code null}.
*/
public final class Reflection {
private static String _versionString;
private Reflection() { }
/**
* Gets the version string from the package name of the CraftBukkit server implementation.
* This is needed to bypass the JAR package name changing on each update.
*
* @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
*/
public synchronized static String getVersion() {
if (_versionString == null) {
if (Bukkit.getServer() == null) {
// The server hasn't started, static initializer call?
return null;
}
String name = Bukkit.getServer().getClass().getPackage().getName();
_versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
}
return _versionString;
}
/**
* Stores loaded classes from the {@code net.minecraft.server} package.
*/
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<String, Class<?>>();
/**
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
*/
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<String, Class<?>>();
/**
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
*
* @param className The name of the class, excluding the package, within NMS.
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
*/
public synchronized static Class<?> getNMSClass(String className) {
if (_loadedNMSClasses.containsKey(className)) {
return _loadedNMSClasses.get(className);
}
String fullName = "net.minecraft.server." + getVersion() + className;
Class<?> clazz = null;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
e.printStackTrace();
_loadedNMSClasses.put(className, null);
return null;
}
_loadedNMSClasses.put(className, clazz);
return clazz;
}
/**
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
*
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory.CraftItemStack}.
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
*/
public synchronized static Class<?> getOBCClass(String className) {
if (_loadedOBCClasses.containsKey(className)) {
return _loadedOBCClasses.get(className);
}
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
Class<?> clazz = null;
try {
clazz = Class.forName(fullName);
} catch (Exception e) {
e.printStackTrace();
_loadedOBCClasses.put(className, null);
return null;
}
_loadedOBCClasses.put(className, clazz);
return clazz;
}
/**
* Attempts to get the NMS handle of a CraftBukkit object.
* <p>
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the runtime type of the specified object.
* </p>
*
* @param obj The object for which to retrieve an NMS handle.
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
*/
public synchronized static Object getHandle(Object obj) {
try {
return getMethod(obj.getClass(), "getHandle").invoke(obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<Class<?>, Map<String, Field>>();
/**
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
* returned will be an instance or static field.
* <p>
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
* no field will be reflectively looked up twice.
* </p>
* <p>
* If a field is deemed suitable for return, {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
* </p>
*
* @param clazz The class which contains the field to retrieve.
* @param name The declared name of the field in the class.
* @return A field object with the specified name declared by the specified class.
* @see Class#getDeclaredField(String)
*/
public synchronized static Field getField(Class<?> clazz, String name) {
Map<String, Field> loaded;
if (!_loadedFields.containsKey(clazz)) {
loaded = new HashMap<String, Field>();
_loadedFields.put(clazz, loaded);
} else {
loaded = _loadedFields.get(clazz);
}
if (loaded.containsKey(name)) {
// If the field is loaded (or cached as not existing), return the relevant value, which might be null
return loaded.get(name);
}
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
loaded.put(name, field);
return field;
} catch (Exception e) {
// Error loading
e.printStackTrace();
// Cache field as not existing
loaded.put(name, null);
return null;
}
}
/**
* Contains loaded methods in a cache.
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
*/
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>>();
/**
* Retrieves a {@link Method} instance declared by the specified class with the specified name and argument types.
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
* returned will be an instance or static field.
* <p>
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that
* no method will be reflectively looked up twice.
* </p>
* <p>
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
* </p>
* <p>
* This method does <em>not</em> search superclasses of the specified type for methods with the specified signature.
* Callers wishing this behavior should use {@link Class#getDeclaredMethod(String, Class...)}.
*
* @param clazz The class which contains the method to retrieve.
* @param name The declared name of the method in the class.
* @param args The formal argument types of the method.
* @return A method object with the specified name declared by the specified class.
*/
public synchronized static Method getMethod(Class<?> clazz, String name, Class<?>... args) {
if (!_loadedMethods.containsKey(clazz)) {
_loadedMethods.put(clazz, new HashMap<String, Map<ArrayWrapper<Class<?>>, Method>>());
}
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz);
if (!loadedMethodNames.containsKey(name)) {
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>());
}
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<Class<?>>(args);
if (loadedSignatures.containsKey(wrappedArg)) {
return loadedSignatures.get(wrappedArg);
}
for (Method m : clazz.getMethods()) {
if (m.getName().equals(name) && Arrays.equals(args, m.getParameterTypes())) {
m.setAccessible(true);
loadedSignatures.put(wrappedArg, m);
return m;
}
}
loadedSignatures.put(wrappedArg, null);
return null;
}
}

View File

@ -1,297 +0,0 @@
package com.plotsquared.bukkit.chat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.gson.stream.JsonWriter;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a textual component of a message part.
* This can be used to not only represent string literals in a JSON message,
* but also to represent localized strings and other text values.
* <p>Different instances of this class can be created with static constructor methods.</p>
*/
public abstract class TextualComponent implements Cloneable {
static {
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
}
@Override
public String toString() {
return getReadableString();
}
/**
* @return The JSON key used to represent text components of this type.
*/
public abstract String getKey();
/**
* @return A readable String
*/
public abstract String getReadableString();
/**
* Clones a textual component instance.
* The returned object should not reference this textual component instance, but should maintain the same key and value.
*/
@Override
public abstract TextualComponent clone() throws CloneNotSupportedException;
/**
* Writes the text data represented by this textual component to the specified JSON writer object.
* A new object within the writer is not started.
*
* @param writer The object to which to write the JSON data.
* @throws IOException If an error occurs while writing to the stream.
*/
public abstract void writeJson(JsonWriter writer) throws IOException;
static TextualComponent deserialize(Map<String, Object> map) {
if (map.containsKey("key") && map.size() == 2 && map.containsKey("value")) {
// Arbitrary text component
return ArbitraryTextTypeComponent.deserialize(map);
} else if (map.size() >= 2 && map.containsKey("key") && !map.containsKey("value") /* It contains keys that START WITH value */) {
// Complex JSON object
return ComplexTextTypeComponent.deserialize(map);
}
return null;
}
static boolean isTextKey(String key) {
return key.equals("translate") || key.equals("text") || key.equals("score") || key.equals("selector");
}
static boolean isTranslatableText(TextualComponent component) {
return component instanceof ComplexTextTypeComponent && ((ComplexTextTypeComponent) component).getKey().equals("translate");
}
/**
* Internal class used to represent all types of text components.
* Exception validating done is on keys and values.
*/
private static final class ArbitraryTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
public ArbitraryTextTypeComponent(String key, String value) {
setKey(key);
setValue(value);
}
@Override
public String getKey() {
return _key;
}
public void setKey(String key) {
Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
_key = key;
}
public String getValue() {
return _value;
}
public void setValue(String value) {
Preconditions.checkArgument(value != null, "The value must be specified.");
_value = value;
}
private String _key;
private String _value;
@Override
public TextualComponent clone() throws CloneNotSupportedException {
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
return new ArbitraryTextTypeComponent(getKey(), getValue());
}
@Override
public void writeJson(JsonWriter writer) throws IOException {
writer.name(getKey()).value(getValue());
}
@SuppressWarnings("serial")
public Map<String, Object> serialize() {
return new HashMap<String, Object>() {{
put("key", getKey());
put("value", getValue());
}};
}
public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) {
return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString());
}
@Override
public String getReadableString() {
return getValue();
}
}
/**
* Internal class used to represent a text component with a nested JSON value.
* Exception validating done is on keys and values.
*/
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
public ComplexTextTypeComponent(String key, Map<String, String> values) {
setKey(key);
setValue(values);
}
@Override
public String getKey() {
return _key;
}
public void setKey(String key) {
Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
_key = key;
}
public Map<String, String> getValue() {
return _value;
}
public void setValue(Map<String, String> value) {
Preconditions.checkArgument(value != null, "The value must be specified.");
_value = value;
}
private String _key;
private Map<String, String> _value;
@Override
public TextualComponent clone() throws CloneNotSupportedException {
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
return new ComplexTextTypeComponent(getKey(), getValue());
}
@Override
public void writeJson(JsonWriter writer) throws IOException {
writer.name(getKey());
writer.beginObject();
for (Map.Entry<String, String> jsonPair : _value.entrySet()) {
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
}
writer.endObject();
}
@SuppressWarnings("serial")
public Map<String, Object> serialize() {
return new java.util.HashMap<String, Object>() {{
put("key", getKey());
for (Map.Entry<String, String> valEntry : getValue().entrySet()) {
put("value." + valEntry.getKey(), valEntry.getValue());
}
}};
}
public static ComplexTextTypeComponent deserialize(Map<String, Object> map) {
String key = null;
Map<String, String> value = new HashMap<String, String>();
for (Map.Entry<String, Object> valEntry : map.entrySet()) {
if (valEntry.getKey().equals("key")) {
key = (String) valEntry.getValue();
} else if (valEntry.getKey().startsWith("value.")) {
value.put(((String) valEntry.getKey()).substring(6) /* Strips out the value prefix */, valEntry.getValue().toString());
}
}
return new ComplexTextTypeComponent(key, value);
}
@Override
public String getReadableString() {
return getKey();
}
}
/**
* Create a textual component representing a string literal.
* This is the default type of textual component when a single string literal is given to a method.
*
* @param textValue The text which will be represented.
* @return The text component representing the specified literal text.
*/
public static TextualComponent rawText(String textValue) {
return new ArbitraryTextTypeComponent("text", textValue);
}
/**
* Create a textual component representing a localized string.
* The client will see this text component as their localized version of the specified string <em>key</em>, which can be overridden by a resource pack.
* <p>
* If the specified translation key is not present on the client resource pack, the translation key will be displayed as a string literal to the client.
* </p>
*
* @param translateKey The string key which maps to localized text.
* @return The text component representing the specified localized text.
*/
public static TextualComponent localizedText(String translateKey) {
return new ArbitraryTextTypeComponent("translate", translateKey);
}
private static void throwUnsupportedSnapshot() {
throw new UnsupportedOperationException("This feature is only supported in snapshot releases.");
}
/**
* Create a textual component representing a scoreboard value.
* The client will see their own score for the specified objective as the text represented by this component.
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score (for the viewing player), or {@code null} if an error occurs during JSON serialization.
*/
public static TextualComponent objectiveScore(String scoreboardObjective) {
return objectiveScore("*", scoreboardObjective);
}
/**
* Create a textual component representing a scoreboard value.
* The client will see the score of the specified player for the specified objective as the text represented by this component.
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param playerName The name of the player whos score will be shown. If this string represents the single-character sequence "*", the viewing player's score will be displayed.
* Standard minecraft selectors (@a, @p, etc) are <em>not</em> supported.
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score for the specified player, or {@code null} if an error occurs during JSON serialization.
*/
public static TextualComponent objectiveScore(String playerName, String scoreboardObjective) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
return new ComplexTextTypeComponent("score", ImmutableMap.<String, String>builder()
.put("name", playerName)
.put("objective", scoreboardObjective)
.build());
}
/**
* Create a textual component representing a player name, retrievable by using a standard minecraft selector.
* The client will see the players or entities captured by the specified selector as the text represented by this component.
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param selector The minecraft player or entity selector which will capture the entities whose string representations will be displayed in the place of this text component.
* @return The text component representing the name of the entities captured by the selector.
*/
public static TextualComponent selector(String selector) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
return new ArbitraryTextTypeComponent("selector", selector);
}
}

View File

@ -1,351 +0,0 @@
package com.plotsquared.bukkit.database.plotme;
import com.intellectualcrafters.configuration.MemorySection;
import com.intellectualcrafters.configuration.file.FileConfiguration;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.command.CommandException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
public class LikePlotMeConverter {
private final String plugin;
public LikePlotMeConverter(String plugin) {
this.plugin = plugin;
}
public static String getWorld(String world) {
for (World newWorld : Bukkit.getWorlds()) {
if (newWorld.getName().equalsIgnoreCase(world)) {
return newWorld.getName();
}
}
return world;
}
private void sendMessage(String message) {
PS.debug("&3PlotMe&8->&3PlotSquared&8: &7" + message);
}
public String getPlotMePath() {
return new File(".").getAbsolutePath() + File.separator + "plugins" + File.separator + plugin + File.separator;
}
public FileConfiguration getPlotMeConfig(String dataFolder) {
File plotMeFile = new File(dataFolder + "config.yml");
if (!plotMeFile.exists()) {
return null;
}
return YamlConfiguration.loadConfiguration(plotMeFile);
}
public Set<String> getPlotMeWorlds(FileConfiguration plotConfig) {
return plotConfig.getConfigurationSection("worlds").getKeys(false);
}
public void mergeWorldYml(FileConfiguration plotConfig) {
try {
File genConfig =
new File("plugins" + File.separator + plugin + File.separator + "PlotMe-DefaultGenerator" + File.separator + "config.yml");
if (genConfig.exists()) {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(genConfig);
for (String key : yml.getKeys(true)) {
if (!plotConfig.contains(key)) {
Object value = yml.get(key);
if (!(value instanceof MemorySection)) {
plotConfig.set(key, value);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void updateWorldYml(String location) {
try {
Path path = Paths.get(location);
File file = new File(location);
if (!file.exists()) {
return;
}
String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
content = content.replace("PlotMe-DefaultGenerator", "PlotSquared");
content = content.replace("PlotMe", "PlotSquared");
content = content.replace("AthionPlots", "PlotSquared");
content = content.replace("PlotZWorld", "PlotSquared");
Files.write(path, content.getBytes(StandardCharsets.UTF_8));
} catch (IOException ignored) {}
}
public boolean run(APlotMeConnector connector) {
try {
String dataFolder = getPlotMePath();
FileConfiguration plotConfig = getPlotMeConfig(dataFolder);
if (plotConfig == null) {
return false;
}
String version = plotConfig.getString("Version");
if (version == null) {
version = plotConfig.getString("version");
}
if (!connector.accepts(version)) {
return false;
}
PS.debug("&3Using connector: " + connector.getClass().getCanonicalName());
Connection connection = connector.getPlotMeConnection(plotConfig, dataFolder);
if (!connector.isValidConnection(connection)) {
sendMessage("Cannot connect to PlotMe DB. Conversion process will not continue");
return false;
}
sendMessage("PlotMe conversion has started. To disable this, please set 'plotme-convert.enabled' to false in the 'settings.yml'");
mergeWorldYml(plotConfig);
sendMessage("Connecting to PlotMe DB");
ArrayList<Plot> createdPlots = new ArrayList<>();
sendMessage("Collecting plot data");
String dbPrefix = "PlotMe".toLowerCase();
sendMessage(" - " + dbPrefix + "Plots");
final Set<String> worlds = getPlotMeWorlds(plotConfig);
if (Settings.Enabled_Components.PLOTME_CONVERTER) {
sendMessage("Updating bukkit.yml");
updateWorldYml("bukkit.yml");
updateWorldYml("plugins/Multiverse-Core/worlds.yml");
for (String world : plotConfig.getConfigurationSection("worlds").getKeys(false)) {
sendMessage("Copying config for: " + world);
try {
String actualWorldName = getWorld(world);
connector.copyConfig(plotConfig, world, actualWorldName);
PS.get().worlds.save(PS.get().worldsFile);
} catch (IOException e) {
e.printStackTrace();
sendMessage("&c-- &lFailed to save configuration for world '" + world
+ "'\nThis will need to be done using the setup command, or manually");
}
}
}
HashMap<String, HashMap<PlotId, Plot>> plots = connector.getPlotMePlots(connection);
int plotCount = 0;
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
plotCount += entry.getValue().size();
}
if (!Settings.Enabled_Components.PLOTME_CONVERTER) {
return false;
}
sendMessage(" - " + dbPrefix + "Allowed");
sendMessage("Collected " + plotCount + " plots from PlotMe");
File plotmeDgFile = new File(dataFolder + File.separator + "PlotMe-DefaultGenerator" + File.separator + "config.yml");
if (plotmeDgFile.exists()) {
YamlConfiguration plotmeDgYml = YamlConfiguration.loadConfiguration(plotmeDgFile);
try {
for (String world : plots.keySet()) {
String actualWorldName = getWorld(world);
String plotMeWorldName = world.toLowerCase();
Integer pathWidth = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".PathWidth"); //
PS.get().worlds.set("worlds." + world + ".road.width", pathWidth);
int pathHeight = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".RoadHeight", 64); //
PS.get().worlds.set("worlds." + world + ".road.height", pathHeight);
PS.get().worlds.set("worlds." + world + ".wall.height", pathHeight);
PS.get().worlds.set("worlds." + world + ".plot.height", pathHeight);
int plotSize = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".PlotSize", 32); //
PS.get().worlds.set("worlds." + world + ".plot.size", plotSize);
String wallblock = plotmeDgYml.getString("worlds." + plotMeWorldName + ".WallBlock", "44"); //
PS.get().worlds.set("worlds." + world + ".wall.block", wallblock);
String floor = plotmeDgYml.getString("worlds." + plotMeWorldName + ".PlotFloorBlock", "2"); //
PS.get().worlds.set("worlds." + world + ".plot.floor", Collections.singletonList(floor));
String filling = plotmeDgYml.getString("worlds." + plotMeWorldName + ".FillBlock", "3"); //
PS.get().worlds.set("worlds." + world + ".plot.filling", Collections.singletonList(filling));
String road = plotmeDgYml.getString("worlds." + plotMeWorldName + ".RoadMainBlock", "5");
PS.get().worlds.set("worlds." + world + ".road.block", road);
int height = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".RoadHeight"); //
if (height == 0) {
height = plotmeDgYml.getInt("worlds." + plotMeWorldName + ".GroundHeight", 64); //
}
PS.get().worlds.set("worlds." + actualWorldName + ".road.height", height);
PS.get().worlds.set("worlds." + actualWorldName + ".plot.height", height);
PS.get().worlds.set("worlds." + actualWorldName + ".wall.height", height);
PS.get().worlds.save(PS.get().worldsFile);
}
} catch (IOException ignored) {}
}
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
String world = entry.getKey();
PlotArea area = PS.get().getPlotArea(world, null);
int duplicate = 0;
if (area != null) {
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
if (area.getOwnedPlotAbs(entry2.getKey()) != null) {
duplicate++;
} else {
createdPlots.add(entry2.getValue());
}
}
if (duplicate > 0) {
PS.debug("&c[WARNING] Found " + duplicate + " duplicate plots already in DB for world: '" + world
+ "'. Have you run the converter already?");
}
} else {
if (PS.get().plots_tmp != null) {
HashMap<PlotId, Plot> map = PS.get().plots_tmp.get(world);
if (map != null) {
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
if (map.containsKey(entry2.getKey())) {
duplicate++;
} else {
createdPlots.add(entry2.getValue());
}
}
if (duplicate > 0) {
PS.debug("&c[WARNING] Found " + duplicate + " duplicate plots already in DB for world: '" + world
+ "'. Have you run the converter already?");
}
continue;
}
}
createdPlots.addAll(entry.getValue().values());
}
}
sendMessage("Creating plot DB");
Thread.sleep(1000);
final AtomicBoolean done = new AtomicBoolean(false);
DBFunc.createPlotsAndData(createdPlots, new Runnable() {
@Override
public void run() {
if (done.get()) {
done();
sendMessage("&aDatabase conversion is now complete!");
PS.debug("&c - Stop the server");
PS.debug("&c - Disable 'plotme-convert.enabled' and 'plotme-convert.cache-uuids' in the settings.yml");
PS.debug("&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
PS.debug("&c - Start the server");
PS.get().setPlots(DBFunc.getPlots());
} else {
sendMessage("&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
done.set(true);
}
}
});
sendMessage("Saving configuration...");
try {
PS.get().worlds.save(PS.get().worldsFile);
} catch (IOException ignored) {
sendMessage(" - &cFailed to save configuration.");
}
TaskManager.runTask(new Runnable() {
@Override
public void run() {
try {
boolean mv = false;
boolean mw = false;
if ((Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null) && Bukkit.getPluginManager().getPlugin("Multiverse-Core")
.isEnabled()) {
mv = true;
} else if ((Bukkit.getPluginManager().getPlugin("MultiWorld") != null) && Bukkit.getPluginManager().getPlugin("MultiWorld")
.isEnabled()) {
mw = true;
}
for (String worldName : worlds) {
World world = Bukkit.getWorld(getWorld(worldName));
if (world == null) {
sendMessage("&cInvalid world in PlotMe configuration: " + worldName);
}
String actualWorldName = world.getName();
sendMessage("Reloading generator for world: '" + actualWorldName + "'...");
PS.get().removePlotAreas(actualWorldName);
if (mv) {
// unload world with MV
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv unload " + actualWorldName);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// load world with MV
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mv import " + actualWorldName + " normal -g PlotSquared");
} else if (mw) {
// unload world with MW
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw unload " + actualWorldName);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// load world with MW
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(),
"mw create " + actualWorldName + " plugin:PlotSquared");
} else {
// Load using Bukkit API
// - User must set generator manually
Bukkit.getServer().unloadWorld(world, true);
World myWorld = WorldCreator.name(actualWorldName).generator(new BukkitPlotGenerator(new HybridGen())).createWorld();
myWorld.save();
}
}
} catch (CommandException e) {
e.printStackTrace();
}
if (done.get()) {
done();
sendMessage("&aDatabase conversion is now complete!");
PS.debug("&c - Stop the server");
PS.debug("&c - Disable 'plotme-convert.enabled' and 'plotme-convert.cache-uuids' in the settings.yml");
PS.debug("&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
PS.debug("&c - Start the server");
} else {
sendMessage("&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
done.set(true);
}
}
});
} catch (InterruptedException | SQLException e) {
e.printStackTrace();
PS.debug("&/end/");
}
return true;
}
public void done() {
PS.get().setPlots(DBFunc.getPlots());
}
}

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