328 Commits

Author SHA1 Message Date
foss-mc
6988bec0ee fix: update dependencies and rebranding 2025-02-18 18:18:07 +11:00
josephworks
68193885f5 Update README.md 2024-08-08 11:44:52 -07:00
josephworks
eba57d2c30 Merge pull request #215 from siyy123/ver/1.16.5
Update Log4j
2022-03-17 18:46:10 -07:00
siyy123
f61f8a2ebb Update Log4j 2022-03-18 07:35:13 +08:00
ㄗㄠˋ ㄑㄧˊ
34852bf543 Update 0015-Modify-default-configs.patch 2021-08-08 16:43:49 +00:00
ㄗㄠˋ ㄑㄧˊ
4e2340e8fd Update 0015-Modify-default-configs.patch 2021-08-08 16:43:17 +00:00
Joseph Robinson
33aa25b2e0 Merge pull request #208 from ghost/revert-204-ver/1.16.5
Revert "Update .gitmodules"
2021-07-24 15:22:01 +00:00
Primia
0a5314ecb3 Revert "Update .gitmodules" 2021-07-24 13:58:58 +08:00
LegacyGamerHD
480a5fca27 Merge pull request #204 from Primia/ver/1.16.5
Update .gitmodules
2021-07-10 20:03:57 +02:00
Primia
59d89107c5 Update .gitmodules 2021-07-02 00:11:42 +08:00
Joseph Robinson
6be3d577c7 Update Jenkinsfile 2021-03-12 19:04:04 -07:00
Joseph Robinson
3aa2e99752 Merge pull request #198 from HookWoods/ver/1.16.5
Update patches to 1.16.5
2021-03-12 18:40:29 -07:00
Hugo Planque
c548038547 try to fix velocity repo 2021-03-12 20:00:33 +01:00
Hugo Planque
5b03eb1aa4 Update patches to 1.16.5 2021-03-12 19:22:10 +01:00
Joseph Robinson
aeaa4c4ca2 Merge pull request #197 from HookWoods/ver/1.16.5
Update tuinity 1.16.5
2021-03-11 13:21:28 -07:00
Hugo Planque
ad25e7ef02 Updated Upstream (Tuinity)
/e/Developpement/dev/Akarin 1
Tuinity Changes:
5b6d8be Updated Upstream (Paper)
81d5fc1 Fix NPE in pickup logic for arrow
2021-03-11 21:16:58 +01:00
Hugo Planque
f849bcaf04 Upstream tuinity 2021-03-11 21:09:52 +01:00
Joseph Robinson
62342de306 Update README.md 2021-03-02 09:21:56 -07:00
Joseph Robinson
dfcbbf5aaa Update SUPPORT.md 2021-03-02 09:20:28 -07:00
Joseph Robinson
4225fcf8d2 Updated Tuinity's Paper 2020-12-15 14:29:47 -07:00
Joseph Robinson
cf361a2fa1 Update README.md 2020-11-30 08:48:28 -07:00
Joseph Robinson
bcbeae5fdb Update README.md 2020-11-30 08:43:40 -07:00
Joseph Robinson
65feaec945 Update README.md 2020-11-30 08:42:05 -07:00
Joseph Robinson
7773efcfad Update README.md 2020-11-30 08:41:37 -07:00
Joseph Robinson
773f36d908 Merge pull request #189 from CirnoTH/patch-2
Remove unsafe option
2020-11-30 08:40:50 -07:00
CirnoTH
35278cd7c0 Remove unsafe option
"disable-move-event" is a bad option, it will break plugins that listens to InventoryMoveItemEvent.
2020-11-30 23:29:46 +08:00
Joseph Robinson
b53f48a85b Update Jenkinsfile 2020-11-28 14:15:56 -07:00
Joseph Robinson
1e9cf1a3d8 Update SUPPORT.md 2020-11-28 13:36:16 -07:00
LegacyGamerHD
b9255e8a0d kinda useless when we have jenkins 2020-11-26 12:41:00 +01:00
Joseph Robinson
f6e4782bc2 Update Jenkinsfile 2020-11-24 19:35:15 -07:00
Joseph Robinson
5ecf3feab6 Update Jenkinsfile 2020-11-24 19:33:18 -07:00
Joseph Robinson
cbd236bd6e Updated JenkinsFile 2020-11-19 14:43:17 -07:00
Joseph Robinson
0d2ff083db Removed Gradle 2020-11-19 14:08:54 -07:00
Joseph Robinson
72e3c4a96f Update README.md 2020-11-16 19:47:06 -07:00
Joseph Robinson
bbad638c88 Update README.md 2020-11-10 21:22:52 -07:00
Joseph Robinson
bbdea8ed57 Update Jenkinsfile 2020-11-10 21:22:00 -07:00
Joseph Robinson
bb9db8b0c7 Updated tuinity to spottedleaf repo 2020-11-10 21:05:16 -07:00
Joseph Robinson
6961481ce0 Updated Tuinity branch 2020-11-10 20:59:54 -07:00
Joseph Robinson
de978305ae Updated Tuinity 2020-11-10 20:58:05 -07:00
Joseph Robinson
62d4b43ee8 Update SUPPORT.md 2020-11-10 20:28:35 -07:00
Joseph Robinson
21fffd0c66 Update README.md 2020-11-10 13:13:06 -07:00
Joseph Robinson
4bd120bfe2 Merge pull request #186 from adsa562/patch-1
add demo server
2020-09-15 12:45:31 -07:00
Tsuna
1f8eccf535 add demo server 2020-09-15 23:23:37 +08:00
Joseph Robinson
630ea7242d Updated Tuinity 2020-09-14 16:34:41 -07:00
Joseph Robinson
59fae5a4e7 Made 1.15.2 build again 2020-09-14 15:54:30 -07:00
Joseph Robinson
a339866983 Update SUPPORT.md 2020-08-24 21:20:31 -07:00
LegacyGamerHD
db61690ca9 stated that it is not a bedrock server software
removed my server
instead of bedrock use stability
2020-08-23 10:26:29 +02:00
Joseph Robinson
75b7f131c4 removed broken patch 2020-08-18 15:22:47 -07:00
Joseph Robinson
c5a7778cdf fixed build 2020-08-11 09:51:35 -07:00
Joseph Robinson
2d3ea37895 Updated Tuinity and Paper 2020-08-11 09:12:26 -07:00
Joseph Robinson
220d1b8c5c Removed patch 0019 - breaks upstream 2020-08-11 09:03:04 -07:00
Joseph Robinson
1ccf6150fa Added tuinity branch to gitmodules 2020-08-11 08:58:42 -07:00
ㄗㄠˋ ㄑㄧˊ
c5e73c7b4e Updated Upstream (Tuinity)
Upstream has released updates that appears to apply and compile correctly
Tuinity Changes:
18fdc0c Updated Upstream (Paper)
9a6fb96 Change paper target branch to ver/1.15.2
067a82a Updated Upstream (Paper)
db8a861 Updated Upstream (Paper)
2020-07-07 11:05:58 +08:00
Joseph Robinson
90e3f89e0a Update SUPPORT.md 2020-07-01 09:29:46 -07:00
ㄗㄠˋ ㄑㄧˊ
b30241b848 fix 2020-07-01 23:25:27 +08:00
ㄗㄠˋ ㄑㄧˊ
4e06aea9f0 fix 2020-07-01 22:44:41 +08:00
ㄗㄠˋ ㄑㄧˊ
d7466e342f Updated Upstream (Tuinity)
Upstream has released updates that appears to apply and compile correctly
Tuinity Changes:
db8a861 Updated Upstream (Paper)
cb75b52 Updated Upstream (Paper)
98e9d5b Updated Upstream (Paper)
1aa9097 Updated Upstream (Paper)
126d3cc Fix abnormally high cpu usage caused by lighting
9a88f39 Fix skull NPE
eedc3fc Updated Upstream (Paper)
d0e617d Updated Upstream (Paper)
15c661b Updated Upstream (Paper)
2020-07-01 21:44:23 +08:00
ㄗㄠˋ ㄑㄧˊ
ea4cd742bb update Tuinity submodule url 2020-07-01 19:43:19 +08:00
Joseph Robinson
16bcdffd58 Dropped 1.14.4 support 2020-06-24 22:14:18 -07:00
Joseph Robinson
6b7fa95e5e added git submodule command to build script 2020-06-24 09:22:04 -07:00
Joseph Robinson
44356f510f Updated jenkins badge 2020-06-20 12:44:42 -07:00
ㄗㄠˋ ㄑㄧˊ
6d85efa9aa use Torch bStats 2020-06-19 20:04:38 +08:00
ㄗㄠˋ ㄑㄧˊ
f40f067478 Remove Streams using IntelliJ IDEA 2020-06-19 19:57:01 +08:00
ㄗㄠˋ ㄑㄧˊ
518c6e1ce6 Updated Upstream (Tuinity)
Upstream has released updates that appears to apply and compile correctly
Tuinity Changes:
12efad6 Prevent log spam for "Block is water but TE is chest"
6d4fc1f Prevent unload() calls removing tickets for sync loads
f9de229 Allow entities to be removed during entity tick
ca376d1 Make sure flush consolidation works
16b65f0 Make setting of TE less hacky
7c03cbe Rebuild patches
da09c8c Merge branch 'master' of github.com:Spottedleaf/Tuinity
7ed0891 Remove an unused patch (#133)
fc37bbd Remove allocation of Long by the light engine
1bb0c6a Updated Upstream (Paper)
eb0ca1a Ensure pistons moving signs drops signs items if they can't be placed
35bd141 Add the option to allow pistons to push tile entities
f355806 Fix incorrect async future completion by worldgen thread
2051fe3 Revert frustrum priority in ChunkMapDistance
7e7af54 Updated Upstream (Paper)
8c4edd5 Prevent getChunkAt from retaining chunks for long periods of time
42ce364 Updated Upstream (Paper)
391273f Fix newer jdk compile
2020-06-19 19:40:28 +08:00
ㄗㄠˋ ㄑㄧˊ
9c56ced43e Updated Upstream (Tuinity)
Upstream has released updates that appears to apply and compile correctly
\Tuinity Changes:
32ac48d Updated Upstream (Paper)
e41b5ce Optimise some block api calls
6f9ca4f Always use full Chunk objects for collision checking + getType calls
2020-06-06 12:06:52 +08:00
Joseph Robinson
7236c2e48d Update README.md 2020-06-05 10:15:40 -07:00
ㄗㄠˋ ㄑㄧˊ
d49bc970a5 Revert "Option-for-async-world-ticking.patch" 2020-05-31 12:22:50 +08:00
ㄗㄠˋ ㄑㄧˊ
66baff1de0 Modify default configs 2020-05-31 12:11:24 +08:00
ㄗㄠˋ ㄑㄧˊ
b0c8570540 Option for async world ticking 2020-05-31 11:37:53 +08:00
ㄗㄠˋ ㄑㄧˊ
ef58d9d301 switch to Tuinity 2020-05-31 10:54:52 +08:00
Joseph Robinson
39ef5ce402 fixed gradle wrapper deletion 2020-05-17 22:08:42 -07:00
Joseph Robinson
cabecd8235 readded gradle 2020-05-17 22:07:50 -07:00
Joseph Robinson
40927d6242 removed gradle entries from gitignore 2020-05-17 22:07:27 -07:00
Joseph Robinson
39eaaefd03 Fixed git deleting wrapper 2020-05-16 19:38:24 -07:00
Joseph Robinson
59841b8f8b Added maven tests 2020-05-16 15:38:36 -07:00
Joseph Robinson
e8b3b58b73 Added surefire report plugin 2020-05-16 15:36:16 -07:00
Joseph Robinson
86789c2fa3 Update Jenkinsfile 2020-05-16 15:16:37 -07:00
Joseph Robinson
a66520e29d Update Jenkinsfile 2020-05-16 15:11:41 -07:00
Joseph Robinson
fe2aab88e3 Update Jenkinsfile 2020-05-16 14:54:11 -07:00
Joseph Robinson
03db17b2b0 Update Jenkinsfile 2020-05-16 14:34:32 -07:00
Joseph Robinson
dac220f206 Update Jenkinsfile 2020-05-16 14:26:34 -07:00
Joseph Robinson
5a5eda4b09 Update Jenkinsfile 2020-05-16 14:09:08 -07:00
Joseph Robinson
b7c5442ec6 Update Jenkinsfile 2020-05-16 13:36:43 -07:00
Joseph Robinson
81f70deb80 Fixed issue with second discordsend 2020-05-16 12:45:08 -07:00
Joseph Robinson
039e306258 Update Jenkinsfile 2020-05-16 12:43:16 -07:00
Joseph Robinson
b1722e413b Update Jenkinsfile 2020-05-16 12:22:39 -07:00
Joseph Robinson
bc0e402dd0 Update Jenkinsfile 2020-05-16 12:08:07 -07:00
Joseph Robinson
1225c9a974 Update Jenkinsfile 2020-05-16 11:53:48 -07:00
Joseph Robinson
50c23fe297 Update Jenkinsfile 2020-05-16 11:26:38 -07:00
Joseph Robinson
b66c57f732 Update Jenkinsfile 2020-05-16 11:24:59 -07:00
Joseph Robinson
61ea3d099a Update Jenkinsfile 2020-05-16 11:11:04 -07:00
Joseph Robinson
68ac862f97 Update Jenkinsfile 2020-05-16 11:04:21 -07:00
Joseph Robinson
c66e679bdd Update Jenkinsfile 2020-05-16 10:45:53 -07:00
Joseph Robinson
edabb53147 Update Jenkinsfile 2020-05-15 22:31:46 -07:00
Joseph Robinson
caa6d634f5 Update Jenkinsfile 2020-05-15 22:31:33 -07:00
Joseph Robinson
df4727ead9 Added discord integration with pipeline 2020-05-15 22:10:27 -07:00
Joseph Robinson
50386a0373 Fixed archiving artifacts 2020-05-15 13:24:42 -07:00
Joseph Robinson
86928e546a Updated build init 2020-05-15 13:09:18 -07:00
ㄗㄠˋ ㄑㄧˊ
4b5100fd8f cleanup mcdev import 2020-05-15 18:21:09 +08:00
Joseph Robinson
4072f0c3e2 Updated the Jenkinsfile 2020-05-13 19:35:12 -07:00
Joseph Robinson
848851db37 Added Jenkinsfile 2020-05-13 19:27:44 -07:00
Joseph Robinson
53fd5de975 General Readme changes 2020-05-10 15:10:50 -07:00
ㄗㄠˋ ㄑㄧˊ
49aa46cfa8 fix 2020-05-09 18:37:39 +08:00
Joseph Robinson
e78d9787f2 Update LICENSE.md 2020-05-08 17:44:31 -07:00
Joseph Robinson
91fb56b9bc Update README.md 2020-05-08 17:24:16 -07:00
Joseph Robinson
e2bfe688f1 Update README.md 2020-05-08 17:22:57 -07:00
Joseph Robinson
5c7d5d9af6 Update README.md 2020-05-08 17:21:48 -07:00
Joseph Robinson
e894487240 Update README.md 2020-05-08 17:19:04 -07:00
Joseph Robinson
71ec109edc Update README.md 2020-05-08 17:18:07 -07:00
Joseph Robinson
eeda28c4bd Update README.md 2020-05-08 17:17:39 -07:00
Sotr
69537b0219 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
cfed00cf Fix Light Command
a6ff84ad Revert Nibble patch, causing issues still
f1a8eb7f Use a finalizer for light packet instead of onPacketDone
03c9bb05 Optimize NibbleArray to use pooled buffers
d0a528b1 Move delayed init down later in tick, improve accuracy of startup time
cc477e6a Force Plugins that use delayed tasks for init back in their place
597263fd Don't skip full player connection tick when dead
e2c23475 Revert loaded entity list (#3304)
fa87db6b Move another NetworkManager util into the inner class (#3303)
841c7d18 Make loaded entity list logic more consistent (#3301)
36f34f01 Updated Upstream (Bukkit/CraftBukkit)
5ca5f131 Rebuild all patches using the new rebuild pattern
1ccff6fa Add villager reputation API
5c0bfffa Speed up rebuilding patches and reduce diff
f37381ea Optimize Network Manager to not need synchronization
8f9df2ed Anti Xray cleanup
878c66f1 No-Tick view distance implementation - Closes #3196
b87743c1 Stop copy-on-write operations for updating light data
97a9c972 Optimize isOutsideRange to use distance maps
b4e629a2 Use distance map to optimise entity tracker / Misc Utils
d80d1517 Optimize Entity Ticking to Loaded Chunks only
31d7686d Add item slot helper methods for various inventories (#3221)
75e1e3b3 Mob Goal API
c7bc393a Revert "Don't flush packet queue off main thread"
1abd2bd2 Don't flush packet queue off main thread
a4ed58a9 Clean up Direct Memory Region Files Fix for different Java versions
55e35019 Set cap on JDK per-thread native byte buffer cache
b5101f4f Cleanup Region Files Direct Memory on close
81e655d7 Optimize Voxel Shape Merging
ed9fc11f Sync position on teleportation
9c326fce Nanothing to see here
3e9fc24b Attempt to fix FastLogin maybe
932e97f3 Rename to AsyncPlayerSendSuggestionsEvent to be consistent in naming
0dd19075 AsyncSendPlayerSuggestionsEvent Brigadier Event
a9e20e5f Fix being kicked in survival for block picking - Fixes #3277
4d20537e Expose game version (#3274)
85fb0015 Validate PickItem Packet and kick for invalid - Fixes #3256
5729bc71 Special case Keep Alive packets from Anti Xray
a76b7740 Improved oversized chunk data packet handling
a6f78170 Use Vanilla Bed Search for non players (Villagers)
68fb98b5 Fix 2 plugin specific issues with loot drop and pathfinders
6e41f7b7 Update Activation Range 2.0 with more villager controls
57dd3971 Updated Upstream (Bukkit/CraftBukkit)
a6a197b1 Bump API ASM version to follow server
5ab48ad9 Fix commodore (#3264)
87e7ee7e Improve Async Login to avoid firing in middle of Entity Ticking
8ce3dd5f [CI-SKIP] Fix Mojang API Brigadier dep - THIS IS NOT A NEW BUILD
00d760a5 Fix build due to spigot changing the build timestamp process
842e040c Updated Upstream (Bukkit/CraftBukkit/Spigot)
c03260a2 Add getter and setter for villager's numberOfRestocksToday (#3231)
fe366fbe null check tracker for entity metadata update - Fixes #3070
fdf41b74 Implement Brigadier Mojang API
e0ea2e0e Entity Activation Range 2.0! Major improvements to restoring behavior
10396d28 Fix Tracking Range mismatch on Vehicle/Passenger checks
68994c64 Add a config to turn off Optimized TickList #3145
d847d336 Improve blocking players from opening inventories while sleeping
ac4f6b50 Clean up Timings and Async Chunk Configs
fcf89e85 Improve mid tick chunk loading, Fix Oversleep, other improvements
ab36835c Improve random ticking behaviour - Fixes #3181
a6ac47e5 Fix numerous item duplication issues and teleport issues
b7402f11 Add phantom creative and insomniac controls (#3222)
75819fac Fix Potion#toItemStack swapping the extended and upgraded constructor values (#3216)
cb15cfa4 Improve Async Login so pending connections dont get exposed
f275e9cb Optimize Hoppers - Major Boost - Got2GoFast!
0106485c Improvements to watchdog changes
65934b1f Fix build for last commit. 5am commits are great
3f436029 Don't process watchdog until server has fully started and ticked.
938bd972 Don't fire BlockFade on worldgen threads - Fixes #3208
509a828e Fix loading spawn chunks when async chunks is off
8a91bfd2 Improvements to async login
bf698865 Revert "Re-track players that dismount from other players"
82b98418 Fix some issues with async login as well another source of sync loads
aa241d2b Allow multiple callbacks to schedule for Callback Executor
a2064a41 Add PlayerAttackEntityCooldownResetEvent This event is called when processing a player's attack on an entity right before their attack strength cd is reset, there are no existing events that fire within this period of time so it was impossible to capture the players attack strength via API prior to this commit.
f48d4299 Allow sleeping players to float
eeb2f67d Fix Bed respawn deviating too far from vanilla (#3195)
68a7b9fe Move player to spawn point if spawn in unloaded world
f29c7ebd Improve async login (#3189)
9fd36824 Fix Citizens Player NPC tracking issue - Fixes #3186
2020-05-08 17:57:09 +08:00
ㄗㄠˋ ㄑㄧˊ
2a2e9149ec update maven flags 2020-05-02 10:59:20 +08:00
Joseph Robinson
6257ad1520 Merge pull request #164 from Akarin-project/buildmultithread
Buildmultithread
2020-04-30 11:07:19 -07:00
Joseph Robinson
14a36a6861 Added multithreading 2020-04-30 10:50:42 -07:00
Joseph Robinson
09aaa59f0a Added gradle 2020-04-30 10:25:58 -07:00
Joseph Robinson
f20260117f Update and rename SECURITY.md to SUPPORT.md 2020-04-23 19:52:54 -07:00
LegacyGamerHD
fe1dd687d0 upstream 2020-04-19 16:18:53 +02:00
ㄗㄠˋ ㄑㄧˊ
341aca2883 fix 2020-04-18 20:21:43 +08:00
ㄗㄠˋ ㄑㄧˊ
1b66f4548e Tuinity View distance api
Based on my Tuinity fork: caf081984d
2020-04-18 20:01:29 +08:00
ㄗㄠˋ ㄑㄧˊ
3f277e8af5 Log exceptions for async chunk load failures 2020-04-18 18:11:28 +08:00
ㄗㄠˋ ㄑㄧˊ
f802f1d7ea Change writes to use NORMAL priority rather than LOW 2020-04-18 18:09:03 +08:00
ㄗㄠˋ ㄑㄧˊ
6f26a671b5 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
26fb7cc35 Fix Chunk Post Processing deadlock risk
ffecc4e26 Revert "Optimize entity list iteration requiring entities be in"
0a4286cc4 Prevent Fire from loading chunks
07915ea18 Add Player Client Options API (#2883)
bc48a3172 Optimize entity list iteration requiring entities be in  loaded chunks
88092fef1 Optimize ChunkProviderServer's chunk level checking helper methods
01e8ce8d2 Forced Watchdog Crash support and Improve Async Shutdown
fdb8fe780 Be less strict with vanilla teleport command limits
0f06d3806 Restrict vanilla teleport command to within worldborder
24d93aafa Fix Optional null issue - Fixes #3155
eb71c5fa3 Fix incorect timing of mspt
1ca804342 Optimise entity hard collision checking
b67a42376 Don't run entity collision code if not needed
bd9aa547d Optimise ArraySetSorted#removeIf
2020-04-18 18:05:03 +08:00
ㄗㄠˋ ㄑㄧˊ
4b8997f4b5 get rid of current-paper; update options of format-patch 2020-04-18 18:00:20 +08:00
ㄗㄠˋ ㄑㄧˊ
d2674b1d4a better cache 2020-04-18 17:57:03 +08:00
ㄗㄠˋ ㄑㄧˊ
86e68e7f60 update bStats url 2020-04-16 15:34:15 +08:00
Sotr
44c20dd789 Further optimize pathfinder 2020-04-16 03:11:04 +07:00
Sotr
9f21b23335 Format patches 2020-04-16 02:17:13 +07:00
Sotr
4b9b6169c3 Fixes patch conflict with Anti-Xray - Close GH-158 2020-04-16 00:26:01 +07:00
Sotr
9a3a5c67f3 Fully remove callers of vanilla profiler 2020-04-15 23:18:38 +07:00
Sotr
08d2f7a357 Remove a few more streams 2020-04-15 22:46:29 +07:00
Sotr
542ac96613 Retitle some patches 2020-04-15 22:21:06 +07:00
Sotr
17c797f817 Format patches 2020-04-15 22:19:23 +07:00
Sotr
5ee75e7aa4 Clarify patch titles 2020-04-15 22:11:13 +07:00
Sotr
44f01b0fd3 Format async pathfinder patch 2020-04-15 22:07:35 +07:00
Sotr
a5f25a0d29 Fixup missing modification 2020-04-15 21:40:23 +07:00
Sotr
dfd3a966d5 Fix typo 2020-04-15 20:01:12 +07:00
Sotr
4d0ea06a78 Remove stream and simplify op in pathfinder & fix scripts 2020-04-15 19:59:23 +07:00
Sotr
790aedb67b Fix wrong gitcmd & rebuild patches 2020-04-15 17:24:46 +07:00
Sotr
1f992c63e9 Cache Hashcode for BlockPosition 2020-04-15 04:28:58 +07:00
Sotr
78713a1039 Remove stream for ender teleport 2020-04-15 04:18:04 +07:00
Sotr
ecc989a4e9 Merge branch '1.15.2' of github.com:Akarin-project/Akarin into 1.15.2 2020-04-15 04:02:27 +07:00
Sotr
0974876d10 Fix missing caller 2020-04-15 04:00:52 +07:00
Sotr
997e18267e Optimize door interact pathfinding 2020-04-15 03:59:51 +07:00
Sotr
3e03959525 Optimize door interact pathfinding 2020-04-15 03:52:25 +07:00
Sotr
177baf669a Multiple patches backported from Tuinity 2020-04-15 02:52:10 +07:00
Sotr
e4cdd73478 [CI-SKIP] Remove empty lines 2020-04-15 01:22:34 +07:00
Sotr
0aa5f300de [CI-SKIP] Cleanup patch 2020-04-15 01:19:11 +07:00
Sotr
9b12bb9099 Save more lines & fix patch order 2020-04-15 01:16:46 +07:00
Sotr
f5c5fa32bf Fix errors on eclipse 2020-04-15 00:55:18 +07:00
ㄗㄠˋ ㄑㄧˊ
14e953b249 remove broken gradle wrapper 2020-04-14 14:35:20 +08:00
Joseph Robinson
2b85988951 Added GitHub Packages 2020-04-13 23:04:50 -07:00
Sotr
30f1e8427f Merge branch '1.15.2' of github.com:Akarin-project/Akarin into 1.15.2 2020-04-14 04:46:19 +07:00
Sotr
39007a5eb3 Add more arguments 2020-04-14 04:46:00 +07:00
Sotr
9353e8d78c Fix typo in patch title 2020-04-14 04:11:46 +07:00
Sotr
6738f46ead Never drop items on command "/give" 2020-04-14 04:08:08 +07:00
Sotr
8aed0bbc0f Possibly fix build 2020-04-13 22:00:15 +07:00
Sotr
1a234f3daf Fixes typo 2020-04-13 21:45:17 +07:00
Sotr
df40958a45 Actually fix scripts 2020-04-13 21:40:08 +07:00
Sotr
75f7fd17cb Possibly fix import scripts 2020-04-13 21:30:41 +07:00
Sotr
f36324e061 Possibly fix shells 2020-04-13 21:15:08 +07:00
Sotr
525aeb9112 Setup Paper before applying patches 2020-04-13 21:01:32 +07:00
Sotr
e461f5cdf5 Rebuild patches 2020-04-13 20:51:34 +07:00
Sotr
a40c1a79c7 A few more tweaks in script 2020-04-13 20:39:14 +07:00
ㄗㄠˋ ㄑㄧˊ
b14089ec8b Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
81706e626 Make the shutdown thread try to shutdown on main
891824509 Prevent opening inventories when frozen
e6d395cc8 Port 04-Util.patch from Tuinity (#3136)
59453f667 Fix incorrectly loading chunks on a cancelled interact event
bdcc31caa Let invalid positioned entities clean up previous chunk by the chunkCheck
2020-04-13 18:39:40 +08:00
LegacyGamerHD
6a64b0a0b0 add my server back because i miss understand my partner
whoops
2020-04-13 10:38:15 +02:00
ㄗㄠˋ ㄑㄧˊ
7e709d1e2b Akarin Metrics 2020-04-13 13:19:03 +08:00
ㄗㄠˋ ㄑㄧˊ
b6e993f8d3 fix scripts/applyPatches.sh and update upstream 2020-04-13 10:43:24 +08:00
ㄗㄠˋ ㄑㄧˊ
43ef314288 move gitcmd to script/functions.sh 2020-04-13 10:33:12 +08:00
ㄗㄠˋ ㄑㄧˊ
8ea17d256c remove "git config commit.gpgsign" since it's included in $gitcmd; set encoding to UTF-8; correct scripts file name 2020-04-13 10:27:12 +08:00
Sotr
aff7715bff Fixup artifact name 2020-04-13 05:45:40 +07:00
Sotr
9d1de1b4b3 Fix Actions 2020-04-13 05:38:02 +07:00
Sotr
686a1c9053 Fixes clip script 2020-04-13 05:35:36 +07:00
Sotr
5d4688ff88 Possibly fix permission 2020-04-13 05:15:35 +07:00
Sotr
07e7fa41ad Fixes typo 2020-04-13 05:11:54 +07:00
Sotr
16732ba964 Possibly fix chmod usage 2020-04-13 05:09:08 +07:00
Sotr
8cc5beac54 Add permission for scripts 2020-04-13 05:05:17 +07:00
Sotr
a38e3f4149 Possibly fix build 2020-04-13 05:02:43 +07:00
Sotr
6b125ec995 Fixes shell typo 2020-04-13 04:59:43 +07:00
Sotr
7aa8eb6363 Rewrite scripts and fix more build issues 2020-04-13 04:58:10 +07:00
LegacyGamerHD
6f32d02a63 remove my server curently running saberspigot
i might come back to akarin idk  ¯\_(ツ)_/¯
2020-04-12 11:26:55 +02:00
ㄗㄠˋ ㄑㄧˊ
173fa1ee6d Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
bc17ce69d Delay unsafe actions until after entity ticking is done - Fixes #3114
5553e6b3e Disable Sync Events firing Async errors during shutdown
e12c51d9b Use better variable for isStopping() API
586ee2bb1 Remove patch for MC-111480, fixed in 1.14
09a942155 Remove streams from Mob AI System
bb5c294ec Fix Disabling Asynchronous Chunks
089d83568 Implement Chunk Priority / Urgency System for World Gen
fce69af70 Use dedicated thread for main thread blocking chunk loads
588b62e47 Add tick times API and /mspt command (#3102)
11de41c77 Add API MinecraftServer#isStopping (#3129)
942ff3c28 My patches are under MIT (#3130)
2020-04-12 12:13:51 +08:00
ㄗㄠˋ ㄑㄧˊ
6a3b8598fb update upstream and fix scripts 2020-04-11 13:13:24 +08:00
ㄗㄠˋ ㄑㄧˊ
15e263286f more fix 2020-04-11 13:07:15 +08:00
ㄗㄠˋ ㄑㄧˊ
5ed989168a more fixes 2020-04-11 12:53:03 +08:00
ㄗㄠˋ ㄑㄧˊ
72efdaaa43 more fix 2020-04-11 12:42:54 +08:00
ㄗㄠˋ ㄑㄧˊ
e538e89116 partially fix scripts 2020-04-11 12:37:04 +08:00
ㄗㄠˋ ㄑㄧˊ
27c7488d6c fix permissions of scripts 2020-04-11 12:08:35 +08:00
LegacyGamerHD
f75c743f0c another try to fix git actions 2020-04-10 18:46:24 +02:00
LegacyGamerHD
3843a9749d add sudo to the build script 2020-04-10 18:37:55 +02:00
Sotr
7f43fec40c Clarify a few scripts 2020-04-10 19:12:12 +07:00
Sotr
c42aca9d76 Fixes submodule 2020-04-10 18:32:03 +07:00
Sotr
6f81d8ccb6 Reignore git files 2020-04-10 18:10:51 +07:00
Sotr
93c202f509 Add more function to script 2020-04-10 17:55:34 +07:00
ㄗㄠˋ ㄑㄧˊ
98d9de5ed3 remove fast notes on readme since its function is different in current scripts 2020-04-10 18:31:11 +08:00
cakoyo
1967b9ac17 Removing official server link 2020-04-10 17:11:13 +07:00
cakoyo
360289af08 Possibly fix the build status 2020-04-10 17:07:50 +07:00
ㄗㄠˋ ㄑㄧˊ
9d6226f8af make the patch more readable 2020-04-10 15:51:42 +08:00
ㄗㄠˋ ㄑㄧˊ
4b20455cd5 Swaps the predicate order of collision 2020-04-10 15:47:49 +08:00
ㄗㄠˋ ㄑㄧˊ
b4a88eb15f Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
23ee0a8a8 Fix issue with 0,0 chunks causing crash
2020-04-10 11:14:23 +08:00
ㄗㄠˋ ㄑㄧˊ
504eb37c5e Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
bc8fafb20 Updated Upstream (CraftBukkit/Spigot)
ebbca5ced Drowned is a RangedEntity (fixes API for Drowned to support Ranged)
83b03eee0 Don't move existing players to world spawn
3b3e38fd0 Fix issue with loading chunk during ticking chunks issue
78431dcae Update test server startup script
ab74bb451 Speed up processing of chunk loads and generation
f5dd491fc Increase Light Queue Size
9ab693487 Don't load chunks when attempting to unload a chunk
38c626229 Improve Optimize Memory use logic to make iterator safer and fix bad plugins like P2
d33ba160a Fix incorrect keyword use on visibleChunksClone
2f3430158 Updated Upstream (Bukkit/CraftBukkit)
a65831bd6 Optimize PlayerChunkMap memory use for visibleChunks
2020-04-10 11:02:20 +08:00
ㄗㄠˋ ㄑㄧˊ
468cd6781d rebuild patches 2020-04-10 11:00:14 +08:00
cakoyo
62b087a42e Merge pull request #155 from tsao-chi-fork/1.15.2-patch-2
Optimizations for network
2020-04-09 18:02:45 +07:00
ㄗㄠˋ ㄑㄧˊ
82eb6f16e8 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
6c39a59ae Use entity.dead instead of entity.die()
2020-04-08 15:45:23 +08:00
ㄗㄠˋ ㄑㄧˊ
fad722d038 Merge pull request #154 from tsao-chi-fork/1.15.2-patch-1
Async pathfinder
2020-04-08 15:42:55 +08:00
ㄗㄠˋ ㄑㄧˊ
1729bd7448 fix 2020-04-08 15:42:26 +08:00
Joseph Robinson
2d80430845 Update SECURITY.md 2020-04-05 17:52:05 -07:00
Joseph Robinson
da87117ef9 Update SECURITY.md 2020-04-05 17:46:35 -07:00
ㄗㄠˋ ㄑㄧˊ
72f90a19ca fix 2020-04-05 15:22:13 +08:00
ㄗㄠˋ ㄑㄧˊ
dc062e6862 Optimizations for network 2020-04-05 15:00:30 +08:00
ㄗㄠˋ ㄑㄧˊ
8d3f4c10bd Async Sending packets 2020-04-05 14:39:14 +08:00
ㄗㄠˋ ㄑㄧˊ
616211e7cc cleanup 2020-04-05 14:19:51 +08:00
ㄗㄠˋ ㄑㄧˊ
a225ac6aa2 Async pathfinder 2020-04-05 13:07:17 +08:00
ㄗㄠˋ ㄑㄧˊ
276fb78565 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
2c37d2ebe Restore accidently reverted item in water fix
2020-04-04 15:55:16 +08:00
ㄗㄠˋ ㄑㄧˊ
c54ba6329c Merge pull request #151 from tsao-chi-fork/tsao-chi-patch-2
paperclip.sh: remove unnecessary lines and correctly fail
2020-04-03 16:59:31 +08:00
cakoyo
52155ff022 Merge pull request #148 from tsao-chi-fork/1.15.2-patch-1
fix typo
2020-04-03 15:50:36 +07:00
cakoyo
74a9ae3c0f Merge pull request #150 from tsao-chi-fork/fix-url
fix url
2020-04-03 15:45:33 +07:00
ㄗㄠˋ ㄑㄧˊ
a63a13fcf4 paperclip.sh: remove unnecessary lines 2020-04-03 16:35:15 +08:00
ㄗㄠˋ ㄑㄧˊ
5e7342bed3 fix typo 2020-04-03 16:23:57 +08:00
ㄗㄠˋ ㄑㄧˊ
8997c00356 remove Circle CI 2020-04-03 16:20:36 +08:00
ㄗㄠˋ ㄑㄧˊ
55da64b3c4 fix url 2020-04-03 16:19:52 +08:00
Joseph Robinson
3c37c5e9fc Merge pull request #147 from tsao-chi-fork/1.15.2-patch-1
Server Config
2020-04-03 00:27:40 -07:00
ㄗㄠˋ ㄑㄧˊ
7421223d32 Server Config 2020-04-03 15:18:55 +08:00
Joseph Robinson
25baf8af64 Merge pull request #145 from tsao-chi-fork/1.15.2-patch-1
Updated Upstream (Paper)
2020-04-02 23:28:14 -07:00
ㄗㄠˋ ㄑㄧˊ
19edc4fde1 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
cfaf32cf6 Dead Player's shouldn't be able to move
16287d01e Don't tick dead players
e4d10a6d6 Updated Upstream (Bukkit/CraftBukkit)
c867045d3 And that's why hand editing patch files in nano is risky.... make it compile
c2d7876a5 Improve Entities in water activation immunity and let items always move
2020-04-03 09:06:41 +08:00
Joseph Robinson
ac7fe2301e Merge pull request #141 from tsao-chi-fork/patch-1
remove circleci
2020-04-02 10:22:01 -07:00
Joseph Robinson
5ce858a3e9 Merge pull request #144 from tsao-chi-fork/1.15.2-patch-2
Updated Upstream (Paper)
2020-04-02 01:00:51 -07:00
ㄗㄠˋ ㄑㄧˊ
054d4f8f97 Updated Upstream (Paper)
Upstream has released updates that appears to apply and compile correctly

Paper Changes:
1dc7c308a Optimize Collision Chunk lookup and avoid loading far chunks
d5c6dbee5 Prevent Double PlayerChunkMap adds crashing server
a2a9ffe3b Fix issues with Activation Range causing large chunk lookups.
017297cdb Improve entity.getCurrentChunk() and use it for entity.isChunkLoaded()
52cf89060 Remove some old removed 1.14 patches that are never going to be needed (fixed/already applied)
2020-04-02 15:56:34 +08:00
ㄗㄠˋ ㄑㄧˊ
898788406f Update README.md 2020-04-02 15:26:12 +08:00
Joseph Robinson
aa9af6f41f Create SECURITY.md 2020-04-02 00:23:16 -07:00
ㄗㄠˋ ㄑㄧˊ
5e5720b0f4 remove circleci 2020-04-02 14:56:32 +08:00
Joseph Robinson
8284b9471f Merge pull request #133 from tsao-chi-fork/1.15.2-patch-2
Add Github Actions
2020-04-01 23:40:03 -07:00
Joseph Robinson
66d6565fbe Merge pull request #139 from tsao-chi-fork/1.15.2-patch-1
Disable Snooper
2020-04-01 23:07:25 -07:00
ㄗㄠˋ ㄑㄧˊ
8d58bd05c0 Disable Snooper 2020-04-02 14:03:43 +08:00
Joseph Robinson
2a35b21972 Added gradle to gitignore 2020-04-01 21:54:45 -07:00
Joseph Robinson
2e00ec2f28 Merge pull request #138 from tsao-chi-fork/1.15.2-patch-1
Remove method profiler callers
2020-04-01 21:42:03 -07:00
ㄗㄠˋ ㄑㄧˊ
6d1c80f9e6 Remove method profiler callers 2020-04-02 12:31:20 +08:00
ㄗㄠˋ ㄑㄧˊ
d4f86e6321 rebuild patches 2020-04-02 12:28:47 +08:00
Joseph Robinson
bfa1dd14bd Merge pull request #137 from tsao-chi-fork/1.15.2-patch-6
Don't trigger Lootable Refresh for non player interaction
2020-04-01 21:09:03 -07:00
Joseph Robinson
20eef225e9 Merge pull request #135 from tsao-chi-fork/1.15.2-patch-4
never drop items on command "/give"
2020-04-01 21:08:42 -07:00
Joseph Robinson
632eb0a7dc Merge pull request #134 from tsao-chi-fork/1.15.2-patch-3
Avoid double I/O operation on load player file
2020-04-01 21:08:30 -07:00
Joseph Robinson
9983eb9873 Merge pull request #132 from tsao-chi-fork/1.15.2-patch-1
Save json list async
2020-04-01 21:06:33 -07:00
Joseph Robinson
8a7925d89b Merge pull request #136 from tsao-chi-fork/1.15.2-patch-5
update build instructions
2020-04-01 21:05:09 -07:00
ㄗㄠˋ ㄑㄧˊ
31f4a48344 Don't trigger Lootable Refresh for non player interaction 2020-04-02 11:45:08 +08:00
ㄗㄠˋ ㄑㄧˊ
0e7fd6cb74 update build instructions 2020-04-02 11:40:19 +08:00
ㄗㄠˋ ㄑㄧˊ
38a51d1eda update build instructions 2020-04-02 11:39:07 +08:00
ㄗㄠˋ ㄑㄧˊ
f58756b1e3 never drop items on command "/give" 2020-04-02 11:35:44 +08:00
ㄗㄠˋ ㄑㄧˊ
18f159f4b0 Avoid double I/O operation on load player file 2020-04-02 11:29:23 +08:00
ㄗㄠˋ ㄑㄧˊ
0694ba0207 Add Github Actions 2020-04-02 11:24:45 +08:00
ㄗㄠˋ ㄑㄧˊ
9bd12e76fa Save json list async 2020-04-02 11:16:46 +08:00
Joseph Robinson
4d99eb3486 Updated gradle 2020-04-01 11:43:38 -07:00
Joseph Robinson
a491c9f8c2 Updated Gradle 2020-04-01 11:28:42 -07:00
Joseph Robinson
922d0f6de7 Formatted PATCHES.md 2020-04-01 11:21:11 -07:00
Joseph Robinson
bc6c89df9c Added header to license 2020-04-01 11:17:50 -07:00
Joseph Robinson
bb4ec8ea2d Added gradle 2020-04-01 11:16:46 -07:00
Joseph Robinson
75527e3716 added project file and eclipse prefs 2020-04-01 11:15:06 -07:00
Joseph Robinson
6fece498fb Merge pull request #131 from tsao-chi-fork/1.15.2-patch-1
convert to patches
2020-04-01 10:57:10 -07:00
ㄗㄠˋ ㄑㄧˊ
e349c84177 patches doc 2020-04-01 18:39:04 +08:00
ㄗㄠˋ ㄑㄧˊ
dd949dfa38 convert to patches 2020-04-01 18:17:33 +08:00
Joseph Robinson
3ee44ec206 Added spigot repo to gradle 2020-03-31 13:24:34 -07:00
Joseph Robinson
a9387a171b Added submodule work/Paper 2020-03-31 12:31:47 -07:00
Joseph Robinson
f22c18755f Removed work/Paper 2020-03-31 12:30:00 -07:00
Joseph Robinson
ad2d0cf8db Update build.sh 2020-03-31 02:55:57 -07:00
Joseph Robinson
40035d52a8 Added another spigotmc repo 2020-03-31 02:41:15 -07:00
Joseph Robinson
20da1f5278 Merge branch '1.15.2' of https://github.com/Akarin-project/Akarin into 1.15.2 2020-03-29 10:40:48 -07:00
Joseph Robinson
c39f1e381d Updated README.md - Linted 2020-03-29 10:40:16 -07:00
Joseph Robinson
66dd469d76 Updated README.md - Linted 2020-03-29 10:39:33 -07:00
Joseph Robinson
f8343a64b2 Fixed distribution error 2020-03-29 10:29:15 -07:00
Joseph Robinson
06fe720dc0 Merge pull request #126 from Akarin-project/master
Updated various dev files from master
2020-03-28 21:54:10 -07:00
Joseph Robinson
8c4adc5eb5 Merge branch 'master' of https://github.com/Akarin-project/Akarin 2020-03-28 21:50:38 -07:00
Joseph Robinson
cbb010a22d Updated API pom.xml for 1.15.2 2020-03-28 21:49:00 -07:00
Joseph Robinson
e479cb0ead Updated pom.xml for 1.15.2 2020-03-28 21:48:01 -07:00
Joseph Robinson
6d31958de3 Update build.gradle 2020-03-28 21:42:46 -07:00
Joseph Robinson
504b0aed9e Updated paper to latest (1.15.2) 2020-03-28 21:41:04 -07:00
Joseph Robinson
7be85efd51 Added gradlebuild.sh 2020-03-28 18:32:01 -07:00
Joseph Robinson
9313f9d557 Updated checksums? 2020-03-28 17:15:39 -07:00
Joseph Robinson
aeec043ef1 removed copy of build.sh 2020-03-28 17:15:27 -07:00
Joseph Robinson
86631090a7 updated gradle 2020-03-28 17:14:17 -07:00
Joseph Robinson
82d21e2156 Update README.md 2020-03-26 17:35:19 -07:00
Joseph Robinson
bd6a6a4af2 Update README.md 2020-03-26 17:29:29 -07:00
Joseph Robinson
f95d397ee1 Update README.md 2020-03-26 17:26:02 -07:00
Joseph Robinson
c47fa0e78c Merge pull request #121 from LegacyGamerHD/patch-5
update the link
2020-03-19 10:36:20 -07:00
LegacyGamerHD
a70eb4415c Update README.md 2020-03-19 18:35:47 +01:00
Joseph Robinson
21713af0a0 Update README.md 2020-03-19 10:33:39 -07:00
Joseph Robinson
5bb3faf096 Update README.md 2020-03-18 19:53:43 -07:00
Joseph Robinson
b8e12697cc Merge pull request #118 from tsao-chi/patch-1
Rebrand (fix #109)
2020-03-16 09:16:26 -07:00
ㄗㄠˋ ㄑㄧˊ
0917583727 net.minecraft.server.MinecraftServer: Rebrand 2020-03-16 16:27:28 +08:00
ㄗㄠˋ ㄑㄧˊ
74d7463012 org.bukkit.craftbukkit.CraftServer: Rebrand 2020-03-16 16:25:37 +08:00
Joseph Robinson
c50dd7660f updated gradle to 6.2.2 2020-03-06 22:04:16 -07:00
Joseph Robinson
2e6ed47fc3 Updated build.gradle 2020-03-06 22:02:37 -07:00
Joseph Robinson
ff11917fde Merge pull request #112 from Akarin-project/gradle
Gradle
2020-03-06 22:01:23 -07:00
Joseph Robinson
fb0fb08ca9 Merge pull request #116 from Akarin-project/master
Updated gradle branch with master
2020-03-06 22:01:08 -07:00
Joseph Robinson
d996e03194 Revert "Merge branch 'master' of https://github.com/Akarin-project/Akarin"
This reverts commit d21f1ae0f7.
2020-03-06 21:47:22 -07:00
Joseph Robinson
0fc67cb84b Revert "changes suggested by @liach"
This reverts commit d9c7c27de2.
2020-03-06 21:46:16 -07:00
Joseph Robinson
d9c7c27de2 changes suggested by @liach 2020-03-06 21:35:40 -07:00
Joseph Robinson
d21f1ae0f7 Merge branch 'master' of https://github.com/Akarin-project/Akarin 2020-03-06 21:32:41 -07:00
Joseph Robinson
cfedff9496 Merge pull request #115 from Akarin-project/master
Added new gitignore to gradle branch
2020-03-06 21:31:42 -07:00
Joseph Robinson
8ee8f1125a Merge pull request #113 from Akarin-project/gitignore-update
Update .gitignore
2020-03-06 21:30:08 -07:00
Joseph Robinson
77f5c39f45 Merge pull request #114 from josephworks/master
Updated Gradle to last ver of gradle 5
2020-03-06 14:23:56 -07:00
Joseph Robinson
dcda956eb9 Updated Gradle to last ver of gradle 5 2020-03-06 14:20:47 -07:00
Joseph Robinson
3eae763c37 Update .gitignore 2020-03-06 14:14:20 -07:00
Joseph Robinson
673af6e6ce Merge pull request #111 from josephworks/master
Added Gradle
2020-03-06 14:05:12 -07:00
Joseph Robinson
1773ae99c0 Added Gradle 2020-03-06 14:01:58 -07:00
Joseph Robinson
eedfeffb32 Merge branch 'master' of https://github.com/Akarin-project/Akarin 2020-03-01 13:22:16 -07:00
Joseph Robinson
9b0e0440fa double [] for scripts 2020-03-01 13:19:05 -07:00
Joseph Robinson
c462bfc444 Updated EULA.java 2020-03-01 13:18:10 -07:00
Joseph Robinson
a3e57ec664 Merge pull request #108 from josephworks/master
Update EULA.java
2020-03-01 13:15:44 -07:00
Joseph Robinson
f303f0429a Update EULA.java 2020-03-01 13:15:04 -07:00
Joseph Robinson
9001462a77 Updated donation text 2020-03-01 10:19:18 -07:00
cakoyo
603e6030f5 Merge pull request #105 from WhyDoWeWonder/hacky-build
Workaround to Make Akarin Build
2020-02-17 11:10:50 +07:00
WhyDoWeWonder
1a5e7ff422 Debugging code
Trying to get it to build properly, just some debugging code
2020-02-14 20:04:37 -05:00
WhyDoWeWonder
1e5930ff4f Workaround to Make Project Build
Quick and Dirty hacks to get Akarin to build on the rbuild server.
2020-02-14 19:30:45 -05:00
cakoyo
89d7ca75b2 Merge pull request #100 from Akarin-project/dependabot/maven/io.netty-netty-all-4.1.42.Final
Bump netty-all from 4.1.35.Final-SNAPSHOT to 4.1.42.Final
2020-02-01 06:05:17 +07:00
Mgazul
0c27784fc2 Merge pull request #102 from braddevans/patch-1
fix compile from fresh git clone
2019-12-21 07:26:52 +08:00
Mgazul
0f4d9dbcc6 Merge pull request #103 from braddevans/master
update campfire to the latest 1.14.4 version from craftbukkit
2019-12-21 07:26:29 +08:00
bradd evans
cf9ddb81d4 update ci build 2019-12-20 17:15:16 +00:00
braddevans
51703b3300 fix travis.yml build 2019-12-20 17:10:51 +00:00
bradd evans
5c9567e797 update campfire to the latest 1.14.4 version on craftbukkit
update pom.xml to use a repo with almost every single lib you would ever need since nallar has been down for a year
update maven command to fully skip tests propperly
update work/paper
2019-12-20 16:58:56 +00:00
braddevans
e75ae756d7 fix compile from fresh git clone
fix compile
2019-12-20 14:52:18 +00:00
Mgazul
d1569d7502 Merge pull request #101 from LegacyGamerHD/patch-2
fix circleci and travis starting
2019-11-29 13:42:29 +08:00
LegacyGamerHD
e39a36bd42 Update .travis.yml 2019-11-22 23:41:07 -08:00
LegacyGamerHD
f726349f27 fix travis 2019-11-22 23:31:25 -08:00
LegacyGamerHD
f13789ac6a fix circleci 2019-11-22 23:29:23 -08:00
Mgazul
80713fe0ac api 2019-11-22 23:06:18 +08:00
Mgazul
e24a0066a3 1.14.4 2019-11-22 22:45:47 +08:00
Mgazul
c08e6988a0 add Paper-1.14.4 2019-11-22 20:24:58 +08:00
Mgazul
e08e69fba1 Delete .gitmodules 2019-11-22 20:19:05 +08:00
Mgazul
e7bd70d7cf Delete Paper 2019-11-22 20:15:38 +08:00
dependabot[bot]
dc96116b8e Bump netty-all from 4.1.35.Final-SNAPSHOT to 4.1.42.Final
Bumps [netty-all](https://github.com/netty/netty) from 4.1.35.Final-SNAPSHOT to 4.1.42.Final.
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](https://github.com/netty/netty/commits/netty-4.1.42.Final)

Signed-off-by: dependabot[bot] <support@github.com>
2019-11-02 10:06:16 +00:00
2237 changed files with 5493 additions and 306742 deletions

122
.gitignore vendored
View File

@@ -1,57 +1,85 @@
# Eclipse stuff
.classpath
.project
# Akarin
Akarin-Server
Akarin-API
mc-dev
testserver
run
*.jar
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Eclipse
.settings/
.factorypath
.externalToolBuilders/
.project
# netbeans
nbproject/
nbactions.xml
# we use maven!
build.xml
# maven
target/
dependency-reduced-pom.xml
# vim
.*.sw[a-p]
# various other potential build files
build/
bin/
dist/
manifest.mf
work/1.*
work/Minecraft
work/BuildData
work/Bukkit
work/CraftBukkit
work/Paperclip
work/Spigot
work/Spigot-Server
work/Spigot-API
work/*.jar
work/test-server
# Mac filesystem dust
.DS_Store/
.DS_Store
# intellij
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
.idea
out/
# Linux temp files
*~
# Maven
target/
# other stuff
run/
# Gradle
gradle-app.setting
.gradletasknamecache
.gradle
build/
*/build/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs
hs_err_pid*
replay_pid*
# Paper/Akarin specific
paper-api/
paper-server/
.paper-nms/
.paper-nms.at
.paper-nms.mixin
.paper-nms.plugin
.paper-nms.remapped
.paper-nms.remapped.notch
.paper-nms.remapped.spigot
.paper-nms.remapped.yarn
.paper-nms.remapped.mojang
.paper-nms.remapped.obf
.paper-nms.remapped.srg
.paper-nms.remapped.tsrg
.paper-nms.remapped.tiny
.paper-nms.remapped.csrg
.paper-nms.remapped.proguard
.paper-nms.remapped.retroguard
.paper-nms.remapped.specialsource
.paper-nms.remapped.asm
.paper-nms.remapped.fernflower
.paper-nms.remapped.cfr
.paper-nms.remapped.procyon
.paper-nms.remapped.quiltflower
# OS specific
.DS_Store
Thumbs.db
akarin-*.jar

6
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "work/Paper"]
path = work/Paper
url = https://github.com/PaperMC/Paper.git
[submodule "Tuinity"]
path = Tuinity
url = https://github.com/Spottedleaf/Tuinity
branch = master

17
.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>akarin-parent</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

33
Jenkinsfile vendored
View File

@@ -1,24 +1,47 @@
//@Library('forge-shared-library') _
pipeline {
agent any
environment {
DISCORD_WEBHOOK_URL = credentials('3e8105ad-8e03-4550-bc66-a27438ec6fb3')
CHANGES = getChanges(currentBuild)
ARTIFACT = "http://ci.josephworks.net/job/Akarin/job/1.16.5/${currentBuild.id}/artifact/target/akarin-1.16.5-launcher.jar"
}
stages {
stage('Init Submodules') {
stage('Initialize') {
steps {
sh 'git submodule update --init --recursive'
sh '''git submodule update --init --recursive'''
}
}
stage('Build') {
steps {
sh 'bash ./scripts/build.sh'
sh 'bash ./scripts/inst.sh --setup --fast'
sh './akarin jar'
}
}
stage('Archive') {
steps {
archiveArtifacts(artifacts: '*.jar', fingerprint: true)
archiveArtifacts(artifacts: 'target/*.jar', fingerprint: true)
}
}
stage('Report') {
steps {
discordSend(
description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n\n**Changes:**\n```$CHANGES```\n**Artifacts:**\n - $ARTIFACT",
footer: "JosephWorks Jenkins Server",
link: env.BUILD_URL,
result: currentBuild.currentResult,
title: "${env.JOB_NAME} #${currentBuild.id}",
webhookURL: "$DISCORD_WEBHOOK_URL"
)
}
}
}
post {
always {
cleanWs()
}
}
}

View File

@@ -1,3 +1,5 @@
# License
Akarin inherits its licensing from upstream projects.
As such, Akarin is licensed under the
@@ -17,4 +19,5 @@ should submit a Pull Request to this project and add their name.
```text
Sotr <kira@kira.moe>
MatrixTunnel <https://github.com/MatrixTunnel>
JosephWorks <https://github.com/josephworks>
```

29
NOTES.md Normal file
View File

@@ -0,0 +1,29 @@
# Development Notes
## Patching System
Modern Paper forks (including Purpur) use a file-based patching system:
### API Patches
- Located in `purpur-api/paper-patches/files/`
- Contains patches for API source files
### Server Patches
1. Minecraft Patches (`purpur-server/minecraft-patches/`)
- `features/` - Feature-specific patches
- `sources/` - Direct source code modifications
2. Paper Patches (`purpur-server/paper-patches/`)
- `features/` - Feature-specific patches
- `files/` - Source code modifications
### Historical Patches
The `patches/` directory contains only historical patches from older versions:
- 1-20-6 (dropped)
- 1-21-1 (dropped)
- 1-21-3 (dropped)
- Some unapplied patches
## Reference
- Purpur reference implementation can be found at `~/purpur-reference`
- Clean Purpur clone at `~/purpur-clean`
- Version: 1.21.4

183
PATCHES.md Normal file
View File

@@ -0,0 +1,183 @@
# Contributing to Akarin
## Understanding Patches
Patches to Akarin are very simple, but center around the directories 'Akarin-API' and 'Akarin-Server'
Assuming you already have forked the repository:
1. Pull the latest changes from the main repository
2. Type `./akarin patch` in git bash to apply the changes from upstream
3. cd into `Akarin-Server` for server changes, and `Akarin-API` for API changes
These directories aren't git repositories in the traditional sense:
- Every single commit in Akarin-Server/API is a patch.
- 'origin/master' points to a directory similar to Akarin-Server/API but for Paper
- Typing `git status` should show that we are 10 or 11 commits ahead of master, meaning we have 10 or 11 patches that Paper and Spigot don't
- If it says something like `212 commits ahead, 207 commits behind`, then type `git fetch` to update spigot/paper
## Adding Patches
Adding patches to Paper is very simple:
1. Modify `Akarin-Server` and/or `Akarin-API` with the appropriate changes
2. Type `git add .` to add your changes
3. Run `git commit` with the desired patch message
4. Run `./akarin rebuild` in the main directory to convert your commit into a new patch
5. PR your patches back to this repository
Your commit will be converted into a patch that you can then PR into Paper
## Help! I can't find the file I'm looking for
By default, Paper (and upstream) only import files that we make changes to.
If you would like to make changes to a file that isn't present in Paper-Server's source directory, you
just need to add it to our import script to be ran during the patch process.
1. Save (rebuild) any patches you are in the middle of working on!
2. Identify the names of the files you want to import.
- A complete list of all possible file names can be found at ```./work/Minecraft/$MCVER/net/minecraft/server```
3. Open the file at `./scripts/importmcdev.sh` and add the name of your file to the script.
4. Re-patch the server `./akarin patch`
5. Edit away!
This change is temporary! DO NOT COMMIT CHANGES TO THIS FILE!
Once you have made your changes to the new file, and rebuilt patches, you may undo your changes to importmcdev.sh
Any file modified in a patch file gets automatically imported, so you only need this temporarily
to import it to create the first patch.
To undo your changes to the file, type `git checkout scripts/importmcdev.sh`
## Modifying Patches
Modifying previous patches is a bit more complex:
#### Manual method
In case you need something more complex or want more control, this step-by-step instruction does
exactly what the above slightly automated system does.
1. If you have changes you are working on type `git stash` to store them for later.
- Later you can type `git stash pop` to get them back.
2. Type `git rebase -i upstream/upstream`
- It should show something like [this](https://gist.github.com/zachbr/21e92993cb99f62ffd7905d7b02f3159).
3. Replace `pick` with `edit` for the commit/patch you want to modify, and "save" the changes.
- Only do this for one commit at a time.
4. Make the changes you want to make to the patch.
5. Type `git add .` to add your changes.
6. Type `git commit --amend` to commit.
- **MAKE SURE TO ADD `--amend`** or else a new patch will be created.
- You can also modify the commit message here.
7. Type `git rebase --continue` to finish rebasing.
8. Type `./akarin rebuild` in the main directory.
- This will modify the appropriate patches based on your commits.
9. PR your modifications back to this project.
### Method 2 (sometimes easier)
If you are simply editing a more recent commit or your change is small, simply making the change at HEAD and then moving the commit after you have tested it may be easier.
This method has the benefit of being able to compile to test your change without messing with your API HEAD.
1. Make your change while at HEAD
2. Make a temporary commit. You don't need to make a message for this.
3. Type `git rebase -i upstream/upstream`, move (cut) your temporary commit and move it under the line of the patch you wish to modify.
4. Change the `pick` with `f` (fixup) or `s` (squash) if you need to edit the commit message
5. Type `./akarin rebuild` in the main directory
- This will modify the appropriate patches based on your commits
6. PR your modifications to github
## Formatting
All modifications to non-Paper files should be marked
- Multi line changes start with `// Akarin start` and end with `// Akarin end`
- You can put a messages with a change if it isn't obvious, like this: `// Akarin start - reason`
- Should generally be about the reason the change was made, what it was before, or what the change is
- Multi-line messages should start with `// Akarin start` and use `/* Multi line message here */` for the message itself
- Single line changes should have `// Akarin` or `// Akarin - reason`
- For example:
````java
entity.getWorld().dontbeStupid(); // Akarin - was beStupid() which is bad
entity.getFriends().forEach(Entity::explode());
entity.a();
entity.b();
// Akarin start - use plugin-set spawn
// entity.getWorld().explode(entity.getWorld().getSpawn());
Location spawnLocation = ((CraftWorld)entity.getWorld()).getSpawnLocation();
entity.getWorld().explode(new BlockPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ()));
// Akarin end
````
- We generally follow usual java style, or what is programmed into most IDEs and formatters by default
- This is also known as oracle style
- It is fine to go over 80 lines as long as it doesn't hurt readability
- There are exceptions, especially in Spigot-related files
- When in doubt, use the same style as the surrounding code
## Patch Notes
When submitting patches to Akarin, we may ask you to add notes to the patch header.
While we do not require it for all changes, you should add patch notes when the changes you're making are technical or complex.
It is very likely that your patch will remain long after we've all forgotten about the details of your PR, patch notes will help
us maintain it without having to dig back through GitHub history looking for your PR.
These notes should express the intent of your patch, as well as any pertinent technical details we should keep in mind long-term.
Ultimately, they exist to make it easier for us to maintain the patch across major version changes.
If you add a long message to your commit in the Akarin-Server/API repos, the rebuildPatches command will handle these patch
notes automatically as part of generating the patch file. Otherwise if you're careful they can be added by hand (though you should be careful when doing this, and run it through a patch and rebuild cycle once or twice).
```patch
From 02abc033533f70ef3165a97bfda3f5c2fa58633a Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 15 Oct 2017 00:29:07 +0100
Subject: [PATCH] revert serverside behavior of keepalives
This patch intends to bump up the time that a client has to reply to the
server back to 30 seconds as per pre 1.12.2, which allowed clients
more than enough time to reply potentially allowing them to be less
tempermental due to lag spikes on the network thread, e.g. that caused
by plugins that are interacting with netty.
We also add a system property to allow people to tweak how long the server
will wait for a reply. There is a compromise here between lower and higher
values, lower values will mean that dead connections can be closed sooner,
whereas higher values will make this less sensitive to issues such as spikes
from networking or during connections flood of chunk packets on slower clients,
at the cost of dead connections being kept open for longer.
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index a92bf8967..d0ab87d0f 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
```
## Obfuscation Helpers
In an effort to make future updates easier on ourselves, Akarin tries to use obfuscation helpers whenever possible. The purpose of these helpers is to make the code more readable. These helpers should be be made as easy to inline as possible by the JVM whenever possible.
An obfuscation helper to get an obfuscated field may be as simple as something like this:
```java
public final int getStuckArrows() { return this.bY(); } // Akarin - OBFHELPER
```
Or it may be as complex as forwarding an entire method so that it can be overriden later:
```java
public boolean be() {
// Akarin start - OBFHELPER
return this.pushedByWater();
}
public boolean pushedByWater() {
// Akarin end
return true;
}
```
While they may not always be done in exactly the same way each time, the general goal is always to improve readability and maintainability, so use your best judgement.

View File

@@ -1,61 +1,66 @@
# <img src="https://i.loli.net/2018/05/17/5afd869c443ef.png" alt="Akarin Face" align="right">Akarin
[![Powered by](https://img.shields.io/badge/Powered_by-Akarin_project-ee6aa7.svg?style=flat)](https://akarin.io)
<img src="https://i.loli.net/2018/05/17/5afd869c443ef.png" alt="Akarin Face" align="right">
<div align="center">
<h1>Akarin</h1>
<h3>Formerly known as torch, A powerful Minecraft Server Software</h3>
<h4>Akarin is **under heavy development** and contributions are welcome!</h4>
[![Powered by](https://img.shields.io/badge/Powered_by-Akarin_project-ee6aa7.svg?style=flat)](https://akarin.app/)
[![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://discord.gg/fw2pJAj)
[![bStats](https://img.shields.io/badge/bStats-Torch-0099ff.svg?style=flat)](https://bstats.org/plugin/bukkit/Torch)
![Jenkins](https://img.shields.io/jenkins/build?jobUrl=http%3A%2F%2Fci.josephworks.net%2Fjob%2FAkarin%2Fjob%2Fver%25252F1.13.2%2F)
[![Patreon](https://img.shields.io/badge/Patreon-donate_us-yellow.svg?style=flat)](https://www.patreon.com/akarinproject)
Akarin is currently **under heavy development** and contributions are welcome!
![Jenkins](https://img.shields.io/jenkins/build?jobUrl=http%3A%2F%2Fci.josephworks.net%2Fjob%2FAkarin%2Fjob%2Fver%25252F1.16.5%2F)
[![Patreon](https://img.shields.io/badge/Patreon-Donate-yellow.svg?style=flat)](https://www.patreon.com/akarinproject)
</div>
Introduction
---
> Akarin is a powerful server software from the 'new dimension', formerly known as Torch.
As a [Paper](https://github.com/PaperMC/Paper) fork, it should support almost all plugins that work on [Spigot](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/browse).
Our project has a few key goals:
* **Open Access** - Make more game mechanics configurable.
* **Bedrock** - Make the server more safe and stable.
* **Fast** - Simplify the logic and implement multi-threaded computing.
### note: this is not a mc bedrock software
*Issues and Pull Requests will be labeled accordingly*
* **Open Access** - Make more game mechanics configurable.
* **Compatible** - Support all plugins that work on [Spigot](https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/browse).
* **Stability** - Make the server more safe and stable.
* **Fast** - Simplify the logic and implement multi-threaded computing.
Get Akarin
---
### Download
#### Recommended
+ [**JosephWorks Jenkins**](http://ci.josephworks.net/job/Akarin)
+ [**JosephWorks Jenkins**](http://ci.josephworks.net/job/Akarin/)
*Open an [Issue](https://github.com/Akarin-project/Akarin/issues) or a [Pull Request](https://github.com/Akarin-project/Akarin/pulls) if you want to add your website here*
### Build
#### Requirements
* Java (JDK) 8 or above
* Maven
#### Compile
```sh
./scripts/inst.sh --setup --fast
```
**Notes**
* You must use `--setup` at least once to deploy necessary dependencies otherwise some imports cannot be organized.
* For non-modified projects, it is recommended to add the `--fast` option to skip any tests.
* If your machine has insufficient memory, you may want to add the `--remote` option to avoid decompiling locally.
```sh
git submodule update --init --recursive
./akarin jar
```
Demo Servers
---
* [Fair Server](https://fairserver.ru)
* [LoyaltyMC](https://minecraft-mp.com/server-s212077)
* ~~`demo.akarin.io` (official)~~
*Open an [Issue](https://github.com/Akarin-project/Akarin/issues) or a [Pull Request](https://github.com/Akarin-project/Akarin/pulls) if you want to add your website here*
* [Wolfx](https://wolfx.jp/)
* [Pioneercraft](https://www.pioneercraft.pw/)
*Open an [Issue](https://github.com/Akarin-project/Akarin/issues) or a [Pull Request](https://github.com/Akarin-project/Akarin/pulls) if you want to add your server here*
Contributing
---
* You can checkout the `src` folder to see more. Please follow the patch style to do any change, so we are able to update between different Minecraft versions.
* Akarin uses patches to handle code changes.
* Add your name to the [LICENSE](https://github.com/Akarin-project/Akarin/blob/master/LICENSE.md) if you want to publish your code under the [MIT License](https://github.com/Akarin-project/Akarin/blob/master/licenses/MIT.md).
* If you want to join the [Akarin-project](https://github.com/Akarin-project) team, you can [send](mailto://kira@kira.moe) us an email with your experience and necessary information.
* If you want to join the [Akarin-project](https://github.com/Akarin-project) team, welcome to contact us by our [Discord](https://discord.gg/fw2pJAj).
![Akarin project](https://i.loli.net/2018/05/13/5af7fbbfbcddf.png)

25
SUPPORT.md Normal file
View File

@@ -0,0 +1,25 @@
# Support Policy
## Supported Versions
The checked versions below are supported by us.
| Version | Supported | Notes |
| ------- | ------------------ | -------------- |
| 1.16.5 | :white_check_mark: | Latest Build |
| 1.15.2 | :white_check_mark: | Newer Build |
| 1.14.4 | :x: | No Support |
| 1.13.2 | :x: | No Support |
| 1.12.2 | :white_check_mark: | Newer Build |
Latest Build - You need the latest build in order to be provided support.
Newer Build - Up to 20 commits behind or 5 jenkins builds.
No Support - You will be prompted to upgrade to 1.15.2.
LTS Build only - Provided in the releases tab on GitHub.
## Reporting an Issue
Have a problem, feel free to [create an issue](https://github.com/Akarin-project/Akarin/issues) or [ask us on discord](https://discord.gg/dX8MMvP)!

1
Tuinity Submodule

Submodule Tuinity added at 5b6d8beec8

204
akarin Executable file
View File

@@ -0,0 +1,204 @@
#!/usr/bin/env bash
# Akarin Build Script
############################################################################
# Multicore building #
# By JosephWorks #
# -------------------------------------------------------------------------#
# To use multicore building, use "$mvncmd" instead of "maven" #
# 20-50% speed improvement is quite common. #
############################################################################
# Exit immediately if a command exits with a non-zero status
set -e
source "./scripts/functions.sh"
function setupUpstreamAndPatch {
basedir
if [ "$1" == "--updatePaper" ]; then
$scriptdir/updateUpstream.sh "$basedir" 1 || exit 1
else
if [ "$1" != "--skipPaper" ]; then
$scriptdir/updateUpstream.sh "$basedir" 0 || exit 1 # not update submodule
fi
fi
$scriptdir/applyPatches.sh "$basedir" || exit 1
}
failed=0
case "$1" in
"r" | "rb" | "rbp" | "rebuild")
(
set -e
basedir
$scriptdir/importSources.sh "$basedir" || exit 1
$scriptdir/rebuildPatches.sh "$basedir" || exit 1
) || failed=1
;;
"a" | "p" | "patch" | "apply")
(
set -e
setupUpstreamAndPatch $2 || exit 1
) || failed=1
;;
"b" | "bu" | "build" | "install")
(
set -e
setupUpstreamAndPatch $2 || exit 1
basedir
$mvncmd -N install || exit 1
cd ${FORK_NAME}-API
$mvncmd -e clean install && (cd ../Tuinity/Paper/Paper-MojangAPI && $mvncmd -e clean install) && cd ../${FORK_NAME}-Server && $mvncmd -e clean install || exit 1
) || failed=1
;;
"j" | "launcher" | "jar" | "paperclip")
(
setupUpstreamAndPatch $2 || exit 1
basedir
$mvncmd -N install surefire-report:report
cd ${FORK_NAME}-API
$mvncmd -e clean install && (cd ../Tuinity/Paper/Paper-MojangAPI && $mvncmd -e clean install) && cd ../${FORK_NAME}-Server && $mvncmd -e clean install surefire-report:report
basedir
$scriptdir/installLauncher.sh "$basedir"
) || failed=1
;;
"d" | "de" | "deploy")
(
basedir
$mvncmd -N install
cd ${FORK_NAME}-API
$mvncmd clean deploy && (cd ../Tuinity/Paper/Paper-MojangAPI && $mvncmd -e clean install) && cd ../${FORK_NAME}-Server && $mvncmd clean install
)
;;
"u" | "up" | "upstream" | "update")
(
basedir
$scriptdir/updateUpstream.sh "$basedir" 1
)
;;
"r" | "root")
basedir
;;
"a" | "api")
cd "$basedir/Akarin-API"
;;
"s" | "server")
cd "$basedir/Akarin-Server"
;;
"c" | "clean")
rm -rf Akarin-API
rm -rf Akarin-Server
rm -rf Paper
echo "Cleaned build files"
;;
"e" | "edit")
case "$2" in
"s" | "server")
export AKARIN_LAST_EDIT="$basedir/Akarin-Server"
cd "$basedir/Akarin-Server"
(
set -e
gitstash
cd "$basedir/Paper/Paper-Server"
$gitcmd fetch --all
# Create the upstream branch in Paper project with current state
$gitcmd checkout master # possibly already in
$gitcmd branch -D upstream || true
$gitcmd branch -f upstream HEAD
cd "$basedir/Akarin-Server"
$gitcmd rebase -i upstream/upstream
gitunstash
)
;;
"a" | "api")
export AKARIN_LAST_EDIT="$basedir/Akarin-API"
cd "$basedir/Akarin-API"
(
set -e
gitstash
cd "$basedir/Paper/Paper-API"
$gitcmd fetch --all
# Create the upstream branch in Paper project with current state
$gitcmd checkout master # possibly already in
$gitcmd branch -D upstream || true
$gitcmd branch -f upstream HEAD
cd "$basedir/Akarin-API"
$gitcmd rebase -i upstream/upstream
gitunstash
)
;;
"c" | "continue")
cd "$AKARIN_LAST_EDIT"
unset AKARIN_LAST_EDIT
(
set -e
$gitcmd add .
$gitcmd commit --amend
$gitcmd rebase --continue
basedir
$scriptdir/rebuildPatches.sh "$basedir"
)
;;
*)
echo "You must edit either the api or server."
;;
esac
;;
"setup")
if [[ -f ~/.bashrc ]] ; then
NAME="akarin"
if [[ ! -z "${2+x}" ]] ; then
NAME="$2"
fi
(grep "alias $NAME=" ~/.bashrc > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" ~/.bashrc) || (echo "alias $NAME='. $SOURCE'" >> ~/.bashrc)
alias "$NAME=. $SOURCE"
echo "You can now just type '$NAME' at any time to access the akarin tool."
fi
;;
*)
echo "Akarin build tool command. This provides a variety of commands to build and manage the Akarin build"
echo "environment. For all of the functionality of this command to be available, you must first run the"
echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup."
echo ""
echo " Normal commands:"
echo " * r, rebuild | Rebuild patches, can be called from anywhere."
echo " * p, patch | Apply all patches to top of Paper without building it. Can be run from anywhere."
echo " * u, update | Update and patch the Paper submodule. Can be run from anywhere."
echo " * b, build | Build the projects, including the API and the Server. Can be ran anywhere."
echo " * j, jar | Build the projects and build the launcher jar. Can be ran anywhere."
echo " * d, deploy | Build the projects and deploy through Maven. Can be ran anywhere."
echo ""
echo " These commands require the setup command before use:"
echo " * r, root | Change directory to the root of the project."
echo " * a. api | Move to the Akarin-API directory."
echo " * s, server | Move to the Akarin-Server directory."
echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\""
echo " | respectively to edit the correct project. Use the argument \"continue\" after"
echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere."
echo ""
echo " * setup | Add an alias to .bashrc to allow full functionality of this script. Run as:"
echo " | . ./akarin setup"
echo " | After you run this command you'll be able to just run 'akarin' from anywhere."
echo " | The default name for the resulting alias is 'akarin', you can give an argument to override"
echo " | this default, such as:"
echo " | . ./akarin setup example"
echo " | Which will allow you to run 'example' instead."
;;
esac
unset RCPATH
unset SOURCE
unset basedir
unset -f color
unset -f colorend
unset -f gitstash
unset -f gitunstash
if [[ "$failed" == "1" ]]; then
unset failed
false
else
unset failed
true
fi

View File

@@ -1,245 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>akarin-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-parent</artifactId>
<version>dev-SNAPSHOT</version>
</parent>
<name>Akarin-API</name>
<url>https://github.com/Akarin-project/Akarin</url>
<description>An enhanced plugin API for Minecraft servers.</description>
<properties>
<!-- <skipTests>true</skipTests> Paper - This [was] not going to end well -->
<!-- Paper - #Logic -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<!--
If you are a plugin developer, please use https://hub.spigotmc.org/nexus/content/repositories/snapshots/
as your repository URL. This will ensure only Bukkit / Spigot-API are pulled from our Maven repository.
Please see https://www.spigotmc.org/go/maven for more information.
-->
<repository>
<id>spigotmc-public</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spigotmc-public</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
<scope>compile</scope>
</dependency>
<!-- bundled with Minecraft, shouldn't ever change -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>compile</scope>
</dependency>
<!-- bundled with Minecraft, should be kept in sync -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<scope>compile</scope>
</dependency>
<!-- bundled with Minecraft, should be kept in sync -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<version>1.13-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
<scope>compile</scope>
</dependency>
<!-- annotations -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
<version>17.0.0</version>
<scope>provided</scope>
</dependency>
<!-- Paper - Add SLF4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<!-- testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
<version>7.1</version>
<scope>test</scope>
</dependency>
<!-- ASM -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>7.1</version>
</dependency>
<!-- Akarin -->
<dependency>
<groupId>com.koloboke</groupId>
<artifactId>koloboke-api-jdk8</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.koloboke</groupId>
<artifactId>koloboke-impl-jdk8</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<dependencies>
<!-- we need our custom version as it fixes some bugs on case sensitive file systems -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.5-spigotmc</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.bukkit</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
<!-- when downloading via Maven we can pull depends individually -->
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>development</id>
<properties>
<skipTests>false</skipTests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.17</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java17</artifactId>
<version>1.0</version>
</signature>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -1,84 +0,0 @@
package co.aikar.timings;
import static co.aikar.timings.TimingsManager.*;
import org.jetbrains.annotations.NotNull;
public class FullServerTickHandler extends TimingHandler {
private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null);
final TimingData minuteData;
double avgFreeMemory = -1D;
double avgUsedMemory = -1D;
FullServerTickHandler() {
super(IDENTITY);
minuteData = new TimingData(id);
TIMING_MAP.put(IDENTITY, this);
}
@NotNull
@Override
public Timing startTiming() {
if (TimingsManager.needsFullReset) {
TimingsManager.resetTimings();
} else if (TimingsManager.needsRecheckEnabled) {
TimingsManager.recheckEnabled();
}
return super.startTiming();
}
@Override
public void stopTiming() {
super.stopTiming();
if (!isEnabled()) {
return;
}
if (TimingHistory.timedTicks % 20 == 0) {
final Runtime runtime = Runtime.getRuntime();
double usedMemory = runtime.totalMemory() - runtime.freeMemory();
double freeMemory = runtime.maxMemory() - usedMemory;
if (this.avgFreeMemory == -1) {
this.avgFreeMemory = freeMemory;
} else {
this.avgFreeMemory = (this.avgFreeMemory * (59 / 60D)) + (freeMemory * (1 / 60D));
}
if (this.avgUsedMemory == -1) {
this.avgUsedMemory = usedMemory;
} else {
this.avgUsedMemory = (this.avgUsedMemory * (59 / 60D)) + (usedMemory * (1 / 60D));
}
}
long start = System.nanoTime();
TimingsManager.tick();
long diff = System.nanoTime() - start;
TIMINGS_TICK.addDiff(diff, null);
// addDiff for TIMINGS_TICK incremented this, bring it back down to 1 per tick.
record.setCurTickCount(record.getCurTickCount()-1);
minuteData.setCurTickTotal(record.getCurTickTotal());
minuteData.setCurTickCount(1);
boolean violated = isViolated();
minuteData.processTick(violated);
TIMINGS_TICK.processTick(violated);
processTick(violated);
if (TimingHistory.timedTicks % 1200 == 0) {
MINUTE_REPORTS.add(new TimingHistory.MinuteReport());
TimingHistory.resetTicks(false);
minuteData.reset();
}
if (TimingHistory.timedTicks % Timings.getHistoryInterval() == 0) {
TimingsManager.HISTORY.add(new TimingHistory());
TimingsManager.resetTimings();
}
TimingsExport.reportTimings();
}
boolean isViolated() {
return record.getCurTickTotal() > 50000000;
}
}

View File

@@ -1,68 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class NullTimingHandler implements Timing {
public static final Timing NULL = new NullTimingHandler();
@NotNull
@Override
public Timing startTiming() {
return this;
}
@Override
public void stopTiming() {
}
@NotNull
@Override
public Timing startTimingIfSync() {
return this;
}
@Override
public void stopTimingIfSync() {
}
@Override
public void abort() {
}
@Nullable
@Override
public TimingHandler getTimingHandler() {
return null;
}
@Override
public void close() {
}
}

View File

@@ -1,17 +0,0 @@
package co.aikar.timings;
public class ThreadAssertion {
private static boolean mainThread;
public static boolean is() {
return mainThread;
}
static void start() {
mainThread = true;
}
public static void close() {
mainThread = false;
}
}

View File

@@ -1,83 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TimedEventExecutor implements EventExecutor {
private final EventExecutor executor;
private final Timing timings;
/**
* Wraps an event executor and associates a timing handler to it.
*
* @param executor Executor to wrap
* @param plugin Owning plugin
* @param method EventHandler method
* @param eventClass Owning class
*/
public TimedEventExecutor(@NotNull EventExecutor executor, @NotNull Plugin plugin, @Nullable Method method, @NotNull Class<? extends Event> eventClass) {
this.executor = executor;
String id;
if (method == null) {
if (executor.getClass().getEnclosingClass() != null) { // Oh Skript, how we love you
method = executor.getClass().getEnclosingMethod();
}
}
if (method != null) {
id = method.getDeclaringClass().getName();
} else {
id = executor.getClass().getName();
}
final String eventName = eventClass.getSimpleName();
boolean verbose = "BlockPhysicsEvent".equals(eventName);
this.timings = Timings.ofSafe(plugin.getName(), (verbose ? "## " : "") +
"Event: " + id + " (" + eventName + ")", null);
}
@Override
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
if (event.isAsynchronous() || !Timings.timingsEnabled || !Bukkit.isPrimaryThread()) {
executor.execute(listener, event);
return;
}
try (Timing ignored = timings.startTiming()){
executor.execute(listener, event);
}
}
}

View File

@@ -1,87 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import javax.annotation.Nonnull; // Akarin - javax.annotation
import javax.annotation.Nullable; // Akarin - javax.annotation
/**
* Provides an ability to time sections of code within the Minecraft Server
*/
public interface Timing extends AutoCloseable {
/**
* Starts timing the execution until {@link #stopTiming()} is called.
*
* @return Timing
*/
@Nonnull // Akarin - javax.annotation
Timing startTiming();
default Timing startTiming(boolean assertThread) { return startTiming(); }; // Akarin
default Timing startTimingUnsafe() { return startTiming(); }; // Akarin
/**
* <p>Stops timing and records the data. Propagates the data up to group handlers.</p>
*
* Will automatically be called when this Timing is used with try-with-resources
*/
void stopTiming();
default void stopTimingUnsafe() { stopTiming(); }; // Akarin
/**
* Starts timing the execution until {@link #stopTiming()} is called.
*
* But only if we are on the primary thread.
*
* @return Timing
*/
@Nonnull // Akarin - javax.annotation
Timing startTimingIfSync();
default Timing startTimingIfSync(boolean assertThread) { return startTimingIfSync(); }; // Akarin
/**
* <p>Stops timing and records the data. Propagates the data up to group handlers.</p>
*
* <p>Will automatically be called when this Timing is used with try-with-resources</p>
*
* But only if we are on the primary thread.
*/
void stopTimingIfSync();
/**
* @deprecated Doesn't do anything - Removed
*/
@Deprecated
void abort();
/**
* Used internally to get the actual backing Handler in the case of delegated Handlers
*
* @return TimingHandler
*/
@Nullable
TimingHandler getTimingHandler();
@Override
void close();
}

View File

@@ -1,122 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import static co.aikar.util.JSONUtil.toArray;
/**
* <p>Lightweight object for tracking timing data</p>
*
* This is broken out to reduce memory usage
*/
class TimingData {
private final int id;
private int count = 0;
private int lagCount = 0;
private long totalTime = 0;
private long lagTotalTime = 0;
private int curTickCount = 0;
private long curTickTotal = 0;
TimingData(int id) {
this.id = id;
}
private TimingData(TimingData data) {
this.id = data.id;
this.totalTime = data.totalTime;
this.lagTotalTime = data.lagTotalTime;
this.count = data.count;
this.lagCount = data.lagCount;
}
void add(long diff) {
++curTickCount;
curTickTotal += diff;
}
void processTick(boolean violated) {
totalTime += curTickTotal;
count += curTickCount;
if (violated) {
lagTotalTime += curTickTotal;
lagCount += curTickCount;
}
curTickTotal = 0;
curTickCount = 0;
}
void reset() {
count = 0;
lagCount = 0;
curTickTotal = 0;
curTickCount = 0;
totalTime = 0;
lagTotalTime = 0;
}
protected TimingData clone() {
return new TimingData(this);
}
@NotNull
List<Object> export() {
List<Object> list = toArray(
id,
count,
totalTime);
if (lagCount > 0) {
list.add(lagCount);
list.add(lagTotalTime);
}
return list;
}
boolean hasData() {
return count > 0;
}
long getTotalTime() {
return totalTime;
}
int getCurTickCount() {
return curTickCount;
}
void setCurTickCount(int curTickCount) {
this.curTickCount = curTickCount;
}
long getCurTickTotal() {
return curTickTotal;
}
void setCurTickTotal(long curTickTotal) {
this.curTickTotal = curTickTotal;
}
}

View File

@@ -1,256 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import co.aikar.util.LoadingIntMap;
import io.akarin.server.core.AkarinGlobalConfig;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull; // Akarin - javax.annotation
import javax.annotation.Nullable; // Akarin - javax.annotation
import org.bukkit.Bukkit;
class TimingHandler implements Timing {
private static AtomicInteger idPool = new AtomicInteger(1);
private static Deque<TimingHandler> TIMING_STACK = new ArrayDeque<>();
final int id = idPool.getAndIncrement();
final TimingIdentifier identifier;
private final boolean verbose;
private final Int2ObjectOpenHashMap<TimingData> children = new LoadingIntMap<>(TimingData::new);
final TimingData record;
private final TimingHandler groupHandler;
private long start = 0;
private int timingDepth = 0;
private boolean added;
private boolean timed;
private boolean enabled;
TimingHandler(@Nonnull TimingIdentifier id) { // Akarin - javax.annotation
this.identifier = id;
this.verbose = id.name.startsWith("##");
this.record = new TimingData(this.id);
this.groupHandler = id.groupHandler;
TimingIdentifier.getGroup(id.group).handlers.add(this);
checkEnabled();
}
final void checkEnabled() {
enabled = Timings.timingsEnabled && (!verbose || Timings.verboseEnabled);
}
void processTick(boolean violated) {
if (timingDepth != 0 || record.getCurTickCount() == 0) {
timingDepth = 0;
start = 0;
return;
}
record.processTick(violated);
for (TimingData handler : children.values()) {
handler.processTick(violated);
}
}
@Nonnull // Akarin - javax.annotation
@Override
public Timing startTimingIfSync() {
// Akarin start
return startTiming(false);
}
@Nonnull // Akarin - javax.annotation
@Override
public Timing startTimingIfSync(boolean assertThread) {
startTiming(assertThread);
// Akarin end
return this;
}
@Override
public void stopTimingIfSync() {
stopTiming();
}
@Nonnull // Akarin - javax.annotation
public Timing startTiming() {
// Akarin start
return startTiming(false);
}
@Override
public Timing startTimingUnsafe() {
if (enabled && ++timingDepth == 1) {
ThreadAssertion.close();
// Akarin end
start = System.nanoTime();
TIMING_STACK.addLast(this);
}
return this;
}
// Akarin start
@Override
public Timing startTiming(boolean assertThread) {
if (enabled && (ThreadAssertion.is() || Bukkit.isPrimaryThread()) && ++timingDepth == 1) {
start = System.nanoTime();
TIMING_STACK.addLast(this);
if (assertThread && AkarinGlobalConfig.lazyThreadAssertion)
ThreadAssertion.start();
}
return this;
}
@Override
public void stopTimingUnsafe() {
if (enabled && timingDepth > 0 && --timingDepth == 0 && start != 0) {
TimingHandler last = TIMING_STACK.removeLast();
if (last != this) {
Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to Paper! ( " + this.identifier + ":" + last +")", new Throwable());
TIMING_STACK.addLast(last); // Add it back
}
addDiff(System.nanoTime() - start, TIMING_STACK.peekLast());
start = 0;
ThreadAssertion.close();
}
}
// Akarin end
public void stopTiming() {
if (enabled && timingDepth > 0 && (ThreadAssertion.is() || Bukkit.isPrimaryThread()) && --timingDepth == 0 && start != 0) { // Akarin
TimingHandler last;
while ((last = TIMING_STACK.removeLast()) != this) {
last.timingDepth = 0;
String reportTo;
if ("minecraft".equals(last.identifier.group)) {
reportTo = "Paper! This is a potential bug in Paper";
} else {
reportTo = "the plugin " + last.identifier.group + "(Look for errors above this in the logs)";
}
Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to " + reportTo + " (" + last.identifier +" did not stopTiming)", new Throwable());
}
addDiff(System.nanoTime() - start, TIMING_STACK.peekLast());
start = 0;
// Akarin start
if (AkarinGlobalConfig.lazyThreadAssertion)
ThreadAssertion.close();
// Akarin end
}
}
@Override
public final void abort() {
}
void addDiff(long diff, @Nullable TimingHandler parent) {
if (parent != null) {
parent.children.get(id).add(diff);
}
record.add(diff);
if (!added) {
added = true;
timed = true;
TimingsManager.HANDLERS.add(this);
}
if (groupHandler != null) {
groupHandler.addDiff(diff, parent);
groupHandler.children.get(id).add(diff);
}
}
/**
* Reset this timer, setting all values to zero.
*/
void reset(boolean full) {
record.reset();
if (full) {
timed = false;
}
start = 0;
timingDepth = 0;
added = false;
children.clear();
checkEnabled();
}
@Nonnull // Akarin - javax.annotation
@Override
public TimingHandler getTimingHandler() {
return this;
}
@Override
public boolean equals(Object o) {
return (this == o);
}
@Override
public int hashCode() {
return id;
}
/**
* This is simply for the Closeable interface so it can be used with try-with-resources ()
*/
@Override
public void close() {
if (ThreadAssertion.is()) stopTimingUnsafe(); else stopTimingIfSync(); // Akarin
}
public boolean isSpecial() {
return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK;
}
boolean isTimed() {
return timed;
}
public boolean isEnabled() {
return enabled;
}
@Nonnull // Akarin - javax.annotation
TimingData[] cloneChildren() {
final TimingData[] clonedChildren = new TimingData[children.size()];
int i = 0;
for (TimingData child : children.values()) {
clonedChildren[i++] = child.clone();
}
return clonedChildren;
}
}

View File

@@ -1,354 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import co.aikar.timings.TimingHistory.RegionData.RegionId;
import com.google.common.base.Function;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import co.aikar.util.LoadingMap;
import co.aikar.util.MRUMapCache;
import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK;
import static co.aikar.timings.TimingsManager.MINUTE_REPORTS;
import static co.aikar.util.JSONUtil.*;
@SuppressWarnings({"deprecation", "SuppressionAnnotation", "Convert2Lambda", "Anonymous2MethodRef"})
public class TimingHistory {
public static long lastMinuteTime;
public static long timedTicks;
public static long playerTicks;
public static long entityTicks;
public static long tileEntityTicks;
public static long activatedEntityTicks;
private static int worldIdPool = 1;
static Map<String, Integer> worldMap = LoadingMap.newHashMap(new Function<String, Integer>() {
@NotNull
@Override
public Integer apply(@Nullable String input) {
return worldIdPool++;
}
});
private final long endTime;
private final long startTime;
private final long totalTicks;
private final long totalTime; // Represents all time spent running the server this history
private final MinuteReport[] minuteReports;
private final TimingHistoryEntry[] entries;
final Set<Material> tileEntityTypeSet = Sets.newHashSet();
final Set<EntityType> entityTypeSet = Sets.newHashSet();
private final Map<Object, Object> worlds;
TimingHistory() {
this.endTime = System.currentTimeMillis() / 1000;
this.startTime = TimingsManager.historyStart / 1000;
if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) {
this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]);
this.minuteReports[this.minuteReports.length - 1] = new MinuteReport();
} else {
this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]);
}
long ticks = 0;
for (MinuteReport mp : this.minuteReports) {
ticks += mp.ticksRecord.timed;
}
this.totalTicks = ticks;
this.totalTime = FULL_SERVER_TICK.record.getTotalTime();
this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()];
int i = 0;
for (TimingHandler handler : TimingsManager.HANDLERS) {
entries[i++] = new TimingHistoryEntry(handler);
}
// Information about all loaded chunks/entities
//noinspection unchecked
this.worlds = toObjectMapper(Bukkit.getWorlds(), new Function<World, JSONPair>() {
@NotNull
@Override
public JSONPair apply(World world) {
Map<RegionId, RegionData> regions = LoadingMap.newHashMap(RegionData.LOADER);
for (Chunk chunk : world.getLoadedChunks()) {
RegionData data = regions.get(new RegionId(chunk.getX(), chunk.getZ()));
for (Entity entity : chunk.getEntities()) {
if (entity == null) {
Bukkit.getLogger().warning("Null entity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ());
continue;
}
data.entityCounts.get(entity.getType()).increment();
}
for (BlockState tileEntity : chunk.getTileEntities(false)) {
if (tileEntity == null) {
Bukkit.getLogger().warning("Null tileentity detected in chunk at position x: " + chunk.getX() + ", z: " + chunk.getZ());
continue;
}
data.tileEntityCounts.get(tileEntity.getBlock().getType()).increment();
}
}
return pair(
worldMap.get(world.getName()),
toArrayMapper(regions.values(),new Function<RegionData, Object>() {
@NotNull
@Override
public Object apply(RegionData input) {
return toArray(
input.regionId.x,
input.regionId.z,
toObjectMapper(input.entityCounts.entrySet(),
new Function<Map.Entry<EntityType, Counter>, JSONPair>() {
@NotNull
@Override
public JSONPair apply(Map.Entry<EntityType, Counter> entry) {
entityTypeSet.add(entry.getKey());
return pair(
String.valueOf(entry.getKey().getTypeId()),
entry.getValue().count()
);
}
}
),
toObjectMapper(input.tileEntityCounts.entrySet(),
new Function<Map.Entry<Material, Counter>, JSONPair>() {
@NotNull
@Override
public JSONPair apply(Map.Entry<Material, Counter> entry) {
tileEntityTypeSet.add(entry.getKey());
return pair(
String.valueOf(entry.getKey().getId()),
entry.getValue().count()
);
}
}
)
);
}
})
);
}
});
}
static class RegionData {
final RegionId regionId;
@SuppressWarnings("Guava")
static Function<RegionId, RegionData> LOADER = new Function<RegionId, RegionData>() {
@NotNull
@Override
public RegionData apply(@NotNull RegionId id) {
return new RegionData(id);
}
};
RegionData(@NotNull RegionId id) {
this.regionId = id;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RegionData that = (RegionData) o;
return regionId.equals(that.regionId);
}
@Override
public int hashCode() {
return regionId.hashCode();
}
@SuppressWarnings("unchecked")
final Map<EntityType, Counter> entityCounts = MRUMapCache.of(LoadingMap.of(
new EnumMap<EntityType, Counter>(EntityType.class), k -> new Counter()
));
@SuppressWarnings("unchecked")
final Map<Material, Counter> tileEntityCounts = MRUMapCache.of(LoadingMap.of(
new EnumMap<Material, Counter>(Material.class), k -> new Counter()
));
static class RegionId {
final int x, z;
final long regionId;
RegionId(int x, int z) {
this.x = x >> 5 << 5;
this.z = z >> 5 << 5;
this.regionId = ((long) (this.x) << 32) + (this.z >> 5 << 5) - Integer.MIN_VALUE;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RegionId regionId1 = (RegionId) o;
return regionId == regionId1.regionId;
}
@Override
public int hashCode() {
return (int) (regionId ^ (regionId >>> 32));
}
}
}
static void resetTicks(boolean fullReset) {
if (fullReset) {
// Non full is simply for 1 minute reports
timedTicks = 0;
}
lastMinuteTime = System.nanoTime();
playerTicks = 0;
tileEntityTicks = 0;
entityTicks = 0;
activatedEntityTicks = 0;
}
@NotNull
Object export() {
return createObject(
pair("s", startTime),
pair("e", endTime),
pair("tk", totalTicks),
pair("tm", totalTime),
pair("w", worlds),
pair("h", toArrayMapper(entries, new Function<TimingHistoryEntry, Object>() {
@Nullable
@Override
public Object apply(TimingHistoryEntry entry) {
TimingData record = entry.data;
if (!record.hasData()) {
return null;
}
return entry.export();
}
})),
pair("mp", toArrayMapper(minuteReports, new Function<MinuteReport, Object>() {
@NotNull
@Override
public Object apply(MinuteReport input) {
return input.export();
}
}))
);
}
static class MinuteReport {
final long time = System.currentTimeMillis() / 1000;
final TicksRecord ticksRecord = new TicksRecord();
final PingRecord pingRecord = new PingRecord();
final TimingData fst = TimingsManager.FULL_SERVER_TICK.minuteData.clone();
final double tps = 1E9 / ( System.nanoTime() - lastMinuteTime ) * ticksRecord.timed;
final double usedMemory = TimingsManager.FULL_SERVER_TICK.avgUsedMemory;
final double freeMemory = TimingsManager.FULL_SERVER_TICK.avgFreeMemory;
final double loadAvg = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
@NotNull
List<Object> export() {
return toArray(
time,
Math.round(tps * 100D) / 100D,
Math.round(pingRecord.avg * 100D) / 100D,
fst.export(),
toArray(ticksRecord.timed,
ticksRecord.player,
ticksRecord.entity,
ticksRecord.activatedEntity,
ticksRecord.tileEntity
),
usedMemory,
freeMemory,
loadAvg
);
}
}
private static class TicksRecord {
final long timed;
final long player;
final long entity;
final long tileEntity;
final long activatedEntity;
TicksRecord() {
timed = timedTicks - (TimingsManager.MINUTE_REPORTS.size() * 1200);
player = playerTicks;
entity = entityTicks;
tileEntity = tileEntityTicks;
activatedEntity = activatedEntityTicks;
}
}
private static class PingRecord {
final double avg;
PingRecord() {
final Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
int totalPing = 0;
for (Player player : onlinePlayers) {
totalPing += player.spigot().getPing();
}
avg = onlinePlayers.isEmpty() ? 0 : totalPing / onlinePlayers.size();
}
}
private static class Counter {
private int count = 0;
public int increment() {
return ++count;
}
public int count() {
return count;
}
}
}

View File

@@ -1,58 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import com.google.common.base.Function;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import static co.aikar.util.JSONUtil.toArrayMapper;
class TimingHistoryEntry {
final TimingData data;
private final TimingData[] children;
TimingHistoryEntry(@NotNull TimingHandler handler) {
this.data = handler.record.clone();
children = handler.cloneChildren();
}
@NotNull
List<Object> export() {
List<Object> result = data.export();
if (children.length > 0) {
result.add(
toArrayMapper(children, new Function<TimingData, Object>() {
@NotNull
@Override
public Object apply(TimingData child) {
return child.export();
}
})
);
}
return result;
}
}

View File

@@ -1,116 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import co.aikar.util.LoadingMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* <p>Used as a basis for fast HashMap key comparisons for the Timing Map.</p>
*
* This class uses interned strings giving us the ability to do an identity check instead of equals() on the strings
*/
final class TimingIdentifier {
/**
* Holds all groups. Autoloads on request for a group by name.
*/
static final Map<String, TimingGroup> GROUP_MAP = LoadingMap.of(new ConcurrentHashMap<>(64, .5F), TimingGroup::new);
private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft");
final String group;
final String name;
final TimingHandler groupHandler;
private final int hashCode;
TimingIdentifier(@Nullable String group, @NotNull String name, @Nullable Timing groupHandler) {
this.group = group != null ? group: DEFAULT_GROUP.name;
this.name = name;
this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null;
this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode();
}
@NotNull
static TimingGroup getGroup(@Nullable String groupName) {
if (groupName == null) {
//noinspection ConstantConditions
return DEFAULT_GROUP;
}
return GROUP_MAP.get(groupName);
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
TimingIdentifier that = (TimingIdentifier) o;
return Objects.equals(group, that.group) && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public String toString() {
return "TimingIdentifier{id=" + group + ":" + name +'}';
}
static class TimingGroup {
private static AtomicInteger idPool = new AtomicInteger(1);
final int id = idPool.getAndIncrement();
final String name;
final List<TimingHandler> handlers = Collections.synchronizedList(new ArrayList<>(64));
private TimingGroup(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimingGroup that = (TimingGroup) o;
return id == that.id;
}
@Override
public int hashCode() {
return id;
}
}
}

View File

@@ -1,293 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import com.google.common.base.Preconditions;
import com.google.common.collect.EvictingQueue;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import java.util.Queue;
import java.util.logging.Level;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"})
public final class Timings {
private static final int MAX_HISTORY_FRAMES = 12;
public static final Timing NULL_HANDLER = new NullTimingHandler();
static boolean timingsEnabled = false;
static boolean verboseEnabled = false;
private static int historyInterval = -1;
private static int historyLength = -1;
private Timings() {}
/**
* Returns a Timing for a plugin corresponding to a name.
*
* @param plugin Plugin to own the Timing
* @param name Name of Timing
* @return Handler
*/
@NotNull
public static Timing of(@NotNull Plugin plugin, @NotNull String name) {
Timing pluginHandler = null;
if (plugin != null) {
pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER);
}
return of(plugin, name, pluginHandler);
}
/**
* <p>Returns a handler that has a groupHandler timer handler. Parent timers should not have their
* start/stop methods called directly, as the children will call it for you.</p>
*
* Parent Timers are used to group multiple subsections together and get a summary of them combined
* Parent Handler can not be changed after first call
*
* @param plugin Plugin to own the Timing
* @param name Name of Timing
* @param groupHandler Parent handler to mirror .start/stop calls to
* @return Timing Handler
*/
@NotNull
public static Timing of(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) {
Preconditions.checkNotNull(plugin, "Plugin can not be null");
return TimingsManager.getHandler(plugin.getName(), name, groupHandler);
}
/**
* Returns a Timing object after starting it, useful for Java7 try-with-resources.
*
* try (Timing ignored = Timings.ofStart(plugin, someName)) {
* // timed section
* }
*
* @param plugin Plugin to own the Timing
* @param name Name of Timing
* @return Timing Handler
*/
@NotNull
public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name) {
return ofStart(plugin, name, null);
}
/**
* Returns a Timing object after starting it, useful for Java7 try-with-resources.
*
* try (Timing ignored = Timings.ofStart(plugin, someName, groupHandler)) {
* // timed section
* }
*
* @param plugin Plugin to own the Timing
* @param name Name of Timing
* @param groupHandler Parent handler to mirror .start/stop calls to
* @return Timing Handler
*/
@NotNull
public static Timing ofStart(@NotNull Plugin plugin, @NotNull String name, @Nullable Timing groupHandler) {
Timing timing = of(plugin, name, groupHandler);
timing.startTiming();
return timing;
}
/**
* Gets whether or not the Spigot Timings system is enabled
*
* @return Enabled or not
*/
public static boolean isTimingsEnabled() {
return timingsEnabled;
}
/**
* <p>Sets whether or not the Spigot Timings system should be enabled</p>
*
* Calling this will reset timing data.
*
* @param enabled Should timings be reported
*/
public static void setTimingsEnabled(boolean enabled) {
timingsEnabled = enabled;
reset();
}
/**
* <p>Sets whether or not the Timings should monitor at Verbose level.</p>
*
* <p>When Verbose is disabled, high-frequency timings will not be available.</p>
*
* @return Enabled or not
*/
public static boolean isVerboseTimingsEnabled() {
return verboseEnabled;
}
/**
* <p>Sets whether or not the Timings should monitor at Verbose level.</p>
*
* When Verbose is disabled, high-frequency timings will not be available.
* Calling this will reset timing data.
*
* @param enabled Should high-frequency timings be reported
*/
public static void setVerboseTimingsEnabled(boolean enabled) {
verboseEnabled = enabled;
TimingsManager.needsRecheckEnabled = true;
}
/**
* <p>Gets the interval between Timing History report generation.</p>
*
* Defaults to 5 minutes (6000 ticks)
*
* @return Interval in ticks
*/
public static int getHistoryInterval() {
return historyInterval;
}
/**
* <p>Sets the interval between Timing History report generations.</p>
*
* <p>Defaults to 5 minutes (6000 ticks)</p>
*
* This will recheck your history length, so lowering this value will lower your
* history length if you need more than 60 history windows.
*
* @param interval Interval in ticks
*/
public static void setHistoryInterval(int interval) {
historyInterval = Math.max(20*60, interval);
// Recheck the history length with the new Interval
if (historyLength != -1) {
setHistoryLength(historyLength);
}
}
/**
* Gets how long in ticks Timings history is kept for the server.
*
* Defaults to 1 hour (72000 ticks)
*
* @return Duration in Ticks
*/
public static int getHistoryLength() {
return historyLength;
}
/**
* Sets how long Timing History reports are kept for the server.
*
* Defaults to 1 hours(72000 ticks)
*
* This value is capped at a maximum of getHistoryInterval() * MAX_HISTORY_FRAMES (12)
*
* Will not reset Timing Data but may truncate old history if the new length is less than old length.
*
* @param length Duration in ticks
*/
public static void setHistoryLength(int length) {
// Cap at 12 History Frames, 1 hour at 5 minute frames.
int maxLength = historyInterval * MAX_HISTORY_FRAMES;
// For special cases of servers with special permission to bypass the max.
// This max helps keep data file sizes reasonable for processing on Aikar's Timing parser side.
// Setting this will not help you bypass the max unless Aikar has added an exception on the API side.
if (System.getProperty("timings.bypassMax") != null) {
maxLength = Integer.MAX_VALUE;
}
historyLength = Math.max(Math.min(maxLength, length), historyInterval);
Queue<TimingHistory> oldQueue = TimingsManager.HISTORY;
int frames = (getHistoryLength() / getHistoryInterval());
if (length > maxLength) {
Bukkit.getLogger().log(Level.WARNING, "Timings Length too high. Requested " + length + ", max is " + maxLength + ". To get longer history, you must increase your interval. Set Interval to " + Math.ceil(length / MAX_HISTORY_FRAMES) + " to achieve this length.");
}
TimingsManager.HISTORY = EvictingQueue.create(frames);
TimingsManager.HISTORY.addAll(oldQueue);
}
/**
* Resets all Timing Data
*/
public static void reset() {
TimingsManager.reset();
}
/**
* Generates a report and sends it to the specified command sender.
*
* If sender is null, ConsoleCommandSender will be used.
* @param sender The sender to send to, or null to use the ConsoleCommandSender
*/
public static void generateReport(@Nullable CommandSender sender) {
if (sender == null) {
sender = Bukkit.getConsoleSender();
}
TimingsExport.requestingReport.add(sender);
}
/**
* Generates a report and sends it to the specified listener.
* Use with {@link org.bukkit.command.BufferedCommandSender} to get full response when done!
* @param sender The listener to send responses too.
*/
public static void generateReport(@NotNull TimingsReportListener sender) {
Validate.notNull(sender);
TimingsExport.requestingReport.add(sender);
}
/*
=================
Protected API: These are for internal use only in Bukkit/CraftBukkit
These do not have isPrimaryThread() checks in the startTiming/stopTiming
=================
*/
@NotNull
static TimingHandler ofSafe(@NotNull String name) {
return ofSafe(null, name, null);
}
@NotNull
static Timing ofSafe(@Nullable Plugin plugin, @NotNull String name) {
Timing pluginHandler = null;
if (plugin != null) {
pluginHandler = ofSafe(plugin.getName(), "Combined Total", TimingsManager.PLUGIN_GROUP_HANDLER);
}
return ofSafe(plugin != null ? plugin.getName() : "Minecraft - Invalid Plugin", name, pluginHandler);
}
@NotNull
static TimingHandler ofSafe(@NotNull String name, @Nullable Timing groupHandler) {
return ofSafe(null, name, groupHandler);
}
@NotNull
static TimingHandler ofSafe(@Nullable String groupName, @NotNull String name, @Nullable Timing groupHandler) {
return TimingsManager.getHandler(groupName, name, groupHandler);
}
}

View File

@@ -1,122 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TimingsCommand extends BukkitCommand {
private static final List<String> TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste", "verbon", "verboff");
private long lastResetAttempt = 0;
public TimingsCommand(@NotNull String name) {
super(name);
this.description = "Manages Spigot Timings data to see performance of the server.";
this.usageMessage = "/timings <reset|report|on|off|verbon|verboff>";
this.setPermission("bukkit.command.timings");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) {
if (!testPermission(sender)) {
return true;
}
if (args.length < 1) {
sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
return true;
}
final String arg = args[0];
if ("on".equalsIgnoreCase(arg)) {
Timings.setTimingsEnabled(true);
sender.sendMessage("Enabled Timings & Reset");
return true;
} else if ("off".equalsIgnoreCase(arg)) {
Timings.setTimingsEnabled(false);
sender.sendMessage("Disabled Timings");
return true;
}
if (!Timings.isTimingsEnabled()) {
sender.sendMessage("Please enable timings by typing /timings on");
return true;
}
long now = System.currentTimeMillis();
if ("verbon".equalsIgnoreCase(arg)) {
Timings.setVerboseTimingsEnabled(true);
sender.sendMessage("Enabled Verbose Timings");
return true;
} else if ("verboff".equalsIgnoreCase(arg)) {
Timings.setVerboseTimingsEnabled(false);
sender.sendMessage("Disabled Verbose Timings");
return true;
} else if ("reset".equalsIgnoreCase(arg)) {
if (now - lastResetAttempt < 30000) {
TimingsManager.reset();
sender.sendMessage(ChatColor.RED + "Timings reset. Please wait 5-10 minutes before using /timings report.");
} else {
lastResetAttempt = now;
sender.sendMessage(ChatColor.RED + "WARNING: Timings v2 should not be reset. If you are encountering lag, please wait 3 minutes and then issue a report. The best timings will include 10+ minutes, with data before and after your lag period. If you really want to reset, run this command again within 30 seconds.");
}
} else if ("cost".equals(arg)) {
sender.sendMessage("Timings cost: " + TimingsExport.getCost());
} else if (
"paste".equalsIgnoreCase(arg) ||
"report".equalsIgnoreCase(arg) ||
"get".equalsIgnoreCase(arg) ||
"merged".equalsIgnoreCase(arg) ||
"separate".equalsIgnoreCase(arg)
) {
Timings.generateReport(sender);
} else {
sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
}
return true;
}
@NotNull
@Override
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
Validate.notNull(sender, "Sender cannot be null");
Validate.notNull(args, "Arguments cannot be null");
Validate.notNull(alias, "Alias cannot be null");
if (args.length == 1) {
return StringUtil.copyPartialMatches(args[0], TIMINGS_SUBCOMMANDS,
new ArrayList<String>(TIMINGS_SUBCOMMANDS.size()));
}
return ImmutableList.of();
}
}

View File

@@ -1,355 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.MemorySection;
import org.bukkit.entity.EntityType;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import static co.aikar.timings.TimingsManager.HISTORY;
import static co.aikar.util.JSONUtil.appendObjectData;
import static co.aikar.util.JSONUtil.createObject;
import static co.aikar.util.JSONUtil.pair;
import static co.aikar.util.JSONUtil.toArray;
import static co.aikar.util.JSONUtil.toArrayMapper;
import static co.aikar.util.JSONUtil.toObjectMapper;
@SuppressWarnings({"rawtypes", "SuppressionAnnotation"})
class TimingsExport extends Thread {
private final TimingsReportListener listeners;
private final Map out;
private final TimingHistory[] history;
private static long lastReport = 0;
final static List<CommandSender> requestingReport = Lists.newArrayList();
private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) {
super("Timings paste thread");
this.listeners = listeners;
this.out = out;
this.history = history;
}
/**
* Checks if any pending reports are being requested, and builds one if needed.
*/
static void reportTimings() {
if (requestingReport.isEmpty()) {
return;
}
TimingsReportListener listeners = new TimingsReportListener(requestingReport);
listeners.addConsoleIfNeeded();
requestingReport.clear();
long now = System.currentTimeMillis();
final long lastReportDiff = now - lastReport;
if (lastReportDiff < 60000) {
listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)");
listeners.done();
return;
}
final long lastStartDiff = now - TimingsManager.timingStart;
if (lastStartDiff < 180000) {
listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)");
listeners.done();
return;
}
listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report...");
lastReport = now;
Map parent = createObject(
// Get some basic system details about the server
pair("version", Bukkit.getVersion()),
pair("maxplayers", Bukkit.getMaxPlayers()),
pair("start", TimingsManager.timingStart / 1000),
pair("end", System.currentTimeMillis() / 1000),
pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000)
);
if (!TimingsManager.privacy) {
appendObjectData(parent,
pair("server", Bukkit.getServerName()),
pair("motd", Bukkit.getServer().getMotd()),
pair("online-mode", Bukkit.getServer().getOnlineMode()),
pair("icon", Bukkit.getServer().getServerIcon().getData())
);
}
final Runtime runtime = Runtime.getRuntime();
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
parent.put("system", createObject(
pair("timingcost", getCost()),
pair("name", System.getProperty("os.name")),
pair("version", System.getProperty("os.version")),
pair("jvmversion", System.getProperty("java.version")),
pair("arch", System.getProperty("os.arch")),
pair("maxmem", runtime.maxMemory()),
pair("cpu", runtime.availableProcessors()),
pair("runtime", ManagementFactory.getRuntimeMXBean().getUptime()),
pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")),
pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime()))))
)
);
Set<Material> tileEntityTypeSet = Sets.newHashSet();
Set<EntityType> entityTypeSet = Sets.newHashSet();
int size = HISTORY.size();
TimingHistory[] history = new TimingHistory[size + 1];
int i = 0;
for (TimingHistory timingHistory : HISTORY) {
tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet);
entityTypeSet.addAll(timingHistory.entityTypeSet);
history[i++] = timingHistory;
}
history[i] = new TimingHistory(); // Current snapshot
tileEntityTypeSet.addAll(history[i].tileEntityTypeSet);
entityTypeSet.addAll(history[i].entityTypeSet);
Map handlers = createObject();
Map groupData;
synchronized (TimingIdentifier.GROUP_MAP) {
for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) {
synchronized (group.handlers) {
for (TimingHandler id : group.handlers) {
if (!id.isTimed() && !id.isSpecial()) {
continue;
}
String name = id.identifier.name;
if (name.startsWith("##")) {
name = name.substring(3);
}
handlers.put(id.id, toArray(
group.id,
name
));
}
}
}
groupData = toObjectMapper(
TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name));
}
parent.put("idmap", createObject(
pair("groups", groupData),
pair("handlers", handlers),
pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))),
pair("tileentity",
toObjectMapper(tileEntityTypeSet, input -> pair(input.getId(), input.name()))),
pair("entity",
toObjectMapper(entityTypeSet, input -> pair(input.getTypeId(), input.name())))
));
// Information about loaded plugins
parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(),
plugin -> pair(plugin.getName(), createObject(
pair("version", plugin.getDescription().getVersion()),
pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()),
pair("website", plugin.getDescription().getWebsite()),
pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", "))
))));
// Information on the users Config
parent.put("config", createObject(
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null))
));
new TimingsExport(listeners, parent, history).start();
}
static long getCost() {
// Benchmark the users System.nanotime() for cost basis
int passes = 100;
TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1");
TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2");
TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3");
TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4");
TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5");
TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6");
long start = System.nanoTime();
for (int i = 0; i < passes; i++) {
SAMPLER1.startTiming();
SAMPLER2.startTiming();
SAMPLER3.startTiming();
SAMPLER3.stopTiming();
SAMPLER4.startTiming();
SAMPLER5.startTiming();
SAMPLER6.startTiming();
SAMPLER6.stopTiming();
SAMPLER5.stopTiming();
SAMPLER4.stopTiming();
SAMPLER2.stopTiming();
SAMPLER1.stopTiming();
}
long timingsCost = (System.nanoTime() - start) / passes / 6;
SAMPLER1.reset(true);
SAMPLER2.reset(true);
SAMPLER3.reset(true);
SAMPLER4.reset(true);
SAMPLER5.reset(true);
SAMPLER6.reset(true);
return timingsCost;
}
private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) {
JSONObject object = new JSONObject();
for (String key : config.getKeys(false)) {
String fullKey = (parentKey != null ? parentKey + "." + key : key);
if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey)) {
continue;
}
final Object val = config.get(key);
object.put(key, valAsJSON(val, fullKey));
}
return object;
}
private static Object valAsJSON(Object val, final String parentKey) {
if (!(val instanceof MemorySection)) {
if (val instanceof List) {
Iterable<Object> v = (Iterable<Object>) val;
return toArrayMapper(v, input -> valAsJSON(input, parentKey));
} else {
return val.toString();
}
} else {
return mapAsJSON((ConfigurationSection) val, parentKey);
}
}
@Override
public void run() {
out.put("data", toArrayMapper(history, TimingHistory::export));
String response = null;
String timingsURL = null;
try {
HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection();
con.setDoOutput(true);
String hostName = "BrokenHost";
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch(Exception ignored) {}
con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getServerName() + "/" + hostName);
con.setRequestMethod("POST");
con.setInstanceFollowRedirects(false);
OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{
this.def.setLevel(7);
}};
request.write(JSONValue.toJSONString(out).getBytes("UTF-8"));
request.close();
response = getResponse(con);
if (con.getResponseCode() != 302) {
listeners.sendMessage(
ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage());
listeners.sendMessage(ChatColor.RED + "Check your logs for more information");
if (response != null) {
Bukkit.getLogger().log(Level.SEVERE, response);
}
return;
}
timingsURL = con.getHeaderField("Location");
listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL);
if (response != null && !response.isEmpty()) {
Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response);
}
} catch (IOException ex) {
listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information");
if (response != null) {
Bukkit.getLogger().log(Level.SEVERE, response);
}
Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex);
} finally {
this.listeners.done(timingsURL);
}
}
private String getResponse(HttpURLConnection con) throws IOException {
InputStream is = null;
try {
is = con.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
return bos.toString();
} catch (IOException ex) {
listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information");
Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex);
return null;
} finally {
if (is != null) {
is.close();
}
}
}
}

View File

@@ -1,188 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import co.aikar.util.LoadingMap;
import com.google.common.collect.EvictingQueue;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.PluginClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class TimingsManager {
static final Map<TimingIdentifier, TimingHandler> TIMING_MAP = LoadingMap.of(
new ConcurrentHashMap<>(4096, .5F), TimingHandler::new
);
public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler();
public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK);
public static final Timing PLUGIN_GROUP_HANDLER = Timings.ofSafe("Plugins");
public static List<String> hiddenConfigs = new ArrayList<String>();
public static boolean privacy = false;
static final List<TimingHandler> HANDLERS = new ArrayList<>(1024);
static final List<TimingHistory.MinuteReport> MINUTE_REPORTS = new ArrayList<>(64);
static EvictingQueue<TimingHistory> HISTORY = EvictingQueue.create(12);
static long timingStart = 0;
static long historyStart = 0;
static boolean needsFullReset = false;
static boolean needsRecheckEnabled = false;
private TimingsManager() {}
/**
* Resets all timing data on the next tick
*/
static void reset() {
needsFullReset = true;
}
/**
* Ticked every tick by CraftBukkit to count the number of times a timer
* caused TPS loss.
*/
static void tick() {
if (Timings.timingsEnabled) {
boolean violated = FULL_SERVER_TICK.isViolated();
for (TimingHandler handler : HANDLERS) {
if (handler.isSpecial()) {
// We manually call this
continue;
}
handler.processTick(violated);
}
TimingHistory.playerTicks += Bukkit.getOnlinePlayers().size();
TimingHistory.timedTicks++;
// Generate TPS/Ping/Tick reports every minute
}
}
static void stopServer() {
Timings.timingsEnabled = false;
recheckEnabled();
}
static void recheckEnabled() {
synchronized (TIMING_MAP) {
for (TimingHandler timings : TIMING_MAP.values()) {
timings.checkEnabled();
}
}
needsRecheckEnabled = false;
}
static void resetTimings() {
if (needsFullReset) {
// Full resets need to re-check every handlers enabled state
// Timing map can be modified from async so we must sync on it.
synchronized (TIMING_MAP) {
for (TimingHandler timings : TIMING_MAP.values()) {
timings.reset(true);
}
}
Bukkit.getLogger().log(Level.INFO, "Timings Reset");
HISTORY.clear();
needsFullReset = false;
needsRecheckEnabled = false;
timingStart = System.currentTimeMillis();
} else {
// Soft resets only need to act on timings that have done something
// Handlers can only be modified on main thread.
for (TimingHandler timings : HANDLERS) {
timings.reset(false);
}
}
HANDLERS.clear();
MINUTE_REPORTS.clear();
TimingHistory.resetTicks(true);
historyStart = System.currentTimeMillis();
}
@NotNull
static TimingHandler getHandler(@Nullable String group, @NotNull String name, @Nullable Timing parent) {
return TIMING_MAP.get(new TimingIdentifier(group, name, parent));
}
/**
* <p>Due to access restrictions, we need a helper method to get a Command TimingHandler with String group</p>
*
* Plugins should never call this
*
* @param pluginName Plugin this command is associated with
* @param command Command to get timings for
* @return TimingHandler
*/
@NotNull
public static Timing getCommandTiming(@Nullable String pluginName, @NotNull Command command) {
Plugin plugin = null;
final Server server = Bukkit.getServer();
if (!( server == null || pluginName == null ||
"minecraft".equals(pluginName) || "bukkit".equals(pluginName) ||
"spigot".equalsIgnoreCase(pluginName) || "paper".equals(pluginName)
)) {
plugin = server.getPluginManager().getPlugin(pluginName);
}
if (plugin == null) {
// Plugin is passing custom fallback prefix, try to look up by class loader
plugin = getPluginByClassloader(command.getClass());
}
if (plugin == null) {
return Timings.ofSafe("Command: " + pluginName + ":" + command.getTimingName());
}
return Timings.ofSafe(plugin, "Command: " + pluginName + ":" + command.getTimingName());
}
/**
* Looks up the class loader for the specified class, and if it is a PluginClassLoader, return the
* Plugin that created this class.
*
* @param clazz Class to check
* @return Plugin if created by a plugin
*/
@Nullable
public static Plugin getPluginByClassloader(@Nullable Class<?> clazz) {
if (clazz == null) {
return null;
}
final ClassLoader classLoader = clazz.getClassLoader();
if (classLoader instanceof PluginClassLoader) {
PluginClassLoader pluginClassLoader = (PluginClassLoader) classLoader;
return pluginClassLoader.getPlugin();
}
return null;
}
}

View File

@@ -1,75 +0,0 @@
package co.aikar.timings;
import com.google.common.collect.Lists;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.MessageCommandSender;
import org.bukkit.command.RemoteConsoleCommandSender;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("WeakerAccess")
public class TimingsReportListener implements MessageCommandSender {
private final List<CommandSender> senders;
private final Runnable onDone;
private String timingsURL;
public TimingsReportListener(@NotNull CommandSender senders) {
this(senders, null);
}
public TimingsReportListener(@NotNull CommandSender sender, @Nullable Runnable onDone) {
this(Lists.newArrayList(sender), onDone);
}
public TimingsReportListener(@NotNull List<CommandSender> senders) {
this(senders, null);
}
public TimingsReportListener(@NotNull List<CommandSender> senders, @Nullable Runnable onDone) {
Validate.notNull(senders);
Validate.notEmpty(senders);
this.senders = Lists.newArrayList(senders);
this.onDone = onDone;
}
@Nullable
public String getTimingsURL() {
return timingsURL;
}
public void done() {
done(null);
}
public void done(@Nullable String url) {
this.timingsURL = url;
if (onDone != null) {
onDone.run();
}
for (CommandSender sender : senders) {
if (sender instanceof TimingsReportListener) {
((TimingsReportListener) sender).done();
}
}
}
@Override
public void sendMessage(@NotNull String message) {
senders.forEach((sender) -> sender.sendMessage(message));
}
public void addConsoleIfNeeded() {
boolean hasConsole = false;
for (CommandSender sender : this.senders) {
if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
hasConsole = true;
}
}
if (!hasConsole) {
this.senders.add(Bukkit.getConsoleSender());
}
}
}

View File

@@ -1,53 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.timings;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
class UnsafeTimingHandler extends TimingHandler {
UnsafeTimingHandler(@NotNull TimingIdentifier id) {
super(id);
}
private static void checkThread() {
if (!Bukkit.isPrimaryThread()) {
throw new IllegalStateException("Calling Timings from Async Operation");
}
}
@NotNull
@Override
public Timing startTiming() {
checkThread();
return super.startTiming();
}
@Override
public void stopTiming() {
checkThread();
super.stopTiming();
}
}

View File

@@ -1,38 +0,0 @@
package co.aikar.util;
import com.google.common.collect.ForwardingMap;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Counter <T> extends ForwardingMap<T, Long> {
private final Map<T, Long> counts = new HashMap<>();
public long decrement(@Nullable T key) {
return increment(key, -1);
}
public long increment(@Nullable T key) {
return increment(key, 1);
}
public long decrement(@Nullable T key, long amount) {
return decrement(key, -amount);
}
public long increment(@Nullable T key, long amount) {
Long count = this.getCount(key);
count += amount;
this.counts.put(key, count);
return count;
}
public long getCount(@Nullable T key) {
return this.counts.getOrDefault(key, 0L);
}
@NotNull
@Override
protected Map<T, Long> delegate() {
return this.counts;
}
}

View File

@@ -1,140 +0,0 @@
package co.aikar.util;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Provides Utility methods that assist with generating JSON Objects
*/
@SuppressWarnings({"rawtypes", "SuppressionAnnotation"})
public final class JSONUtil {
private JSONUtil() {}
/**
* Creates a key/value "JSONPair" object
*
* @param key Key to use
* @param obj Value to use
* @return JSONPair
*/
@NotNull
public static JSONPair pair(@NotNull String key, @Nullable Object obj) {
return new JSONPair(key, obj);
}
@NotNull
public static JSONPair pair(long key, @Nullable Object obj) {
return new JSONPair(String.valueOf(key), obj);
}
/**
* Creates a new JSON object from multiple JSONPair key/value pairs
*
* @param data JSONPairs
* @return Map
*/
@NotNull
public static Map<String, Object> createObject(@NotNull JSONPair... data) {
return appendObjectData(new LinkedHashMap(), data);
}
/**
* This appends multiple key/value Obj pairs into a JSON Object
*
* @param parent Map to be appended to
* @param data Data to append
* @return Map
*/
@NotNull
public static Map<String, Object> appendObjectData(@NotNull Map parent, @NotNull JSONPair... data) {
for (JSONPair JSONPair : data) {
parent.put(JSONPair.key, JSONPair.val);
}
return parent;
}
/**
* This builds a JSON array from a set of data
*
* @param data Data to build JSON array from
* @return List
*/
@NotNull
public static List toArray(@NotNull Object... data) {
return Lists.newArrayList(data);
}
/**
* These help build a single JSON array using a mapper function
*
* @param collection Collection to apply to
* @param mapper Mapper to apply
* @param <E> Element Type
* @return List
*/
@NotNull
public static <E> List toArrayMapper(@NotNull E[] collection, @NotNull Function<E, Object> mapper) {
return toArrayMapper(Lists.newArrayList(collection), mapper);
}
@NotNull
public static <E> List toArrayMapper(@NotNull Iterable<E> collection, @NotNull Function<E, Object> mapper) {
List array = Lists.newArrayList();
for (E e : collection) {
Object object = mapper.apply(e);
if (object != null) {
array.add(object);
}
}
return array;
}
/**
* These help build a single JSON Object from a collection, using a mapper function
*
* @param collection Collection to apply to
* @param mapper Mapper to apply
* @param <E> Element Type
* @return Map
*/
@NotNull
public static <E> Map toObjectMapper(@NotNull E[] collection, @NotNull Function<E, JSONPair> mapper) {
return toObjectMapper(Lists.newArrayList(collection), mapper);
}
@NotNull
public static <E> Map toObjectMapper(@NotNull Iterable<E> collection, @NotNull Function<E, JSONPair> mapper) {
Map object = Maps.newLinkedHashMap();
for (E e : collection) {
JSONPair JSONPair = mapper.apply(e);
if (JSONPair != null) {
object.put(JSONPair.key, JSONPair.val);
}
}
return object;
}
/**
* Simply stores a key and a value, used internally by many methods below.
*/
@SuppressWarnings("PublicInnerClass")
public static class JSONPair {
final String key;
final Object val;
JSONPair(@NotNull String key, @NotNull Object val) {
this.key = key;
this.val = val;
}
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) 2015. Starlis LLC / dba Empire Minecraft
*
* This source code is proprietary software and must not be redistributed without Starlis LLC's approval
*
*/
package co.aikar.util;
import com.google.common.base.Function;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Allows you to pass a Loader function that when a key is accessed that doesn't exist,
* automatically loads the entry into the map by calling the loader Function.
*
* .get() Will only return null if the Loader can return null.
*
* You may pass any backing Map to use.
*
* This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed.
*
* Do not wrap the backing map with Collections.synchronizedMap.
*
* @param <V> Value
*/
public class LoadingIntMap<V> extends Int2ObjectOpenHashMap<V> {
private final Function<Integer, V> loader;
public LoadingIntMap(@NotNull Function<Integer, V> loader) {
super();
this.loader = loader;
}
public LoadingIntMap(int expectedSize, @NotNull Function<Integer, V> loader) {
super(expectedSize);
this.loader = loader;
}
public LoadingIntMap(int expectedSize, float loadFactor, @NotNull Function<Integer, V> loader) {
super(expectedSize, loadFactor);
this.loader = loader;
}
@Nullable
@Override
public V get(int key) {
V res = super.get(key);
if (res == null) {
res = loader.apply(key);
if (res != null) {
put(key, res);
}
}
return res;
}
/**
* Due to java stuff, you will need to cast it to (Function) for some cases
*
* @param <T> Type
*/
public abstract static class Feeder <T> implements Function<T, T> {
@Nullable
@Override
public T apply(@Nullable Object input) {
return apply();
}
@Nullable
public abstract T apply();
}
}

View File

@@ -1,368 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.util;
import com.google.common.base.Preconditions;
import java.lang.reflect.Constructor;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Allows you to pass a Loader function that when a key is accessed that doesn't exists,
* automatically loads the entry into the map by calling the loader Function.
*
* .get() Will only return null if the Loader can return null.
*
* You may pass any backing Map to use.
*
* This class is not thread safe and should be wrapped with Collections.synchronizedMap on the OUTSIDE of the LoadingMap if needed.
*
* Do not wrap the backing map with Collections.synchronizedMap.
*
* @param <K> Key
* @param <V> Value
*/
public class LoadingMap <K, V> extends AbstractMap<K, V> {
private final Map<K, V> backingMap;
private final java.util.function.Function<K, V> loader;
/**
* Initializes an auto loading map using specified loader and backing map
* @param backingMap Map to wrap
* @param loader Loader
*/
public LoadingMap(@NotNull Map<K, V> backingMap, @NotNull java.util.function.Function<K, V> loader) {
this.backingMap = backingMap;
this.loader = loader;
}
/**
* Creates a new LoadingMap with the specified map and loader
*
* @param backingMap Actual map being used.
* @param loader Loader to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> of(@NotNull Map<K, V> backingMap, @NotNull Function<K, V> loader) {
return new LoadingMap<>(backingMap, loader);
}
/**
* Creates a LoadingMap with an auto instantiating loader.
*
* Will auto construct class of of Value when not found
*
* Since this uses Reflection, It is more effecient to define your own static loader
* than using this helper, but if performance is not critical, this is easier.
*
* @param backingMap Actual map being used.
* @param keyClass Class used for the K generic
* @param valueClass Class used for the V generic
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newAutoMap(@NotNull Map<K, V> backingMap, @Nullable final Class<? extends K> keyClass,
@NotNull final Class<? extends V> valueClass) {
return new LoadingMap<>(backingMap, new AutoInstantiatingLoader<>(keyClass, valueClass));
}
/**
* Creates a LoadingMap with an auto instantiating loader.
*
* Will auto construct class of of Value when not found
*
* Since this uses Reflection, It is more effecient to define your own static loader
* than using this helper, but if performance is not critical, this is easier.
*
* @param backingMap Actual map being used.
* @param valueClass Class used for the V generic
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newAutoMap(@NotNull Map<K, V> backingMap,
@NotNull final Class<? extends V> valueClass) {
return newAutoMap(backingMap, null, valueClass);
}
/**
* @see #newAutoMap
*
* new Auto initializing map using a HashMap.
*
* @param keyClass Class used for the K generic
* @param valueClass Class used for the V generic
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newHashAutoMap(@Nullable final Class<? extends K> keyClass, @NotNull final Class<? extends V> valueClass) {
return newAutoMap(new HashMap<>(), keyClass, valueClass);
}
/**
* @see #newAutoMap
*
* new Auto initializing map using a HashMap.
*
* @param valueClass Class used for the V generic
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newHashAutoMap(@NotNull final Class<? extends V> valueClass) {
return newHashAutoMap(null, valueClass);
}
/**
* @see #newAutoMap
*
* new Auto initializing map using a HashMap.
*
* @param keyClass Class used for the K generic
* @param valueClass Class used for the V generic
* @param initialCapacity Initial capacity to use
* @param loadFactor Load factor to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newHashAutoMap(@Nullable final Class<? extends K> keyClass, @NotNull final Class<? extends V> valueClass, int initialCapacity, float loadFactor) {
return newAutoMap(new HashMap<>(initialCapacity, loadFactor), keyClass, valueClass);
}
/**
* @see #newAutoMap
*
* new Auto initializing map using a HashMap.
*
* @param valueClass Class used for the V generic
* @param initialCapacity Initial capacity to use
* @param loadFactor Load factor to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map that auto instantiates on .get()
*/
@NotNull
public static <K, V> Map<K, V> newHashAutoMap(@NotNull final Class<? extends V> valueClass, int initialCapacity, float loadFactor) {
return newHashAutoMap(null, valueClass, initialCapacity, loadFactor);
}
/**
* Initializes an auto loading map using a HashMap
*
* @param loader Loader to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader) {
return new LoadingMap<>(new HashMap<>(), loader);
}
/**
* Initializes an auto loading map using a HashMap
*
* @param loader Loader to use
* @param initialCapacity Initial capacity to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader, int initialCapacity) {
return new LoadingMap<>(new HashMap<>(initialCapacity), loader);
}
/**
* Initializes an auto loading map using a HashMap
*
* @param loader Loader to use
* @param initialCapacity Initial capacity to use
* @param loadFactor Load factor to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> newHashMap(@NotNull Function<K, V> loader, int initialCapacity, float loadFactor) {
return new LoadingMap<>(new HashMap<>(initialCapacity, loadFactor), loader);
}
/**
* Initializes an auto loading map using an Identity HashMap
*
* @param loader Loader to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> newIdentityHashMap(@NotNull Function<K, V> loader) {
return new LoadingMap<>(new IdentityHashMap<>(), loader);
}
/**
* Initializes an auto loading map using an Identity HashMap
*
* @param loader Loader to use
* @param initialCapacity Initial capacity to use
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> newIdentityHashMap(@NotNull Function<K, V> loader, int initialCapacity) {
return new LoadingMap<>(new IdentityHashMap<>(initialCapacity), loader);
}
@Override
public int size() {return backingMap.size();}
@Override
public boolean isEmpty() {return backingMap.isEmpty();}
@Override
public boolean containsKey(@Nullable Object key) {return backingMap.containsKey(key);}
@Override
public boolean containsValue(@Nullable Object value) {return backingMap.containsValue(value);}
@Nullable
@Override
public V get(@Nullable Object key) {
V v = backingMap.get(key);
if (v != null) {
return v;
}
return backingMap.computeIfAbsent((K) key, loader);
}
@Nullable
public V put(@Nullable K key, @Nullable V value) {return backingMap.put(key, value);}
@Nullable
@Override
public V remove(@Nullable Object key) {return backingMap.remove(key);}
public void putAll(@NotNull Map<? extends K, ? extends V> m) {backingMap.putAll(m);}
@Override
public void clear() {backingMap.clear();}
@NotNull
@Override
public Set<K> keySet() {return backingMap.keySet();}
@NotNull
@Override
public Collection<V> values() {return backingMap.values();}
@Override
public boolean equals(@Nullable Object o) {return backingMap.equals(o);}
@Override
public int hashCode() {return backingMap.hashCode();}
@NotNull
@Override
public Set<Entry<K, V>> entrySet() {
return backingMap.entrySet();
}
@NotNull
public LoadingMap<K, V> clone() {
return new LoadingMap<>(backingMap, loader);
}
private static class AutoInstantiatingLoader<K, V> implements Function<K, V> {
final Constructor<? extends V> constructor;
private final Class<? extends V> valueClass;
AutoInstantiatingLoader(@Nullable Class<? extends K> keyClass, @NotNull Class<? extends V> valueClass) {
try {
this.valueClass = valueClass;
if (keyClass != null) {
constructor = valueClass.getConstructor(keyClass);
} else {
constructor = null;
}
} catch (NoSuchMethodException e) {
throw new IllegalStateException(
valueClass.getName() + " does not have a constructor for " + (keyClass != null ? keyClass.getName() : null));
}
}
@NotNull
@Override
public V apply(@Nullable K input) {
try {
return (constructor != null ? constructor.newInstance(input) : valueClass.newInstance());
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object object) {
return false;
}
}
/**
* Due to java stuff, you will need to cast it to (Function) for some cases
*
* @param <T> Type
*/
public abstract static class Feeder <T> implements Function<T, T> {
@Nullable
@Override
public T apply(@Nullable Object input) {
return apply();
}
@Nullable
public abstract T apply();
}
}

View File

@@ -1,111 +0,0 @@
/*
* This file is licensed under the MIT License (MIT).
*
* Copyright (c) 2014 Daniel Ennis <http://aikar.co>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package co.aikar.util;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Implements a Most Recently Used cache in front of a backing map, to quickly access the last accessed result.
*
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
*/
public class MRUMapCache<K, V> extends AbstractMap<K, V> {
final Map<K, V> backingMap;
Object cacheKey;
V cacheValue;
public MRUMapCache(@NotNull final Map<K, V> backingMap) {
this.backingMap = backingMap;
}
public int size() {return backingMap.size();}
public boolean isEmpty() {return backingMap.isEmpty();}
public boolean containsKey(@Nullable Object key) {
return key != null && key.equals(cacheKey) || backingMap.containsKey(key);
}
public boolean containsValue(@Nullable Object value) {
return value != null && value == cacheValue || backingMap.containsValue(value);
}
@Nullable
public V get(@Nullable Object key) {
if (cacheKey != null && cacheKey.equals(key)) {
return cacheValue;
}
cacheKey = key;
return cacheValue = backingMap.get(key);
}
@Nullable
public V put(@Nullable K key, @Nullable V value) {
cacheKey = key;
return cacheValue = backingMap.put(key, value);
}
@Nullable
public V remove(@Nullable Object key) {
if (key != null && key.equals(cacheKey)) {
cacheKey = null;
}
return backingMap.remove(key);
}
public void putAll(@NotNull Map<? extends K, ? extends V> m) {backingMap.putAll(m);}
public void clear() {
cacheKey = null;
cacheValue = null;
backingMap.clear();
}
@NotNull
public Set<K> keySet() {return backingMap.keySet();}
@NotNull
public Collection<V> values() {return backingMap.values();}
@NotNull
public Set<Map.Entry<K, V>> entrySet() {return backingMap.entrySet();}
/**
* Wraps the specified map with a most recently used cache
*
* @param map Map to be wrapped
* @param <K> Key Type of the Map
* @param <V> Value Type of the Map
* @return Map
*/
@NotNull
public static <K, V> Map<K, V> of(@NotNull Map<K, V> map) {
return new MRUMapCache<K, V>(map);
}
}

View File

@@ -1,190 +0,0 @@
/*
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
*/
package com.destroystokyo.paper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class MaterialSetTag implements Tag<Material> {
private final NamespacedKey key;
private final Set<Material> materials;
/**
* @deprecated Use NamespacedKey version of constructor
*/
@Deprecated
public MaterialSetTag(@NotNull Predicate<Material> filter) {
this(null, Stream.of(Material.values()).filter(filter).collect(Collectors.toList()));
}
/**
* @deprecated Use NamespacedKey version of constructor
*/
@Deprecated
public MaterialSetTag(@NotNull Collection<Material> materials) {
this(null, materials);
}
/**
* @deprecated Use NamespacedKey version of constructor
*/
@Deprecated
public MaterialSetTag(@NotNull Material... materials) {
this(null, materials);
}
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Predicate<Material> filter) {
this(key, Stream.of(Material.values()).filter(filter).collect(Collectors.toList()));
}
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Material... materials) {
this(key, Lists.newArrayList(materials));
}
public MaterialSetTag(@Nullable NamespacedKey key, @NotNull Collection<Material> materials) {
this.key = key != null ? key : NamespacedKey.randomKey();
this.materials = Sets.newEnumSet(materials, Material.class);
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
}
@NotNull
public MaterialSetTag add(@NotNull Tag<Material>... tags) {
for (Tag<Material> tag : tags) {
add(tag.getValues());
}
return this;
}
@NotNull
public MaterialSetTag add(@NotNull MaterialSetTag... tags) {
for (Tag<Material> tag : tags) {
add(tag.getValues());
}
return this;
}
@NotNull
public MaterialSetTag add(@NotNull Material... material) {
this.materials.addAll(Lists.newArrayList(material));
return this;
}
@NotNull
public MaterialSetTag add(@NotNull Collection<Material> materials) {
this.materials.addAll(materials);
return this;
}
@NotNull
public MaterialSetTag contains(@NotNull String with) {
return add(mat -> mat.name().contains(with));
}
@NotNull
public MaterialSetTag endsWith(@NotNull String with) {
return add(mat -> mat.name().endsWith(with));
}
@NotNull
public MaterialSetTag startsWith(@NotNull String with) {
return add(mat -> mat.name().startsWith(with));
}
@NotNull
public MaterialSetTag add(@NotNull Predicate<Material> filter) {
add(Stream.of(Material.values()).filter(((Predicate<Material>) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList()));
return this;
}
@NotNull
public MaterialSetTag not(@NotNull MaterialSetTag tags) {
not(tags.getValues());
return this;
}
@NotNull
public MaterialSetTag not(@NotNull Material... material) {
this.materials.removeAll(Lists.newArrayList(material));
return this;
}
@NotNull
public MaterialSetTag not(@NotNull Collection<Material> materials) {
this.materials.removeAll(materials);
return this;
}
@NotNull
public MaterialSetTag not(@NotNull Predicate<Material> filter) {
not(Stream.of(Material.values()).filter(((Predicate<Material>) Material::isLegacy).negate()).filter(filter).collect(Collectors.toList()));
return this;
}
@NotNull
public MaterialSetTag notEndsWith(@NotNull String with) {
return not(mat -> mat.name().endsWith(with));
}
@NotNull
public MaterialSetTag notStartsWith(@NotNull String with) {
return not(mat -> mat.name().startsWith(with));
}
@NotNull
public Set<Material> getValues() {
return this.materials;
}
public boolean isTagged(@NotNull BlockData block) {
return isTagged(block.getMaterial());
}
public boolean isTagged(@NotNull BlockState block) {
return isTagged(block.getType());
}
public boolean isTagged(@NotNull Block block) {
return isTagged(block.getType());
}
public boolean isTagged(@NotNull ItemStack item) {
return isTagged(item.getType());
}
public boolean isTagged(@NotNull Material material) {
return this.materials.contains(material);
}
@NotNull
public MaterialSetTag ensureSize(@NotNull String label, int size) {
long actual = this.materials.stream().filter(((Predicate<Material>) Material::isLegacy).negate()).count();
if (size != actual) {
throw new IllegalStateException(label + " - Expected " + size + " materials, got " + actual);
}
return this;
}
}

View File

@@ -1,382 +0,0 @@
/*
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.destroystokyo.paper;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;
/**
* Represents a collection tags to identify materials that share common properties.
* Will map to minecraft for missing tags, as well as custom ones that may be useful.
*/
@SuppressWarnings({"NonFinalUtilityClass", "unused", "WeakerAccess"})
public class MaterialTags {
private static NamespacedKey keyFor(String key) {
//noinspection deprecation
return new NamespacedKey("paper", key + "_settag");
}
public static final MaterialSetTag ARROWS = new MaterialSetTag(keyFor("arrows"))
.endsWith("ARROW")
.ensureSize("ARROWS", 3);
/**
* Cover all 16 colors of beds.
*/
public static final MaterialSetTag BEDS = new MaterialSetTag(keyFor("beds"))
.endsWith("_BED")
.ensureSize("BEDS", 16);
/**
* Covers all bucket items.
*/
public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets"))
.endsWith("BUCKET")
.ensureSize("BUCKETS", 8);
/**
* Covers coal and charcoal.
*/
public static final MaterialSetTag COALS = new MaterialSetTag(keyFor("coals"))
.add(Material.COAL, Material.CHARCOAL);
/**
* Covers both cobblestone wall variants.
*/
public static final MaterialSetTag COBBLESTONE_WALLS = new MaterialSetTag(keyFor("cobblestone_walls"))
.endsWith("COBBLESTONE_WALL")
.ensureSize("COBBLESTONE_WALLS", 2);
/**
* Covers both cobblestone and mossy Cobblestone.
*/
public static final MaterialSetTag COBBLESTONES = new MaterialSetTag(keyFor("cobblestones"))
.add(Material.COBBLESTONE, Material.MOSSY_COBBLESTONE);
/**
* Covers all 16 colors of concrete.
*/
public static final MaterialSetTag CONCRETES = new MaterialSetTag(keyFor("concretes"))
.endsWith("_CONCRETE")
.ensureSize("CONCRETES", 16);
/**
* Covers all 16 colors of concrete powder.
*/
public static final MaterialSetTag CONCRETE_POWDER = new MaterialSetTag(keyFor("concrete_powder"))
.endsWith("_CONCRETE_POWDER")
.ensureSize("CONCRETE_POWDER", 16);
/**
* Covers the two types of cooked fish.
*/
public static final MaterialSetTag COOKED_FISH = new MaterialSetTag(keyFor("cooked_fish"))
.add(Material.COOKED_COD, Material.COOKED_SALMON);
/**
* Covers all 16 dyes.
*/
public static final MaterialSetTag DYES = new MaterialSetTag(keyFor("dyes"))
.endsWith("_DYE")
.add(Material.BONE_MEAL,
Material.CACTUS_GREEN,
Material.COCOA_BEANS,
Material.DANDELION_YELLOW,
Material.INK_SAC,
Material.LAPIS_LAZULI,
Material.ROSE_RED
)
.ensureSize("DYES", 16);
/**
* Covers all 6 wood variants of gates.
*/
public static final MaterialSetTag FENCE_GATES = new MaterialSetTag(keyFor("fence_gates"))
.endsWith("_GATE")
.ensureSize("FENCE_GATES", 6);
/**
* Covers all 6 wood variants and nether brick fence.
*/
public static final MaterialSetTag FENCES = new MaterialSetTag(keyFor("fences"))
.endsWith("_FENCE")
.ensureSize("FENCES", 7);
/**
* Covers all 4 variants of fish buckets.
*/
public static final MaterialSetTag FISH_BUCKETS = new MaterialSetTag(keyFor("fish_buckets"))
.add(Material.COD_BUCKET, Material.PUFFERFISH_BUCKET, Material.SALMON_BUCKET, Material.TROPICAL_FISH_BUCKET);
/**
* Covers the non-colored glass and 16 stained glass (not panes).
*/
public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass"))
.endsWith("_GLASS")
.add(Material.GLASS)
.ensureSize("GLASS", 17);
/**
* Covers the non-colored glass panes and 16 stained glass panes (panes only).
*/
public static final MaterialSetTag GLASS_PANES = new MaterialSetTag(keyFor("glass_panes"))
.endsWith("GLASS_PANE")
.ensureSize("GLASS_PANES", 17);
/**
* Covers all 16 glazed terracotta blocks.
*/
public static final MaterialSetTag GLAZED_TERRACOTTA = new MaterialSetTag(keyFor("glazed_terracotta"))
.endsWith("GLAZED_TERRACOTTA")
.ensureSize("GLAZED_TERRACOTTA", 16);
/**
* Covers the 16 colors of stained terracotta.
*/
public static final MaterialSetTag STAINED_TERRACOTTA = new MaterialSetTag(keyFor("stained_terracotta"))
.endsWith("TERRACOTTA")
.not(Material.TERRACOTTA)
.notEndsWith("GLAZED_TERRACOTTA")
.ensureSize("STAINED_TERRACOTTA", 16);
/**
* Covers terracotta along with the 16 stained variants.
*/
public static final MaterialSetTag TERRACOTTA = new MaterialSetTag(keyFor("terracotta"))
.endsWith("TERRACOTTA")
.ensureSize("TERRACOTTA", 33);
/**
* Covers both golden apples.
*/
public static final MaterialSetTag GOLDEN_APPLES = new MaterialSetTag(keyFor("golden_apples"))
.endsWith("GOLDEN_APPLE")
.ensureSize("GOLDEN_APPLES", 2);
/**
* Covers the 3 variants of horse armor.
*/
public static final MaterialSetTag HORSE_ARMORS = new MaterialSetTag(keyFor("horse_armors"))
.endsWith("_HORSE_ARMOR")
.ensureSize("HORSE_ARMORS", 3);
/**
* Covers the 6 variants of infested blocks.
*/
public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks"))
.startsWith("INFESTED_")
.ensureSize("INFESTED_BLOCKS", 6);
/**
* Covers the 3 variants of mushroom blocks.
*/
public static final MaterialSetTag MUSHROOM_BLOCKS = new MaterialSetTag(keyFor("mushroom_blocks"))
.endsWith("MUSHROOM_BLOCK")
.add(Material.MUSHROOM_STEM)
.ensureSize("MUSHROOM_BLOCKS", 3);
/**
* Covers both mushrooms.
*/
public static final MaterialSetTag MUSHROOMS = new MaterialSetTag(keyFor("mushrooms"))
.add(Material.BROWN_MUSHROOM, Material.RED_MUSHROOM);
/**
* Covers all 12 music disc items.
*/
public static final MaterialSetTag MUSIC_DISCS = new MaterialSetTag(keyFor("music_discs"))
.startsWith("MUSIC_DISC_")
.ensureSize("MUSIC_DISCS", 12);
/**
* Covers all 8 ores.
*/
public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores"))
.endsWith("_ORE")
.ensureSize("ORES", 8);
/**
* Covers all piston typed items and blocks including the piston head and moving piston.
*/
public static final MaterialSetTag PISTONS = new MaterialSetTag(keyFor("pistons"))
.contains("PISTON")
.ensureSize("PISTONS", 4);
/**
* Covers all potato items.
*/
public static final MaterialSetTag POTATOES = new MaterialSetTag(keyFor("potatoes"))
.endsWith("POTATO")
.ensureSize("POTATOES", 3);
/**
* Covers all 6 wooden pressure plates and the 2 weighted pressure plates and 1 stone pressure plate.
*/
public static final MaterialSetTag PRESSURE_PLATES = new MaterialSetTag(keyFor("pressure_plates"))
.endsWith("_PRESSURE_PLATE")
.ensureSize("PRESSURE_PLATES", 9);
/**
* Covers the 3 variants of prismarine blocks.
*/
public static final MaterialSetTag PRISMARINE = new MaterialSetTag(keyFor("prismarine"))
.add(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE);
/**
* Covers the 3 variants of prismarine slabs.
*/
public static final MaterialSetTag PRISMARINE_SLABS = new MaterialSetTag(keyFor("prismarine_slabs"))
.add(Material.PRISMARINE_SLAB, Material.PRISMARINE_BRICK_SLAB, Material.DARK_PRISMARINE_SLAB);
/**
* Covers the 3 variants of prismarine stairs.
*/
public static final MaterialSetTag PRISMARINE_STAIRS = new MaterialSetTag(keyFor("prismarine_stairs"))
.add(Material.PRISMARINE_STAIRS, Material.PRISMARINE_BRICK_STAIRS, Material.DARK_PRISMARINE_STAIRS);
/**
* Covers the 3 variants of pumpkins.
*/
public static final MaterialSetTag PUMPKINS = new MaterialSetTag(keyFor("pumpkins"))
.add(Material.CARVED_PUMPKIN, Material.JACK_O_LANTERN, Material.PUMPKIN);
/**
* Covers the 4 variants of quartz blocks.
*/
public static final MaterialSetTag QUARTZ_BLOCKS = new MaterialSetTag(keyFor("quartz_blocks"))
.add(Material.QUARTZ_BLOCK, Material.QUARTZ_PILLAR, Material.CHISELED_QUARTZ_BLOCK, Material.SMOOTH_QUARTZ);
/**
* Covers all uncooked fish items.
*/
public static final MaterialSetTag RAW_FISH = new MaterialSetTag(keyFor("raw_fish"))
.add(Material.COD, Material.PUFFERFISH, Material.SALMON, Material.TROPICAL_FISH);
/**
* Covers the 4 variants of red sandstone blocks.
*/
public static final MaterialSetTag RED_SANDSTONES = new MaterialSetTag(keyFor("red_sandstones"))
.endsWith("RED_SANDSTONE")
.ensureSize("RED_SANDSTONES", 4);
/**
* Covers the 4 variants of sandstone blocks.
*/
public static final MaterialSetTag SANDSTONES = new MaterialSetTag(keyFor("sandstones"))
.add(Material.SANDSTONE, Material.CHISELED_SANDSTONE, Material.CUT_SANDSTONE, Material.SMOOTH_SANDSTONE);
/**
* Covers sponge and wet sponge.
*/
public static final MaterialSetTag SPONGES = new MaterialSetTag(keyFor("sponges"))
.endsWith("SPONGE")
.ensureSize("SPONGES", 2);
/**
* Covers the non-colored and 16 colored shulker boxes.
*/
public static final MaterialSetTag SHULKER_BOXES = new MaterialSetTag(keyFor("shulker_boxes"))
.endsWith("SHULKER_BOX")
.ensureSize("SHULKER_BOXES", 17);
/**
* Covers zombie, creeper, skeleton, dragon, and player heads.
*/
public static final MaterialSetTag SKULLS = new MaterialSetTag(keyFor("skulls"))
.endsWith("_HEAD")
.endsWith("_SKULL")
.not(Material.PISTON_HEAD)
.ensureSize("SKULLS", 12);
/**
* Covers all spawn egg items.
*/
public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs"))
.endsWith("_SPAWN_EGG")
.ensureSize("SPAWN_EGGS", 51);
/**
* Covers all 16 colors of stained glass.
*/
public static final MaterialSetTag STAINED_GLASS = new MaterialSetTag(keyFor("stained_glass"))
.endsWith("_STAINED_GLASS")
.ensureSize("STAINED_GLASS", 16);
/**
* Covers all 16 colors of stained glass panes.
*/
public static final MaterialSetTag STAINED_GLASS_PANES = new MaterialSetTag(keyFor("stained_glass_panes"))
.endsWith("STAINED_GLASS_PANE")
.ensureSize("STAINED_GLASS_PANES", 16);
/**
* Covers all 7 variants of trapdoors.
*/
public static final MaterialSetTag TRAPDOORS = new MaterialSetTag(keyFor("trapdoors"))
.endsWith("_TRAPDOOR")
.ensureSize("TRAPDOORS", 7);
/**
* Covers all 6 wood variants of fences.
*/
public static final MaterialSetTag WOODEN_FENCES = new MaterialSetTag(keyFor("wooden_fences"))
.endsWith("_FENCE")
.not(Material.NETHER_BRICK_FENCE)
.ensureSize("WOODEN_FENCES", 6);
/**
* Covers all 6 wood variants of trapdoors.
*/
public static final MaterialSetTag WOODEN_TRAPDOORS = new MaterialSetTag(keyFor("wooden_trapdoors"))
.endsWith("_TRAPDOOR")
.not(Material.IRON_TRAPDOOR)
.ensureSize("WOODEN_TRAPDOORS", 6);
public static final MaterialSetTag WOODEN_GATES = new MaterialSetTag(keyFor("wooden_gates"))
.endsWith("_GATE")
.ensureSize("WOODEN_GATES", 6);
public static final MaterialSetTag PURPUR = new MaterialSetTag(keyFor("purpur"))
.startsWith("PURPUR_")
.ensureSize("PURPUR", 4);
public static final MaterialSetTag SIGNS = new MaterialSetTag(keyFor("signs"))
.add(Material.SIGN, Material.WALL_SIGN)
.ensureSize("SIGNS", 2);
public static final MaterialSetTag TORCH = new MaterialSetTag(keyFor("torch"))
.add(Material.TORCH, Material.WALL_TORCH)
.ensureSize("TORCH", 2);
public static final MaterialSetTag REDSTONE_TORCH = new MaterialSetTag(keyFor("restone_torch"))
.add(Material.REDSTONE_TORCH, Material.REDSTONE_WALL_TORCH)
.ensureSize("REDSTONE_TORCH", 2);
@SuppressWarnings("unchecked")
public static final MaterialSetTag COLORABLE = new MaterialSetTag(keyFor("colorable"))
.add(Tag.WOOL, Tag.CARPETS).add(SHULKER_BOXES, STAINED_GLASS, STAINED_GLASS_PANES, CONCRETES, BEDS);
//.ensureSize("COLORABLE", 81); unit test don't have the vanilla item tags, so counts don't line up for real
}

View File

@@ -1,40 +0,0 @@
package com.destroystokyo.paper;
import org.jetbrains.annotations.NotNull;
/**
* Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements
* or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements
*
* Namespaces may only contain lowercase alphanumeric characters, periods,
* underscores, and hyphens.
* <p>
* Keys may only contain lowercase alphanumeric characters, periods,
* underscores, hyphens, and forward slashes.
* <p>
* You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey}
* or {@link com.destroystokyo.paper.NamespacedTag} as needed instead.
*/
public interface Namespaced {
/**
* Gets the namespace this resource is a part of
* <p>
* This is contractually obligated to only contain lowercase alphanumeric characters,
* periods, underscores, and hyphens.
*
* @return resource namespace
*/
@NotNull
String getNamespace();
/**
* Gets the key corresponding to this resource
* <p>
* This is contractually obligated to only contain lowercase alphanumeric characters,
* periods, underscores, hyphens, and forward slashes.
*
* @return resource key
*/
@NotNull
String getKey();
}

View File

@@ -1,142 +0,0 @@
package com.destroystokyo.paper;
import com.google.common.base.Preconditions;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
/**
* Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace
* and a key.
* <p>
* Namespaces may only contain lowercase alphanumeric characters, periods,
* underscores, and hyphens.
* <p>
* Keys may only contain lowercase alphanumeric characters, periods,
* underscores, hyphens, and forward slashes.
*
*/
// Paper - entire class, based on org.bukkit.NamespacedKey
public final class NamespacedTag implements com.destroystokyo.paper.Namespaced {
/**
* The namespace representing all inbuilt keys.
*/
public static final String MINECRAFT = "minecraft";
/**
* The namespace representing all keys generated by Bukkit for backwards
* compatibility measures.
*/
public static final String BUKKIT = "bukkit";
//
private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+");
private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+");
//
private final String namespace;
private final String key;
/**
* Create a key in a specific namespace.
*
* @param namespace String representing a grouping of keys
* @param key Name for this specific key
* @deprecated should never be used by plugins, for internal use only!!
*/
@Deprecated
public NamespacedTag(@NotNull String namespace, @NotNull String key) {
Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key);
this.namespace = namespace;
this.key = key;
String string = toString();
Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string);
}
/**
* Create a key in the plugin's namespace.
* <p>
* Namespaces may only contain lowercase alphanumeric characters, periods,
* underscores, and hyphens.
* <p>
* Keys may only contain lowercase alphanumeric characters, periods,
* underscores, hyphens, and forward slashes.
*
* @param plugin the plugin to use for the namespace
* @param key the key to create
*/
public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) {
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
this.key = key.toLowerCase().toLowerCase(Locale.ROOT);
// Check validity after normalization
Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
String string = toString();
Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string);
}
@NotNull
public String getNamespace() {
return namespace;
}
@NotNull
public String getKey() {
return key;
}
@Override
public int hashCode() {
int hash = 7;
hash = 47 * hash + this.namespace.hashCode();
hash = 47 * hash + this.key.hashCode();
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final NamespacedTag other = (NamespacedTag) obj;
return this.namespace.equals(other.namespace) && this.key.equals(other.key);
}
@Override
public String toString() {
return "#" + this.namespace + ":" + this.key;
}
/**
* Return a new random key in the {@link #BUKKIT} namespace.
*
* @return new key
* @deprecated should never be used by plugins, for internal use only!!
*/
@Deprecated
public static NamespacedTag randomKey() {
return new NamespacedTag(BUKKIT, UUID.randomUUID().toString());
}
/**
* Get a key in the Minecraft namespace.
*
* @param key the key to use
* @return new key in the Minecraft namespace
*/
@NotNull
public static NamespacedTag minecraft(@NotNull String key) {
return new NamespacedTag(MINECRAFT, key);
}
}

View File

@@ -1,478 +0,0 @@
package com.destroystokyo.paper;
import com.google.common.collect.Lists;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.util.NumberConversions;
import java.util.Collection;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Helps prepare a particle to be sent to players.
*
* Usage of the builder is preferred over the super long {@link World#spawnParticle(Particle, Location, int, double, double, double, double, Object)} API
*/
public class ParticleBuilder {
private Particle particle;
private List<Player> receivers;
private Player source;
private Location location;
private int count = 1;
private double offsetX = 0, offsetY = 0, offsetZ = 0;
private double extra = 1;
private Object data;
private boolean force = true;
public ParticleBuilder(@NotNull Particle particle) {
this.particle = particle;
}
/**
* Sends the particle to all receiving players (or all). This method is safe to use
* Asynchronously
*
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder spawn() {
if (this.location == null) {
throw new IllegalStateException("Please specify location for this particle");
}
location.getWorld().spawnParticle(particle, receivers, source,
location.getX(), location.getY(), location.getZ(),
count, offsetX, offsetY, offsetZ, extra, data, force
);
return this;
}
/**
* @return The particle going to be sent
*/
@NotNull
public Particle particle() {
return particle;
}
/**
* Changes what particle will be sent
*
* @param particle The particle
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder particle(@NotNull Particle particle) {
this.particle = particle;
return this;
}
/**
* @return List of players who will receive the particle, or null for all in world
*/
@Nullable
public List<Player> receivers() {
return receivers;
}
/**
* Example use:
*
* builder.receivers(16); if (builder.hasReceivers()) { sendParticleAsync(builder); }
*
* @return If this particle is going to be sent to someone
*/
public boolean hasReceivers() {
return (receivers == null && !location.getWorld().getPlayers().isEmpty()) || (
receivers != null && !receivers.isEmpty());
}
/**
* Sends this particle to all players in the world. This is rather silly and you should likely not
* be doing this.
*
* Just be a logical person and use receivers by radius or collection.
*
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder allPlayers() {
this.receivers = null;
return this;
}
/**
* @param receivers List of players to receive this particle, or null for all players in the
* world
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(@Nullable List<Player> receivers) {
// Had to keep this as we first made API List<> and not Collection, but removing this may break plugins compiled on older jars
// TODO: deprecate?
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
return this;
}
/**
* @param receivers List of players to receive this particle, or null for all players in the
* world
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(@Nullable Collection<Player> receivers) {
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
return this;
}
/**
* @param receivers List of players to be receive this particle, or null for all players in the
* world
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(@Nullable Player... receivers) {
this.receivers = receivers != null ? Lists.newArrayList(receivers) : null;
return this;
}
/**
* Selects all players within a cuboid selection around the particle location, within the
* specified bounding box. If you want a more spherical check, see {@link #receivers(int,
* boolean)}
*
* @param radius amount to add on all axis
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(int radius) {
return receivers(radius, radius);
}
/**
* Selects all players within the specified radius around the particle location. If byDistance is
* false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
* true, radius is tested by distance in a spherical shape
*
* @param radius amount to add on each axis
* @param byDistance true to use a spherical radius, false to use a cuboid
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(int radius, boolean byDistance) {
if (!byDistance) {
return receivers(radius, radius, radius);
} else {
this.receivers = Lists.newArrayList();
for (Player nearbyPlayer : location.getWorld()
.getNearbyPlayers(location, radius, radius, radius)) {
Location loc = nearbyPlayer.getLocation();
double x = NumberConversions.square(location.getX() - loc.getX());
double y = NumberConversions.square(location.getY() - loc.getY());
double z = NumberConversions.square(location.getZ() - loc.getZ());
if (Math.sqrt(x + y + z) > radius) {
continue;
}
this.receivers.add(nearbyPlayer);
}
return this;
}
}
/**
* Selects all players within a cuboid selection around the particle location, within the
* specified bounding box. Allows specifying a different Y size than X and Z If you want a more
* cylinder check, see {@link #receivers(int, int, boolean)} If you want a more spherical check,
* see {@link #receivers(int, boolean)}
*
* @param xzRadius amount to add on the x/z axis
* @param yRadius amount to add on the y axis
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(int xzRadius, int yRadius) {
return receivers(xzRadius, yRadius, xzRadius);
}
/**
* Selects all players within the specified radius around the particle location. If byDistance is
* false, behavior uses cuboid selection the same as {@link #receivers(int, int)} If byDistance is
* true, radius is tested by distance on the y plane and on the x/z plane, in a cylinder shape.
*
* @param xzRadius amount to add on the x/z axis
* @param yRadius amount to add on the y axis
* @param byDistance true to use a cylinder shape, false to use cuboid
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(int xzRadius, int yRadius, boolean byDistance) {
if (!byDistance) {
return receivers(xzRadius, yRadius, xzRadius);
} else {
this.receivers = Lists.newArrayList();
for (Player nearbyPlayer : location.getWorld()
.getNearbyPlayers(location, xzRadius, yRadius, xzRadius)) {
Location loc = nearbyPlayer.getLocation();
if (Math.abs(loc.getY() - this.location.getY()) > yRadius) {
continue;
}
double x = NumberConversions.square(location.getX() - loc.getX());
double z = NumberConversions.square(location.getZ() - loc.getZ());
if (x + z > NumberConversions.square(xzRadius)) {
continue;
}
this.receivers.add(nearbyPlayer);
}
return this;
}
}
/**
* Selects all players within a cuboid selection around the particle location, within the
* specified bounding box. If you want a more cylinder check, see {@link #receivers(int, int,
* boolean)} If you want a more spherical check, see {@link #receivers(int, boolean)}
*
* @param xRadius amount to add on the x axis
* @param yRadius amount to add on the y axis
* @param zRadius amount to add on the z axis
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder receivers(int xRadius, int yRadius, int zRadius) {
if (location == null) {
throw new IllegalStateException("Please set location first");
}
return receivers(location.getWorld().getNearbyPlayers(location, xRadius, yRadius, zRadius));
}
/**
* @return The player considered the source of this particle (for Visibility concerns), or null
*/
@Nullable
public Player source() {
return source;
}
/**
* Sets the source of this particle for visibility concerns (Vanish API)
*
* @param source The player who is considered the source
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder source(@Nullable Player source) {
this.source = source;
return this;
}
/**
* @return Location of where the particle will spawn
*/
@Nullable
public Location location() {
return location;
}
/**
* Sets the location of where to spawn the particle
*
* @param location The location of the particle
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder location(@NotNull Location location) {
this.location = location.clone();
return this;
}
/**
* Sets the location of where to spawn the particle
*
* @param world World to spawn particle in
* @param x X location
* @param y Y location
* @param z Z location
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder location(@NotNull World world, double x, double y, double z) {
this.location = new Location(world, x, y, z);
return this;
}
/**
* @return Number of particles to spawn
*/
public int count() {
return count;
}
/**
* Sets the number of particles to spawn
*
* @param count Number of particles
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder count(int count) {
this.count = count;
return this;
}
/**
* Particle offset X. Varies by particle on how this is used
*
* @return Particle offset X.
*/
public double offsetX() {
return offsetX;
}
/**
* Particle offset Y. Varies by particle on how this is used
*
* @return Particle offset Y.
*/
public double offsetY() {
return offsetY;
}
/**
* Particle offset Z. Varies by particle on how this is used
*
* @return Particle offset Z.
*/
public double offsetZ() {
return offsetZ;
}
/**
* Sets the particle offset. Varies by particle on how this is used
*
* @param offsetX Particle offset X
* @param offsetY Particle offset Y
* @param offsetZ Particle offset Z
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder offset(double offsetX, double offsetY, double offsetZ) {
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
return this;
}
/**
* Gets the Particle extra data. Varies by particle on how this is used
*
* @return the extra particle data
*/
public double extra() {
return extra;
}
/**
* Sets the particle extra data. Varies by particle on how this is used
*
* @param extra the extra particle data
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder extra(double extra) {
this.extra = extra;
return this;
}
/**
* Gets the particle custom data. Varies by particle on how this is used
*
* @param <T> The Particle data type
* @return the ParticleData for this particle
*/
@Nullable
public <T> T data() {
//noinspection unchecked
return (T) data;
}
/**
* Sets the particle custom data. Varies by particle on how this is used
*
* @param data The new particle data
* @param <T> The Particle data type
* @return a reference to this object.
*/
@NotNull
public <T> ParticleBuilder data(@Nullable T data) {
this.data = data;
return this;
}
/**
* Sets whether the particle is forcefully shown to the player. If forced, the particle will show
* faraway, as far as the player's view distance allows. If false, the particle will show
* according to the client's particle settings.
*
* @param force true to force, false for normal
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder force(boolean force) {
this.force = force;
return this;
}
/**
* Sets the particle Color. Only valid for REDSTONE.
*
* @param color the new particle color
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder color(@Nullable Color color) {
return color(color, 1);
}
/**
* Sets the particle Color and size. Only valid for REDSTONE.
*
* @param color the new particle color
* @param size the size of the particle
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder color(@Nullable Color color, float size) {
if (particle != Particle.REDSTONE && color != null) {
throw new IllegalStateException("Color may only be set on REDSTONE");
}
// We don't officially support reusing these objects, but here we go
if (color == null) {
if (data instanceof Particle.DustOptions) {
return data(null);
} else {
return this;
}
}
return data(new Particle.DustOptions(color, size));
}
/**
* Sets the particle Color.
* Only valid for REDSTONE.
* @param r red color component
* @param g green color component
* @param b blue color component
* @return a reference to this object.
*/
@NotNull
public ParticleBuilder color(int r, int g, int b) {
return color(Color.fromRGB(r, g, b));
}
}

View File

@@ -1,373 +0,0 @@
package com.destroystokyo.paper;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* Represents a title to may be sent to a {@link Player}.
*
* <p>A title can be sent without subtitle text.</p>
*/
public final class Title {
/**
* The default number of ticks for the title to fade in.
*/
public static final int DEFAULT_FADE_IN = 20;
/**
* The default number of ticks for the title to stay.
*/
public static final int DEFAULT_STAY = 200;
/**
* The default number of ticks for the title to fade out.
*/
public static final int DEFAULT_FADE_OUT = 20;
private final BaseComponent[] title;
private final BaseComponent[] subtitle;
private final int fadeIn;
private final int stay;
private final int fadeOut;
/**
* Create a title with the default time values and no subtitle.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @throws NullPointerException if the title is null
*/
public Title(@NotNull BaseComponent title) {
this(title, null);
}
/**
* Create a title with the default time values and no subtitle.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @throws NullPointerException if the title is null
*/
public Title(@NotNull BaseComponent[] title) {
this(title, null);
}
/**
* Create a title with the default time values and no subtitle.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @throws NullPointerException if the title is null
*/
public Title(@NotNull String title) {
this(title, null);
}
/**
* Create a title with the default time values.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
*/
public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle) {
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
}
/**
* Create a title with the default time values.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
*/
public Title(@NotNull BaseComponent[] title, @Nullable BaseComponent[] subtitle) {
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
}
/**
* Create a title with the default time values.
*
* <p>Times use default values.</p>
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
*/
public Title(@NotNull String title, @Nullable String subtitle) {
this(title, subtitle, DEFAULT_FADE_IN, DEFAULT_STAY, DEFAULT_FADE_OUT);
}
/**
* Creates a new title.
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
* @param fadeIn the number of ticks for the title to fade in
* @param stay the number of ticks for the title to stay on screen
* @param fadeOut the number of ticks for the title to fade out
* @throws IllegalArgumentException if any of the times are negative
*/
public Title(@NotNull BaseComponent title, @Nullable BaseComponent subtitle, int fadeIn, int stay, int fadeOut) {
this(
new BaseComponent[]{checkNotNull(title, "title")},
subtitle == null ? null : new BaseComponent[]{subtitle},
fadeIn,
stay,
fadeOut
);
}
/**
* Creates a new title.
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
* @param fadeIn the number of ticks for the title to fade in
* @param stay the number of ticks for the title to stay on screen
* @param fadeOut the number of ticks for the title to fade out
* @throws IllegalArgumentException if any of the times are negative
*/
public Title(@Nullable BaseComponent[] title, @NotNull BaseComponent[] subtitle, int fadeIn, int stay, int fadeOut) {
checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
checkArgument(stay >= 0, "Negative stay: %s", stay);
checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
this.title = checkNotNull(title, "title");
this.subtitle = subtitle;
this.fadeIn = fadeIn;
this.stay = stay;
this.fadeOut = fadeOut;
}
/**
* Creates a new title.
*
* <p>It is recommended to the {@link BaseComponent} constrctors.</p>
*
* @param title the main text of the title
* @param subtitle the secondary text of the title
* @param fadeIn the number of ticks for the title to fade in
* @param stay the number of ticks for the title to stay on screen
* @param fadeOut the number of ticks for the title to fade out
*/
public Title(@NotNull String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut) {
this(
TextComponent.fromLegacyText(checkNotNull(title, "title")),
subtitle == null ? null : TextComponent.fromLegacyText(subtitle),
fadeIn,
stay,
fadeOut
);
}
/**
* Gets the text of this title
*
* @return the text
*/
@NotNull
public BaseComponent[] getTitle() {
return this.title;
}
/**
* Gets the text of this title's subtitle
*
* @return the text
*/
@Nullable
public BaseComponent[] getSubtitle() {
return this.subtitle;
}
/**
* Gets the number of ticks to fade in.
*
* <p>The returned value is never negative.</p>
*
* @return the number of ticks to fade in
*/
public int getFadeIn() {
return this.fadeIn;
}
/**
* Gets the number of ticks to stay.
*
* <p>The returned value is never negative.</p>
*
* @return the number of ticks to stay
*/
public int getStay() {
return this.stay;
}
/**
* Gets the number of ticks to fade out.
*
* <p>The returned value is never negative.</p>
*
* @return the number of ticks to fade out
*/
public int getFadeOut() {
return this.fadeOut;
}
@NotNull
public static Builder builder() {
return new Builder();
}
/**
* A builder for creating titles
*/
public static final class Builder {
private BaseComponent[] title;
private BaseComponent[] subtitle;
private int fadeIn = DEFAULT_FADE_IN;
private int stay = DEFAULT_STAY;
private int fadeOut = DEFAULT_FADE_OUT;
/**
* Sets the title to the given text.
*
* @param title the title text
* @return this builder instance
* @throws NullPointerException if the title is null
*/
@NotNull
public Builder title(@NotNull BaseComponent title) {
return this.title(new BaseComponent[]{checkNotNull(title, "title")});
}
/**
* Sets the title to the given text.
*
* @param title the title text
* @return this builder instance
* @throws NullPointerException if the title is null
*/
@NotNull
public Builder title(@NotNull BaseComponent[] title) {
this.title = checkNotNull(title, "title");
return this;
}
/**
* Sets the title to the given text.
*
* <p>It is recommended to the {@link BaseComponent} methods.</p>
*
* @param title the title text
* @return this builder instance
* @throws NullPointerException if the title is null
*/
@NotNull
public Builder title(@NotNull String title) {
return this.title(TextComponent.fromLegacyText(checkNotNull(title, "title")));
}
/**
* Sets the subtitle to the given text.
*
* @param subtitle the title text
* @return this builder instance
*/
@NotNull
public Builder subtitle(@Nullable BaseComponent subtitle) {
return this.subtitle(subtitle == null ? null : new BaseComponent[]{subtitle});
}
/**
* Sets the subtitle to the given text.
*
* @param subtitle the title text
* @return this builder instance
*/
@NotNull
public Builder subtitle(@Nullable BaseComponent[] subtitle) {
this.subtitle = subtitle;
return this;
}
/**
* Sets the subtitle to the given text.
*
* <p>It is recommended to the {@link BaseComponent} methods.</p>
*
* @param subtitle the title text
* @return this builder instance
*/
@NotNull
public Builder subtitle(@Nullable String subtitle) {
return this.subtitle(subtitle == null ? null : TextComponent.fromLegacyText(subtitle));
}
/**
* Sets the number of ticks for the title to fade in
*
* @param fadeIn the number of ticks to fade in
* @return this builder instance
* @throws IllegalArgumentException if it is negative
*/
@NotNull
public Builder fadeIn(int fadeIn) {
checkArgument(fadeIn >= 0, "Negative fadeIn: %s", fadeIn);
this.fadeIn = fadeIn;
return this;
}
/**
* Sets the number of ticks for the title to stay.
*
* @param stay the number of ticks to stay
* @return this builder instance
* @throws IllegalArgumentException if it is negative
*/
@NotNull
public Builder stay(int stay) {
checkArgument(stay >= 0, "Negative stay: %s", stay);
this.stay = stay;
return this;
}
/**
* Sets the number of ticks for the title to fade out.
*
* @param fadeOut the number of ticks to fade out
* @return this builder instance
* @throws IllegalArgumentException if it is negative
*/
@NotNull
public Builder fadeOut(int fadeOut) {
checkArgument(fadeOut >= 0, "Negative fadeOut: %s", fadeOut);
this.fadeOut = fadeOut;
return this;
}
/**
* Create a title based on the values in the builder.
*
* @return a title from the values in this builder
* @throws IllegalStateException if title isn't specified
*/
@NotNull
public Title build() {
checkState(title != null, "Title not specified");
return new Title(this.title, this.subtitle, this.fadeIn, this.stay, this.fadeOut);
}
}
}

View File

@@ -1,144 +0,0 @@
package com.destroystokyo.paper;
import com.google.common.base.MoreObjects;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
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.nio.file.StandardOpenOption;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum VersionHistoryManager {
INSTANCE;
private final Gson gson = new Gson();
private final Logger logger = Bukkit.getLogger();
private VersionData currentData = null;
VersionHistoryManager() {
final Path path = Paths.get("version_history.json");
if (Files.exists(path)) {
// Basic file santiy checks
if (!Files.isRegularFile(path)) {
if (Files.isDirectory(path)) {
logger.severe(path + " is a directory, cannot be used for version history");
} else {
logger.severe(path + " is not a regular file, cannot be used for version history");
}
// We can't continue
return;
}
try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
currentData = gson.fromJson(reader, VersionData.class);
} catch (final IOException e) {
logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e);
return;
} catch (final JsonSyntaxException e) {
logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e);
return;
}
final String version = Bukkit.getVersion();
if (version == null) {
logger.severe("Failed to retrieve current version");
return;
}
if (!version.equals(currentData.getCurrentVersion())) {
// The version appears to have changed
currentData.setOldVersion(currentData.getCurrentVersion());
currentData.setCurrentVersion(version);
writeFile(path);
}
} else {
// File doesn't exist, start fresh
currentData = new VersionData();
// oldVersion is null
currentData.setCurrentVersion(Bukkit.getVersion());
writeFile(path);
}
}
private void writeFile(@NotNull final Path path) {
try (final BufferedWriter writer = Files.newBufferedWriter(
path,
StandardCharsets.UTF_8,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING
)) {
gson.toJson(currentData, writer);
} catch (final IOException e) {
logger.log(Level.SEVERE, "Failed to write to version history file", e);
}
}
@Nullable
public VersionData getVersionData() {
return currentData;
}
public static class VersionData {
private String oldVersion;
private String currentVersion;
@Nullable
public String getOldVersion() {
return oldVersion;
}
public void setOldVersion(@Nullable String oldVersion) {
this.oldVersion = oldVersion;
}
@Nullable
public String getCurrentVersion() {
return currentVersion;
}
public void setCurrentVersion(@Nullable String currentVersion) {
this.currentVersion = currentVersion;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("oldVersion", oldVersion)
.add("currentVersion", currentVersion)
.toString();
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final VersionData versionData = (VersionData) o;
return Objects.equals(oldVersion, versionData.oldVersion) &&
Objects.equals(currentVersion, versionData.currentVersion);
}
@Override
public int hashCode() {
return Objects.hash(oldVersion, currentVersion);
}
}
}

View File

@@ -1,54 +0,0 @@
package com.destroystokyo.paper.block;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.jetbrains.annotations.NotNull;
/**
* Represents information about a targeted block
*/
public class TargetBlockInfo {
private final Block block;
private final BlockFace blockFace;
public TargetBlockInfo(@NotNull Block block, @NotNull BlockFace blockFace) {
this.block = block;
this.blockFace = blockFace;
}
/**
* Get the block that is targeted
*
* @return Targeted block
*/
@NotNull
public Block getBlock() {
return block;
}
/**
* Get the targeted BlockFace
*
* @return Targeted blockface
*/
@NotNull
public BlockFace getBlockFace() {
return blockFace;
}
/**
* Get the relative Block to the targeted block on the side it is targeted at
*
* @return Block relative to targeted block
*/
@NotNull
public Block getRelativeBlock() {
return block.getRelative(blockFace);
}
public enum FluidMode {
NEVER,
SOURCE_ONLY,
ALWAYS
}
}

View File

@@ -1,170 +0,0 @@
package com.destroystokyo.paper.entity;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Handles pathfinding operations for an Entity
*/
public interface Pathfinder {
/**
*
* @return The entity that is controlled by this pathfinder
*/
@NotNull
Mob getEntity();
/**
* Instructs the Entity to stop trying to navigate to its current desired location
*/
void stopPathfinding();
/**
* If the entity is currently trying to navigate to a destination, this will return true
* @return true if the entity is navigating to a destination
*/
boolean hasPath();
/**
* @return The location the entity is trying to navigate to, or null if there is no destination
*/
@Nullable
PathResult getCurrentPath();
/**
* Calculates a destination for the Entity to navigate to, but does not set it
* as the current target. Useful for calculating what would happen before setting it.
* @param loc Location to navigate to
* @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
*/
@Nullable PathResult findPath(@NotNull Location loc);
/**
* Calculates a destination for the Entity to navigate to to reach the target entity,
* but does not set it as the current target.
* Useful for calculating what would happen before setting it.
*
* The behavior of this PathResult is subject to the games pathfinding rules, and may
* result in the pathfinding automatically updating to follow the target Entity.
*
* However, this behavior is not guaranteed, and is subject to the games behavior.
*
* @param target the Entity to navigate to
* @return The closest Location the Entity can get to for this navigation, or null if no path could be calculated
*/
@Nullable PathResult findPath(@NotNull LivingEntity target);
/**
* Calculates a destination for the Entity to navigate to, and sets it with default speed
* as the current target.
* @param loc Location to navigate to
* @return If the pathfinding was successfully started
*/
default boolean moveTo(@NotNull Location loc) {
return moveTo(loc, 1);
}
/**
* Calculates a destination for the Entity to navigate to, with desired speed
* as the current target.
* @param loc Location to navigate to
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
* @return If the pathfinding was successfully started
*/
default boolean moveTo(@NotNull Location loc, double speed) {
PathResult path = findPath(loc);
return path != null && moveTo(path, speed);
}
/**
* Calculates a destination for the Entity to navigate to to reach the target entity,
* and sets it with default speed.
*
* The behavior of this PathResult is subject to the games pathfinding rules, and may
* result in the pathfinding automatically updating to follow the target Entity.
*
* However, this behavior is not guaranteed, and is subject to the games behavior.
*
* @param target the Entity to navigate to
* @return If the pathfinding was successfully started
*/
default boolean moveTo(@NotNull LivingEntity target) {
return moveTo(target, 1);
}
/**
* Calculates a destination for the Entity to navigate to to reach the target entity,
* and sets it with specified speed.
*
* The behavior of this PathResult is subject to the games pathfinding rules, and may
* result in the pathfinding automatically updating to follow the target Entity.
*
* However, this behavior is not guaranteed, and is subject to the games behavior.
*
* @param target the Entity to navigate to
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
* @return If the pathfinding was successfully started
*/
default boolean moveTo(@NotNull LivingEntity target, double speed) {
PathResult path = findPath(target);
return path != null && moveTo(path, speed);
}
/**
* Takes the result of a previous pathfinding calculation and sets it
* as the active pathfinding with default speed.
*
* @param path The Path to start following
* @return If the pathfinding was successfully started
*/
default boolean moveTo(@NotNull PathResult path) {
return moveTo(path, 1);
}
/**
* Takes the result of a previous pathfinding calculation and sets it
* as the active pathfinding,
*
* @param path The Path to start following
* @param speed Speed multiplier to navigate at, where 1 is 'normal'
* @return If the pathfinding was successfully started
*/
boolean moveTo(@NotNull PathResult path, double speed);
/**
* Represents the result of a pathfinding calculation
*/
interface PathResult {
/**
* All currently calculated points to follow along the path to reach the destination location
*
* Will return points the entity has already moved past, see {@link #getNextPointIndex()}
* @return List of points
*/
@NotNull
List<Location> getPoints();
/**
* @return Returns the index of the current point along the points returned in {@link #getPoints()} the entity
* is trying to reach, or null if we are done with this pathfinding.
*/
int getNextPointIndex();
/**
* @return The next location in the path points the entity is trying to reach, or null if there is no next point
*/
@Nullable Location getNextPoint();
/**
* @return The closest point the path can get to the target location
*/
@Nullable Location getFinalPoint();
}
}

View File

@@ -1,31 +0,0 @@
package com.destroystokyo.paper.entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.jetbrains.annotations.NotNull;
public interface RangedEntity extends Mob {
/**
* Attack the specified entity using a ranged attack.
*
* @param target the entity to target
* @param charge How "charged" the attack is (how far back the bow was pulled for Bow attacks).
* This should be a value between 0 and 1, represented as targetDistance/maxDistance.
*/
void rangedAttack(@NotNull LivingEntity target, float charge);
/**
* Sets that the Entity is "charging" up an attack, by raising its hands
*
* @param raiseHands Whether the entities hands are raised to charge attack
*/
void setChargingAttack(boolean raiseHands);
/**
* Alias to {@link LivingEntity#isHandRaised()}, if the entity is charging an attack
* @return If entities hands are raised
*/
default boolean isChargingAttack() {
return isHandRaised();
}
}

View File

@@ -1,38 +0,0 @@
package com.destroystokyo.paper.entity;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
/**
* Represents information about a targeted entity
*/
public class TargetEntityInfo {
private final Entity entity;
private final Vector hitVec;
public TargetEntityInfo(@NotNull Entity entity, @NotNull Vector hitVec) {
this.entity = entity;
this.hitVec = hitVec;
}
/**
* Get the entity that is targeted
*
* @return Targeted entity
*/
@NotNull
public Entity getEntity() {
return entity;
}
/**
* Get the position the entity is targeted at
*
* @return Targeted position
*/
@NotNull
public Vector getHitVector() {
return hitVec;
}
}

View File

@@ -1,148 +0,0 @@
package com.destroystokyo.paper.event.block;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.inventory.InventoryEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Called when an anvil is damaged from being used
*/
public class AnvilDamagedEvent extends InventoryEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel;
private DamageState damageState;
public AnvilDamagedEvent(@NotNull InventoryView inventory, @NotNull BlockData blockData) {
super(inventory);
this.damageState = DamageState.getState(blockData);
}
@NotNull
@Override
public AnvilInventory getInventory() {
return (AnvilInventory) super.getInventory();
}
/**
* Gets the new state of damage on the anvil
*
* @return Damage state
*/
@NotNull
public DamageState getDamageState() {
return damageState;
}
/**
* Sets the new state of damage on the anvil
*
* @param damageState Damage state
*/
public void setDamageState(@NotNull DamageState damageState) {
this.damageState = damageState;
}
/**
* Gets if anvil is breaking on this use
*
* @return True if breaking
*/
public boolean isBreaking() {
return damageState == DamageState.BROKEN;
}
/**
* Sets if anvil is breaking on this use
*
* @param breaking True if breaking
*/
public void setBreaking(boolean breaking) {
if (breaking) {
damageState = DamageState.BROKEN;
} else if (damageState == DamageState.BROKEN) {
damageState = DamageState.DAMAGED;
}
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
/**
* Represents the amount of damage on an anvil block
*/
public enum DamageState {
FULL(Material.ANVIL),
CHIPPED(Material.CHIPPED_ANVIL),
DAMAGED(Material.DAMAGED_ANVIL),
BROKEN(Material.AIR);
private Material material;
DamageState(@NotNull Material material) {
this.material = material;
}
/**
* Get block material of this state
*
* @return Material
*/
@NotNull
public Material getMaterial() {
return material;
}
/**
* Get damaged state by block data
*
* @param blockData Block data
* @return DamageState
* @throws IllegalArgumentException If non anvil block data is given
*/
@NotNull
public static DamageState getState(@Nullable BlockData blockData) {
return blockData == null ? BROKEN : getState(blockData.getMaterial());
}
/**
* Get damaged state by block material
*
* @param material Block material
* @return DamageState
* @throws IllegalArgumentException If non anvil material is given
*/
@NotNull
public static DamageState getState(@Nullable Material material) {
if (material == null) {
return BROKEN;
}
for (DamageState state : values()) {
if (state.material == material) {
return state;
}
}
throw new IllegalArgumentException("Material not an anvil");
}
}
}

View File

@@ -1,86 +0,0 @@
package com.destroystokyo.paper.event.block;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockEvent;
import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull;
/**
* Called when a beacon effect is being applied to a player.
*/
public class BeaconEffectEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
private PotionEffect effect;
private Player player;
private boolean primary;
public BeaconEffectEvent(@NotNull Block block, @NotNull PotionEffect effect, @NotNull Player player, boolean primary) {
super(block);
this.effect = effect;
this.player = player;
this.primary = primary;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* Gets the potion effect being applied.
*
* @return Potion effect
*/
@NotNull
public PotionEffect getEffect() {
return effect;
}
/**
* Sets the potion effect that will be applied.
*
* @param effect Potion effect
*/
public void setEffect(@NotNull PotionEffect effect) {
this.effect = effect;
}
/**
* Gets the player who the potion effect is being applied to.
*
* @return Affected player
*/
@NotNull
public Player getPlayer() {
return player;
}
/**
* Gets whether the effect is a primary beacon effect.
*
* @return true if this event represents a primary effect
*/
public boolean isPrimary() {
return primary;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,92 +0,0 @@
package com.destroystokyo.paper.event.block;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired anytime the server intends to 'destroy' a block through some triggering reason.
* This does not fire anytime a block is set to air, but only with more direct triggers such
* as physics updates, pistons, Entities changing blocks, commands set to "Destroy".
*
* This event is associated with the game playing a sound effect at the block in question, when
* something can be described as "intend to destroy what is there",
*
* Events such as leaves decaying, pistons retracting (where the block is moving), does NOT fire this event.
*
*/
public class BlockDestroyEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@NotNull private final BlockData newState;
private final boolean willDrop;
private boolean playEffect;
private boolean cancelled = false;
public BlockDestroyEvent(@NotNull Block block, @NotNull BlockData newState, boolean willDrop) {
super(block);
this.newState = newState;
this.willDrop = willDrop;
}
/**
* @return The new state of this block (Air, or a Fluid type)
*/
@NotNull
public BlockData getNewState() {
return newState;
}
/**
* @return If the server is going to drop the block in question with this destroy event
*/
public boolean willDrop() {
return this.willDrop;
}
/**
* @return If the server is going to play the sound effect for this destruction
*/
public boolean playEffect() {
return this.playEffect;
}
/**
* @param playEffect If the server should play the sound effect for this destruction
*/
public void setPlayEffect(boolean playEffect) {
this.playEffect = playEffect;
}
/**
* @return If the event is cancelled, meaning the block will not be destroyed
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* If the event is cancelled, the block will remain in its previous state.
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,114 +0,0 @@
package com.destroystokyo.paper.event.block;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Called when TNT block is about to turn into {@link org.bukkit.entity.TNTPrimed}
* <p>
* Cancelling it won't turn TNT into {@link org.bukkit.entity.TNTPrimed} and leaves
* the TNT block as-is
*
* @author Mark Vainomaa
*/
public class TNTPrimeEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
@NotNull private PrimeReason reason;
@Nullable private Entity primerEntity;
public TNTPrimeEvent(@NotNull Block theBlock, @NotNull PrimeReason reason, @Nullable Entity primerEntity) {
super(theBlock);
this.reason = reason;
this.primerEntity = primerEntity;
}
/**
* Gets the TNT prime reason
*
* @return Prime reason
*/
@NotNull
public PrimeReason getReason() {
return this.reason;
}
/**
* Gets the TNT primer {@link Entity}.
*
* It's null if {@link #getReason()} is {@link PrimeReason#REDSTONE} or {@link PrimeReason#FIRE}.
* It's not null if {@link #getReason()} is {@link PrimeReason#ITEM} or {@link PrimeReason#PROJECTILE}
* It might be null if {@link #getReason()} is {@link PrimeReason#EXPLOSION}
*
* @return The {@link Entity} who primed the TNT
*/
@Nullable
public Entity getPrimerEntity() {
return this.primerEntity;
}
/**
* Gets whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
*
* @return Whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
*/
@Override
public boolean isCancelled() {
return this.cancelled;
}
/**
* Sets whether to cancel spawning {@link org.bukkit.entity.TNTPrimed} or not
*
* @param cancel whether spawning {@link org.bukkit.entity.TNTPrimed} should be cancelled or not
*/
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Nullable
@Override
public HandlerList getHandlers() {
return handlers;
}
@Nullable
public static HandlerList getHandlerList() {
return handlers;
}
public enum PrimeReason {
/**
* When TNT prime was caused by other explosion (chain reaction)
*/
EXPLOSION,
/**
* When TNT prime was caused by fire
*/
FIRE,
/**
* When {@link org.bukkit.entity.Player} used {@link org.bukkit.Material#FLINT_AND_STEEL} or
* {@link org.bukkit.Material#FIRE_CHARGE} on given TNT block
*/
ITEM,
/**
* When TNT prime was caused by an {@link Entity} shooting TNT
* using a bow with {@link org.bukkit.enchantments.Enchantment#ARROW_FIRE} enchantment
*/
PROJECTILE,
/**
* When redstone power triggered the TNT prime
*/
REDSTONE
}
}

View File

@@ -1,54 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Creeper;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when a Creeper is ignite flag is changed (armed/disarmed to explode).
*/
public class CreeperIgniteEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean canceled;
private boolean ignited;
public CreeperIgniteEvent(@NotNull Creeper creeper, boolean ignited) {
super(creeper);
this.ignited = ignited;
}
@NotNull
@Override
public Creeper getEntity() {
return (Creeper) entity;
}
public boolean isIgnited() {
return ignited;
}
public void setIgnited(boolean ignited) {
this.ignited = ignited;
}
public boolean isCancelled() {
return canceled;
}
public void setCancelled(boolean cancel) {
canceled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,79 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.DragonFireball;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import java.util.Collection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Fired when a DragonFireball collides with a block/entity and spawns an AreaEffectCloud
*/
public class EnderDragonFireballHitEvent extends EntityEvent implements Cancellable {
@Nullable private final Collection<LivingEntity> targets;
@NotNull private final AreaEffectCloud areaEffectCloud;
public EnderDragonFireballHitEvent(@NotNull DragonFireball fireball, @Nullable Collection<LivingEntity> targets, @NotNull AreaEffectCloud areaEffectCloud) {
super(fireball);
this.targets = targets;
this.areaEffectCloud = areaEffectCloud;
}
/**
* The fireball involved in this event
*/
@NotNull
@Override
public DragonFireball getEntity() {
return (DragonFireball) super.getEntity();
}
/**
* The living entities hit by fireball
*
* May be null if no entities were hit
*
* @return the targets
*/
@Nullable
public Collection<LivingEntity> getTargets() {
return targets;
}
/**
* @return The area effect cloud spawned in this collision
*/
@NotNull
public AreaEffectCloud getAreaEffectCloud() {
return areaEffectCloud;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,61 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.AreaEffectCloud;
import org.bukkit.entity.EnderDragon;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when an EnderDragon spawns an AreaEffectCloud by shooting flames
*/
public class EnderDragonFlameEvent extends EntityEvent implements Cancellable {
@NotNull private final AreaEffectCloud areaEffectCloud;
public EnderDragonFlameEvent(@NotNull EnderDragon enderDragon, @NotNull AreaEffectCloud areaEffectCloud) {
super(enderDragon);
this.areaEffectCloud = areaEffectCloud;
}
/**
* The enderdragon involved in this event
*/
@NotNull
@Override
public EnderDragon getEntity() {
return (EnderDragon) super.getEntity();
}
/**
* @return The area effect cloud spawned in this collision
*/
@NotNull
public AreaEffectCloud getAreaEffectCloud() {
return areaEffectCloud;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,61 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.DragonFireball;
import org.bukkit.entity.EnderDragon;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when an EnderDragon shoots a fireball
*/
public class EnderDragonShootFireballEvent extends EntityEvent implements Cancellable {
@NotNull private final DragonFireball fireball;
public EnderDragonShootFireballEvent(@NotNull EnderDragon entity, @NotNull DragonFireball fireball) {
super(entity);
this.fireball = fireball;
}
/**
* The enderdragon shooting the fireball
*/
@NotNull
@Override
public EnderDragon getEntity() {
return (EnderDragon) super.getEntity();
}
/**
* @return The fireball being shot
*/
@NotNull
public DragonFireball getFireball() {
return fireball;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when an Enderman determines if it should attack a player or not.
* Starts off cancelled if the player is wearing a pumpkin head or is not looking
* at the Enderman, according to Vanilla rules.
*
*/
public class EndermanAttackPlayerEvent extends EntityEvent implements Cancellable {
@NotNull private final Player player;
public EndermanAttackPlayerEvent(@NotNull Enderman entity, @NotNull Player player) {
super(entity);
this.player = player;
}
/**
* The enderman considering attacking
*
* @return The enderman considering attacking
*/
@NotNull
@Override
public Enderman getEntity() {
return (Enderman) super.getEntity();
}
/**
* The player the Enderman is considering attacking
*
* @return The player the Enderman is considering attacking
*/
@NotNull
public Player getPlayer() {
return player;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
*
* @return If cancelled, the enderman will not attack
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* Cancels if the Enderman will attack this player
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,87 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Enderman;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
public class EndermanEscapeEvent extends EntityEvent implements Cancellable {
@NotNull private final Reason reason;
public EndermanEscapeEvent(@NotNull Enderman entity, @NotNull Reason reason) {
super(entity);
this.reason = reason;
}
@NotNull
@Override
public Enderman getEntity() {
return (Enderman) super.getEntity();
}
/**
* @return The reason the enderman is trying to escape
*/
@NotNull
public Reason getReason() {
return reason;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* Cancels the escape.
*
* If this escape normally would of resulted in damage avoidance such as indirect,
* the enderman will now take damage.
*
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
public enum Reason {
/**
* The enderman has stopped attacking and ran away
*/
RUNAWAY,
/**
* The enderman has teleported away due to indirect damage (ranged)
*/
INDIRECT,
/**
* The enderman has teleported away due to a critical hit
*/
CRITICAL_HIT,
/**
* The enderman has teleported away due to the player staring at it during combat
*/
STARE,
/**
* Specific case for CRITICAL_HIT where the enderman is taking rain damage
*/
DROWN
}
}

View File

@@ -1,32 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired any time an entity is being added to the world for any reason.
*
* Not to be confused with {@link org.bukkit.event.entity.CreatureSpawnEvent}
* This will fire anytime a chunk is reloaded too.
*/
public class EntityAddToWorldEvent extends EntityEvent {
public EntityAddToWorldEvent(@NotNull Entity entity) {
super(entity);
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,82 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
/**
* Fired when an Entity is knocked back by the hit of another Entity. The acceleration
* vector can be modified. If this event is cancelled, the entity is not knocked back.
*
*/
public class EntityKnockbackByEntityEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@NotNull private final Entity hitBy;
private final float knockbackStrength;
@NotNull private final Vector acceleration;
private boolean cancelled = false;
public EntityKnockbackByEntityEvent(@NotNull LivingEntity entity, @NotNull Entity hitBy, float knockbackStrength, @NotNull Vector acceleration) {
super(entity);
this.hitBy = hitBy;
this.knockbackStrength = knockbackStrength;
this.acceleration = acceleration;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
/**
* @return the entity which was knocked back
*/
@NotNull
@Override
public LivingEntity getEntity() {
return (LivingEntity) super.getEntity();
}
/**
* @return the original knockback strength.
*/
public float getKnockbackStrength() {
return knockbackStrength;
}
/**
* @return the Entity which hit
*/
@NotNull
public Entity getHitBy() {
return hitBy;
}
/**
* @return the acceleration that will be applied
*/
@NotNull
public Vector getAcceleration() {
return acceleration;
}
}

View File

@@ -1,82 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Fired when an Entity decides to start moving towards a location.
*
* This event does not fire for the entities actual movement. Only when it
* is choosing to start moving to a location.
*/
public class EntityPathfindEvent extends EntityEvent implements Cancellable {
@Nullable private final Entity targetEntity;
@NotNull private final Location loc;
public EntityPathfindEvent(@NotNull Entity entity, @NotNull Location loc, @Nullable Entity targetEntity) {
super(entity);
this.targetEntity = targetEntity;
this.loc = loc;
}
/**
* The Entity that is pathfinding.
* @return The Entity that is pathfinding.
*/
@NotNull
public Entity getEntity() {
return entity;
}
/**
* If the Entity is trying to pathfind to an entity, this is the entity in relation.
*
* Otherwise this will return null.
*
* @return The entity target or null
*/
@Nullable
public Entity getTargetEntity() {
return targetEntity;
}
/**
* The Location of where the entity is about to move to.
*
* Note that if the target happened to of been an entity
* @return Location of where the entity is trying to pathfind to.
*/
@NotNull
public Location getLoc() {
return loc;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,29 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired any time an entity is being removed from a world for any reason
*/
public class EntityRemoveFromWorldEvent extends EntityEvent {
public EntityRemoveFromWorldEvent(@NotNull Entity entity) {
super(entity);
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,31 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Location;
import org.bukkit.block.EndGateway;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.EntityTeleportEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired any time an entity attempts to teleport in an end gateway
*/
public class EntityTeleportEndGatewayEvent extends EntityTeleportEvent {
@NotNull private final EndGateway gateway;
public EntityTeleportEndGatewayEvent(@NotNull Entity what, @NotNull Location from, @NotNull Location to, @NotNull EndGateway gateway) {
super(what, from, to);
this.gateway = gateway;
}
/**
* The gateway triggering the teleport
*
* @return EndGateway used
*/
@NotNull
public EndGateway getGateway() {
return gateway;
}
}

View File

@@ -1,92 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.entity.EntityTransformEvent;
/**
* Fired when an entity transforms into another entity
* <p>
* If the event is cancelled, the entity will not transform
* @deprecated Bukkit has added {@link EntityTransformEvent}, you should start using that
*/
@Deprecated
public class EntityTransformedEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
private final Entity transformed;
private final TransformedReason reason;
public EntityTransformedEvent(Entity entity, Entity transformed, TransformedReason reason) {
super(entity);
this.transformed = transformed;
this.reason = reason;
}
/**
* The entity after it has transformed
*
* @return Transformed entity
* @deprecated see {@link EntityTransformEvent#getTransformedEntity()}
*/
@Deprecated
public Entity getTransformed() {
return transformed;
}
/**
* @return The reason for the transformation
* @deprecated see {@link EntityTransformEvent#getTransformReason()}
*/
@Deprecated
public TransformedReason getReason() {
return reason;
}
@Override
public HandlerList getHandlers(){
return handlers;
}
public static HandlerList getHandlerList(){
return handlers;
}
@Override
public boolean isCancelled(){
return cancelled;
}
@Override
public void setCancelled(boolean cancel){
cancelled = cancel;
}
public enum TransformedReason {
/**
* When a zombie drowns
*/
DROWNED,
/**
* When a zombie villager is cured
*/
CURED,
/**
* When a villager turns to a zombie villager
*/
INFECTED,
/**
* When a mooshroom turns to a cow
*/
SHEARED,
/**
* When a pig turns to a zombiepigman
*/
LIGHTNING
}
}

View File

@@ -1,65 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LightningStrike;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.event.entity.EntityTransformEvent;
import java.util.Collections;
import org.jetbrains.annotations.NotNull;
/**
* Fired when lightning strikes an entity
*/
public class EntityZapEvent extends EntityTransformEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
@NotNull private final LightningStrike bolt;
public EntityZapEvent(@NotNull final Entity entity, @NotNull final LightningStrike bolt, @NotNull final Entity replacementEntity) {
super(entity, Collections.singletonList(replacementEntity), TransformReason.LIGHTNING);
Validate.notNull(bolt);
Validate.notNull(replacementEntity);
this.bolt = bolt;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
/**
* Gets the lightning bolt that is striking the entity.
* @return The lightning bolt responsible for this event
*/
@NotNull
public LightningStrike getBolt() {
return bolt;
}
/**
* Gets the entity that will replace the struck entity.
* @return The entity that will replace the struck entity
*/
@NotNull
public Entity getReplacementEntity() {
return getTransformedEntity();
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,87 +0,0 @@
/*
* Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired anytime the server is about to merge 2 experience orbs into one
*/
public class ExperienceOrbMergeEvent extends EntityEvent implements Cancellable {
@NotNull private final ExperienceOrb mergeTarget;
@NotNull private final ExperienceOrb mergeSource;
public ExperienceOrbMergeEvent(@NotNull ExperienceOrb mergeTarget, @NotNull ExperienceOrb mergeSource) {
super(mergeTarget);
this.mergeTarget = mergeTarget;
this.mergeSource = mergeSource;
}
/**
* @return The orb that will absorb the other experience orb
*/
@NotNull
public ExperienceOrb getMergeTarget() {
return mergeTarget;
}
/**
* @return The orb that is subject to being removed and merged into the target orb
*/
@NotNull
public ExperienceOrb getMergeSource() {
return mergeSource;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* @param cancel true if you wish to cancel this event, and prevent the orbs from merging
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,31 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Called when a phantom is spawned for an exhausted player
*/
public class PhantomPreSpawnEvent extends PreCreatureSpawnEvent {
@NotNull private final Entity entity;
public PhantomPreSpawnEvent(@NotNull Location location, @NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) {
super(location, EntityType.PHANTOM, reason);
this.entity = entity;
}
/**
* Get the entity this phantom is spawning for
*
* @return Entity
*/
@Nullable
public Entity getSpawningEntity() {
return entity;
}
}

View File

@@ -1,64 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when the server is calculating what chunks to try to spawn monsters in every Monster Spawn Tick event
*/
public class PlayerNaturallySpawnCreaturesEvent extends PlayerEvent implements Cancellable {
private byte radius;
public PlayerNaturallySpawnCreaturesEvent(@NotNull Player player, byte radius) {
super(player);
this.radius = radius;
}
/**
* @return The radius of chunks around this player to be included in natural spawn selection
*/
public byte getSpawnRadius() {
return radius;
}
/**
* @param radius The radius of chunks around this player to be included in natural spawn selection
*/
public void setSpawnRadius(byte radius) {
this.radius = radius;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
* @return If this players chunks will be excluded from natural spawns
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* @param cancel true if you wish to cancel this event, and not include this players chunks for natural spawning
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,104 +0,0 @@
package com.destroystokyo.paper.event.entity;
import com.google.common.base.Preconditions;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull;
/**
* WARNING: This event only fires for a limited number of cases, and not for every case that CreatureSpawnEvent does.
*
* You should still listen to CreatureSpawnEvent as a backup, and only use this event as an "enhancement".
* The intent of this event is to improve server performance, so limited use cases.
*
* Currently: NATURAL and SPAWNER based reasons. Please submit a Pull Request for future additions.
* Also, Plugins that replace Entity Registrations with their own custom entities might not fire this event.
*/
public class PreCreatureSpawnEvent extends Event implements Cancellable {
@NotNull private final Location location;
@NotNull private final EntityType type;
@NotNull private final CreatureSpawnEvent.SpawnReason reason;
private boolean shouldAbortSpawn;
public PreCreatureSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull CreatureSpawnEvent.SpawnReason reason) {
this.location = Preconditions.checkNotNull(location, "Location may not be null").clone();
this.type = Preconditions.checkNotNull(type, "Type may not be null");
this.reason = Preconditions.checkNotNull(reason, "Reason may not be null");
}
/**
* @return The location this creature is being spawned at
*/
@NotNull
public Location getSpawnLocation() {
return location;
}
/**
* @return The type of creature being spawned
*/
@NotNull
public EntityType getType() {
return type;
}
/**
* @return Reason this creature is spawning (ie, NATURAL vs SPAWNER)
*/
@NotNull
public CreatureSpawnEvent.SpawnReason getReason() {
return reason;
}
/**
* @return If the spawn process should be aborted vs trying more attempts
*/
public boolean shouldAbortSpawn() {
return shouldAbortSpawn;
}
/**
* Set this if you are more blanket blocking all types of these spawns, and wish to abort the spawn process from
* trying more attempts after this cancellation.
*
* @param shouldAbortSpawn Set if the spawn process should be aborted vs trying more attempts
*/
public void setShouldAbortSpawn(boolean shouldAbortSpawn) {
this.shouldAbortSpawn = shouldAbortSpawn;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
* @return If the spawn of this creature is cancelled or not
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* Cancelling this event is more effecient than cancelling CreatureSpawnEvent
* @param cancel true if you wish to cancel this event, and abort the spawn of this creature
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,29 +0,0 @@
package com.destroystokyo.paper.event.entity;
import com.google.common.base.Preconditions;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called before an entity is spawned into a world by a spawner.
*
* This only includes the spawner's location and not the full BlockState snapshot for performance reasons.
* If you really need it you have to get the spawner yourself.
*/
public class PreSpawnerSpawnEvent extends PreCreatureSpawnEvent {
@NotNull private final Location spawnerLocation;
public PreSpawnerSpawnEvent(@NotNull Location location, @NotNull EntityType type, @NotNull Location spawnerLocation) {
super(location, type, CreatureSpawnEvent.SpawnReason.SPAWNER);
this.spawnerLocation = Preconditions.checkNotNull(spawnerLocation, "Spawner location may not be null");
}
@NotNull
public Location getSpawnerLocation() {
return spawnerLocation;
}
}

View File

@@ -1,67 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when an projectile collides with an entity
* <p>
* This event is called <b>before</b> {@link org.bukkit.event.entity.EntityDamageByEntityEvent}, and cancelling it will allow the projectile to continue flying
*/
public class ProjectileCollideEvent extends EntityEvent implements Cancellable {
@NotNull private final Entity collidedWith;
/**
* Get the entity the projectile collided with
*
* @return the entity collided with
*/
@NotNull
public Entity getCollidedWith() {
return collidedWith;
}
public ProjectileCollideEvent(@NotNull Projectile what, @NotNull Entity collidedWith) {
super(what);
this.collidedWith = collidedWith;
}
/**
* Get the projectile that collided
*
* @return the projectile that collided
*/
@NotNull
public Projectile getEntity() {
return (Projectile) super.getEntity();
}
private static final HandlerList handlerList = new HandlerList();
@NotNull
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlerList;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}

View File

@@ -1,47 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.SkeletonHorse;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Event called when a player gets close to a skeleton horse and triggers the lightning trap
*/
public class SkeletonHorseTrapEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
public SkeletonHorseTrapEvent(@NotNull SkeletonHorse horse) {
super(horse);
}
@NotNull
@Override
public SkeletonHorse getEntity() {
return (SkeletonHorse) super.getEntity();
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,38 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Slime;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Slime decides to change it's facing direction.
* <p>
* This event does not fire for the entity's actual movement. Only when it
* is choosing to change direction.
*/
public class SlimeChangeDirectionEvent extends SlimePathfindEvent implements Cancellable {
private float yaw;
public SlimeChangeDirectionEvent(@NotNull Slime slime, float yaw) {
super(slime);
this.yaw = yaw;
}
/**
* Get the new chosen yaw
*
* @return Chosen yaw
*/
public float getNewYaw() {
return yaw;
}
/**
* Set the new chosen yaw
*
* @param yaw Chosen yaw
*/
public void setNewYaw(float yaw) {
this.yaw = yaw;
}
}

View File

@@ -1,53 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Slime;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Slime decides to start pathfinding.
* <p>
* This event does not fire for the entity's actual movement. Only when it
* is choosing to start moving.
*/
public class SlimePathfindEvent extends EntityEvent implements Cancellable {
public SlimePathfindEvent(@NotNull Slime slime) {
super(slime);
}
/**
* The Slime that is pathfinding.
*
* @return The Slime that is pathfinding.
*/
@NotNull
public Slime getEntity() {
return (Slime) entity;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,17 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Slime;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Slime decides to start jumping while swimming in water/lava.
* <p>
* This event does not fire for the entity's actual movement. Only when it
* is choosing to start jumping.
*/
public class SlimeSwimEvent extends SlimeWanderEvent implements Cancellable {
public SlimeSwimEvent(@NotNull Slime slime) {
super(slime);
}
}

View File

@@ -1,31 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Slime;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Slime decides to change direction to target a LivingEntity.
* <p>
* This event does not fire for the entity's actual movement. Only when it
* is choosing to start moving.
*/
public class SlimeTargetLivingEntityEvent extends SlimePathfindEvent implements Cancellable {
@NotNull private final LivingEntity target;
public SlimeTargetLivingEntityEvent(@NotNull Slime slime, @NotNull LivingEntity target) {
super(slime);
this.target = target;
}
/**
* Get the targeted entity
*
* @return Targeted entity
*/
@NotNull
public LivingEntity getTarget() {
return target;
}
}

View File

@@ -1,17 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Slime;
import org.bukkit.event.Cancellable;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Slime decides to start wandering.
* <p>
* This event does not fire for the entity's actual movement. Only when it
* is choosing to start moving.
*/
public class SlimeWanderEvent extends SlimePathfindEvent implements Cancellable {
public SlimeWanderEvent(@NotNull Slime slime) {
super(slime);
}
}

View File

@@ -1,49 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Turtle;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Turtle decides to go home
*/
public class TurtleGoHomeEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
public TurtleGoHomeEvent(@NotNull Turtle turtle) {
super(turtle);
}
/**
* The turtle going home
*
* @return The turtle
*/
@NotNull
public Turtle getEntity() {
return (Turtle) entity;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,87 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Location;
import org.bukkit.entity.Turtle;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Turtle lays eggs
*/
public class TurtleLayEggEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
@NotNull
private final Location location;
private int eggCount;
public TurtleLayEggEvent(@NotNull Turtle turtle, @NotNull Location location, int eggCount) {
super(turtle);
this.location = location;
this.eggCount = eggCount;
}
/**
* The turtle laying the eggs
*
* @return The turtle
*/
@NotNull
public Turtle getEntity() {
return (Turtle) entity;
}
/**
* Get the location where the eggs are being laid
*
* @return Location of eggs
*/
@NotNull
public Location getLocation() {
return location;
}
/**
* Get the number of eggs being laid
*
* @return Number of eggs
*/
public int getEggCount() {
return eggCount;
}
/**
* Set the number of eggs being laid
*
* @param eggCount Number of eggs
*/
public void setEggCount(int eggCount) {
if (eggCount < 1) {
cancelled = true;
return;
}
eggCount = Math.min(eggCount, 4);
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,62 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Location;
import org.bukkit.entity.Turtle;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a Turtle starts digging to lay eggs
*/
public class TurtleStartDiggingEvent extends EntityEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
@NotNull private final Location location;
public TurtleStartDiggingEvent(@NotNull Turtle turtle, @NotNull Location location) {
super(turtle);
this.location = location;
}
/**
* The turtle digging
*
* @return The turtle
*/
@NotNull
public Turtle getEntity() {
return (Turtle) entity;
}
/**
* Get the location where the turtle is digging
*
* @return Location where digging
*/
@NotNull
public Location getLocation() {
return location;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,70 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.Witch;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Fired when a witch consumes the potion in their hand to buff themselves.
*/
public class WitchConsumePotionEvent extends EntityEvent implements Cancellable {
@Nullable private ItemStack potion;
public WitchConsumePotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
super(witch);
this.potion = potion;
}
@NotNull
@Override
public Witch getEntity() {
return (Witch) super.getEntity();
}
/**
* @return the potion the witch will consume and have the effects applied.
*/
@Nullable
public ItemStack getPotion() {
return potion;
}
/**
* Sets the potion to be consumed and applied to the witch.
* @param potion The potion
*/
public void setPotion(@Nullable ItemStack potion) {
this.potion = potion != null ? potion.clone() : null;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
* @return Event was cancelled or potion was null
*/
@Override
public boolean isCancelled() {
return cancelled || potion == null;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,80 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.Material;
import org.bukkit.entity.Witch;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class WitchReadyPotionEvent extends EntityEvent implements Cancellable {
private ItemStack potion;
public WitchReadyPotionEvent(@NotNull Witch witch, @Nullable ItemStack potion) {
super(witch);
this.potion = potion;
}
/**
* Fires thee event, returning the desired potion, or air of cancelled
* @param witch the witch whom is readying to use a potion
* @param potion the potion to be used
* @return The ItemStack to be used
*/
@Nullable
public static ItemStack process(@NotNull Witch witch, @Nullable ItemStack potion) {
WitchReadyPotionEvent event = new WitchReadyPotionEvent(witch, potion);
if (!event.callEvent() || event.getPotion() == null) {
return new ItemStack(Material.AIR);
}
return event.getPotion();
}
@NotNull
@Override
public Witch getEntity() {
return (Witch) super.getEntity();
}
/**
* @return the potion the witch is readying to use
*/
@Nullable
public ItemStack getPotion() {
return potion;
}
/**
* Sets the potion the which is going to hold and use
* @param potion The potion
*/
public void setPotion(@Nullable ItemStack potion) {
this.potion = potion != null ? potion.clone() : null;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,81 +0,0 @@
package com.destroystokyo.paper.event.entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Witch;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Fired when a witch throws a potion at a player
*/
public class WitchThrowPotionEvent extends EntityEvent implements Cancellable {
@NotNull private final LivingEntity target;
@Nullable private ItemStack potion;
public WitchThrowPotionEvent(@NotNull Witch witch, @NotNull LivingEntity target, @Nullable ItemStack potion) {
super(witch);
this.target = target;
this.potion = potion;
}
@NotNull
@Override
public Witch getEntity() {
return (Witch) super.getEntity();
}
/**
* @return The target of the potion
*/
@NotNull
public LivingEntity getTarget() {
return target;
}
/**
* @return The potion the witch will throw at a player
*/
@Nullable
public ItemStack getPotion() {
return potion;
}
/**
* Sets the potion to be thrown at a player
* @param potion The potion
*/
public void setPotion(@Nullable ItemStack potion) {
this.potion = potion != null ? potion.clone() : null;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
* @return Event was cancelled or potion was null
*/
@Override
public boolean isCancelled() {
return cancelled || potion == null;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,42 +0,0 @@
package com.destroystokyo.paper.event.executor;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import com.destroystokyo.paper.util.SneakyThrow;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.NotNull;
public class MethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull MethodHandle handle) {
this.eventClass = eventClass;
this.handle = handle;
}
public MethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
this.eventClass = eventClass;
try {
m.setAccessible(true);
this.handle = MethodHandles.lookup().unreflect(m);
} catch (IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
}
@Override
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
if (!eventClass.isInstance(event)) return;
try {
handle.invoke(listener, event);
} catch (Throwable t) {
SneakyThrow.sneaky(t);
}
}
}

View File

@@ -1,43 +0,0 @@
package com.destroystokyo.paper.event.executor;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import com.destroystokyo.paper.util.SneakyThrow;
import com.google.common.base.Preconditions;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.NotNull;
public class StaticMethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
public StaticMethodHandleEventExecutor(@NotNull Class<? extends Event> eventClass, @NotNull Method m) {
Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
Preconditions.checkArgument(eventClass != null, "eventClass is null");
this.eventClass = eventClass;
try {
m.setAccessible(true);
this.handle = MethodHandles.lookup().unreflect(m);
} catch (IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
}
@Override
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
if (!eventClass.isInstance(event)) return;
try {
handle.invoke(event);
} catch (Throwable throwable) {
SneakyThrow.sneaky(throwable);
}
}
}

View File

@@ -1,47 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import static org.objectweb.asm.Opcodes.*;
public class ASMEventExecutorGenerator {
@NotNull
public static byte[] generateEventExecutor(@NotNull Method m, @NotNull String name) {
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[] {Type.getInternalName(EventExecutor.class)});
// Generate constructor
GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null), ACC_PUBLIC, "<init>", "()V");
methodGenerator.loadThis();
methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // Invoke the super class (Object) constructor
methodGenerator.returnValue();
methodGenerator.endMethod();
// Generate the execute method
methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V", null, null), ACC_PUBLIC, "execute", "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Listener;)V");;
methodGenerator.loadArg(0);
methodGenerator.checkCast(Type.getType(m.getDeclaringClass()));
methodGenerator.loadArg(1);
methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0]));
methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface());
if (m.getReturnType() != void.class) {
methodGenerator.pop();
}
methodGenerator.returnValue();
methodGenerator.endMethod();
writer.visitEnd();
return writer.toByteArray();
}
public static AtomicInteger NEXT_ID = new AtomicInteger(1);
@NotNull
public static String generateName() {
int id = NEXT_ID.getAndIncrement();
return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
}
}

View File

@@ -1,35 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import com.destroystokyo.paper.utils.UnsafeUtils;
import org.jetbrains.annotations.NotNull;
public interface ClassDefiner {
/**
* Returns if the defined classes can bypass access checks
*
* @return if classes bypass access checks
*/
public default boolean isBypassAccessChecks() {
return false;
}
/**
* Define a class
*
* @param parentLoader the parent classloader
* @param name the name of the class
* @param data the class data to load
* @return the defined class
* @throws ClassFormatError if the class data is invalid
* @throws NullPointerException if any of the arguments are null
*/
@NotNull
public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data);
@NotNull
public static ClassDefiner getInstance() {
return SafeClassDefiner.INSTANCE;
}
}

View File

@@ -1,66 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.google.common.base.Preconditions;
import com.google.common.collect.MapMaker;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.Type;
public class SafeClassDefiner implements ClassDefiner {
/* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
private SafeClassDefiner() {}
private final ConcurrentMap<ClassLoader, GeneratedClassLoader> loaders = new MapMaker().weakKeys().makeMap();
@NotNull
@Override
public Class<?> defineClass(@NotNull ClassLoader parentLoader, @NotNull String name, @NotNull byte[] data) {
GeneratedClassLoader loader = loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
synchronized (loader.getClassLoadingLock(name)) {
Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
Class<?> c = loader.define(name, data);
assert c.getName().equals(name);
return c;
}
}
private static class GeneratedClassLoader extends ClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
protected GeneratedClassLoader(@NotNull ClassLoader parent) {
super(parent);
}
private Class<?> define(@NotNull String name, byte[] data) {
synchronized (getClassLoadingLock(name)) {
assert !hasClass(name);
Class<?> c = defineClass(name, data, 0, data.length);
resolveClass(c);
return c;
}
}
@Override
@NotNull
public Object getClassLoadingLock(@NotNull String name) {
return super.getClassLoadingLock(name);
}
public boolean hasClass(@NotNull String name) {
synchronized (getClassLoadingLock(name)) {
try {
Class.forName(name);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
}
}

View File

@@ -1,70 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class IllegalPacketEvent extends PlayerEvent {
@Nullable private final String type;
@Nullable private final String ex;
@Nullable private String kickMessage;
private boolean shouldKick = true;
public IllegalPacketEvent(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception e) {
super(player);
this.type = type;
this.kickMessage = kickMessage;
this.ex = e.getMessage();
}
public boolean isShouldKick() {
return shouldKick;
}
public void setShouldKick(boolean shouldKick) {
this.shouldKick = shouldKick;
}
@Nullable
public String getKickMessage() {
return kickMessage;
}
public void setKickMessage(@Nullable String kickMessage) {
this.kickMessage = kickMessage;
}
@Nullable
public String getType() {
return type;
}
@Nullable
public String getExceptionMessage() {
return ex;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
public static void process(@NotNull Player player, @Nullable String type, @Nullable String kickMessage, @NotNull Exception exception) {
IllegalPacketEvent event = new IllegalPacketEvent(player, type, kickMessage, exception);
event.callEvent();
if (event.shouldKick) {
player.kickPlayer(kickMessage);
}
Bukkit.getLogger().severe(player.getName() + "/" + type + ": " + exception.getMessage());
}
}

View File

@@ -1,63 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.advancement.Advancement;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when a player is granted a criteria in an advancement.
*/
public class PlayerAdvancementCriterionGrantEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@NotNull private final Advancement advancement;
@NotNull private final String criterion;
private boolean cancel = false;
public PlayerAdvancementCriterionGrantEvent(@NotNull Player who, @NotNull Advancement advancement, @NotNull String criterion) {
super(who);
this.advancement = advancement;
this.criterion = criterion;
}
/**
* Get the advancement which has been affected.
*
* @return affected advancement
*/
@NotNull
public Advancement getAdvancement() {
return advancement;
}
/**
* Get the criterion which has been granted.
*
* @return granted criterion
*/
@NotNull
public String getCriterion() {
return criterion;
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,137 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static org.bukkit.Material.*;
/**
* Called when the player themselves change their armor items
* <p>
* Not currently called for environmental factors though it <strong>MAY BE IN THE FUTURE</strong>
*/
public class PlayerArmorChangeEvent extends PlayerEvent {
private static final HandlerList HANDLERS = new HandlerList();
@NotNull private final SlotType slotType;
@Nullable private final ItemStack oldItem;
@Nullable private final ItemStack newItem;
public PlayerArmorChangeEvent(@NotNull Player player, @NotNull SlotType slotType, @Nullable ItemStack oldItem, @Nullable ItemStack newItem) {
super(player);
this.slotType = slotType;
this.oldItem = oldItem;
this.newItem = newItem;
}
/**
* Gets the type of slot being altered.
*
* @return type of slot being altered
*/
@NotNull
public SlotType getSlotType() {
return this.slotType;
}
/**
* Gets the existing item that's being replaced
*
* @return old item
*/
@Nullable
public ItemStack getOldItem() {
return this.oldItem;
}
/**
* Gets the new item that's replacing the old
*
* @return new item
*/
@Nullable
public ItemStack getNewItem() {
return this.newItem;
}
@Override
public String toString() {
return "ArmorChangeEvent{" + "player=" + player + ", slotType=" + slotType + ", oldItem=" + oldItem + ", newItem=" + newItem + '}';
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
@NotNull
public static HandlerList getHandlerList() {
return HANDLERS;
}
public enum SlotType {
HEAD(DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, CHAINMAIL_HELMET, LEATHER_HELMET, PUMPKIN, JACK_O_LANTERN),
CHEST(DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, CHAINMAIL_CHESTPLATE, LEATHER_CHESTPLATE, ELYTRA),
LEGS(DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, CHAINMAIL_LEGGINGS, LEATHER_LEGGINGS),
FEET(DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, CHAINMAIL_BOOTS, LEATHER_BOOTS);
private final Set<Material> mutableTypes = new HashSet<>();
private Set<Material> immutableTypes;
SlotType(Material... types) {
this.mutableTypes.addAll(Arrays.asList(types));
}
/**
* Gets an immutable set of all allowed material types that can be placed in an
* armor slot.
*
* @return immutable set of material types
*/
@NotNull
public Set<Material> getTypes() {
if (immutableTypes == null) {
immutableTypes = Collections.unmodifiableSet(mutableTypes);
}
return immutableTypes;
}
/**
* Gets the type of slot via the specified material
*
* @param material material to get slot by
* @return slot type the material will go in, or null if it won't
*/
@Nullable
public static SlotType getByMaterial(@NotNull Material material) {
for (SlotType slotType : values()) {
if (slotType.getTypes().contains(material)) {
return slotType;
}
}
return null;
}
/**
* Gets whether or not this material can be equipped to a slot
*
* @param material material to check
* @return whether or not this material can be equipped
*/
public static boolean isEquipable(@NotNull Material material) {
return getByMaterial(material) != null;
}
}
}

View File

@@ -1,95 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.net.InetAddress;
import java.util.UUID;
import org.jetbrains.annotations.NotNull;
/**
* <p>
* This event is invoked when a player has disconnected. It is guaranteed that,
* if the server is in online-mode, that the provided uuid and username have been
* validated.
* </p>
*
* <p>
* The event is invoked for players who have not yet logged into the world, whereas
* {@link org.bukkit.event.player.PlayerQuitEvent} is only invoked on players who have logged into the world.
* </p>
*
* <p>
* The event is invoked for players who have already logged into the world,
* although whether or not the player exists in the world at the time of
* firing is undefined. (That is, whether the plugin can retrieve a Player object
* using the event parameters is undefined). However, it is guaranteed that this
* event is invoked AFTER {@link org.bukkit.event.player.PlayerQuitEvent}, if the player has already logged into the world.
* </p>
*
* <p>
* This event is guaranteed to never fire unless {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} has
* been fired beforehand, and this event may not be called in parallel with
* {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} for the same connection.
* </p>
*
* <p>
* Cancelling the {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} guarantees the corresponding
* {@code PlayerConnectionCloseEvent} is never called.
* </p>
*
* <p>
* The event may be invoked asynchronously or synchronously. Plugins should check
* {@link Event#isAsynchronous()} and handle accordingly.
* </p>
*/
public class PlayerConnectionCloseEvent extends Event {
private static final HandlerList HANDLERS = new HandlerList();
@NotNull private final UUID playerUniqueId;
@NotNull private final String playerName;
@NotNull private final InetAddress ipAddress;
public PlayerConnectionCloseEvent(@NotNull final UUID playerUniqueId, @NotNull final String playerName, @NotNull final InetAddress ipAddress, final boolean async) {
super(async);
this.playerUniqueId = playerUniqueId;
this.playerName = playerName;
this.ipAddress = ipAddress;
}
/**
* Returns the {@code UUID} of the player disconnecting.
*/
@NotNull
public UUID getPlayerUniqueId() {
return this.playerUniqueId;
}
/**
* Returns the name of the player disconnecting.
*/
@NotNull
public String getPlayerName() {
return this.playerName;
}
/**
* Returns the player's IP address.
*/
@NotNull
public InetAddress getIpAddress() {
return this.ipAddress;
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
@NotNull
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -1,85 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a player boosts elytra flight with a firework
*/
public class PlayerElytraBoostEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
@NotNull private final ItemStack itemStack;
@NotNull private Firework firework;
private boolean consume = true;
public PlayerElytraBoostEvent(@NotNull Player player, @NotNull ItemStack itemStack, @NotNull Firework firework) {
super(player);
this.itemStack = itemStack;
this.firework = firework;
}
/**
* Get the firework itemstack used
*
* @return ItemStack of firework
*/
@NotNull
public ItemStack getItemStack() {
return itemStack;
}
/**
* Get the firework entity that was spawned
*
* @return Firework entity
*/
@NotNull
public Firework getFirework() {
return firework;
}
/**
* Get whether to consume the firework or not
*
* @return True to consume
*/
public boolean shouldConsume() {
return consume;
}
/**
* Set whether to consume the firework or not
*
* @param consume True to consume
*/
public void setShouldConsume(boolean consume) {
this.consume = consume;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,221 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.apache.commons.lang.Validate;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.UUID;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* This event is fired during a player handshake.
*
* <p>If there are no listeners listening to this event, the logic default
* to your server platform will be ran.</p>
*
* <p>WARNING: TAMPERING WITH THIS EVENT CAN BE DANGEROUS</p>
*/
public class PlayerHandshakeEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
@NotNull private final String originalHandshake;
private boolean cancelled;
@Nullable private String serverHostname;
@Nullable private String socketAddressHostname;
@Nullable private UUID uniqueId;
@Nullable private String propertiesJson;
private boolean failed;
private String failMessage = "If you wish to use IP forwarding, please enable it in your BungeeCord config as well!";
/**
* Creates a new {@link PlayerHandshakeEvent}.
*
* @param originalHandshake the original handshake string
* @param cancelled if this event is enabled
*/
public PlayerHandshakeEvent(@NotNull String originalHandshake, boolean cancelled) {
this.originalHandshake = originalHandshake;
this.cancelled = cancelled;
}
/**
* Determines if this event is cancelled.
*
* <p>When this event is cancelled, custom handshake logic will not
* be processed.</p>
*
* @return {@code true} if this event is cancelled, {@code false} otherwise
*/
@Override
public boolean isCancelled() {
return this.cancelled;
}
/**
* Sets if this event is cancelled.
*
* <p>When this event is cancelled, custom handshake logic will not
* be processed.</p>
*
* @param cancelled {@code true} if this event is cancelled, {@code false} otherwise
*/
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* Gets the original handshake string.
*
* @return the original handshake string
*/
@NotNull
public String getOriginalHandshake() {
return this.originalHandshake;
}
/**
* Gets the server hostname string.
*
* <p>This should not include the port.</p>
*
* @return the server hostname string
*/
@Nullable
public String getServerHostname() {
return this.serverHostname;
}
/**
* Sets the server hostname string.
*
* <p>This should not include the port.</p>
*
* @param serverHostname the server hostname string
*/
public void setServerHostname(@NotNull String serverHostname) {
this.serverHostname = serverHostname;
}
/**
* Gets the socket address hostname string.
*
* <p>This should not include the port.</p>
*
* @return the socket address hostname string
*/
@Nullable
public String getSocketAddressHostname() {
return this.socketAddressHostname;
}
/**
* Sets the socket address hostname string.
*
* <p>This should not include the port.</p>
*
* @param socketAddressHostname the socket address hostname string
*/
public void setSocketAddressHostname(@NotNull String socketAddressHostname) {
this.socketAddressHostname = socketAddressHostname;
}
/**
* Gets the unique id.
*
* @return the unique id
*/
@Nullable
public UUID getUniqueId() {
return this.uniqueId;
}
/**
* Sets the unique id.
*
* @param uniqueId the unique id
*/
public void setUniqueId(@NotNull UUID uniqueId) {
this.uniqueId = uniqueId;
}
/**
* Gets the profile properties.
*
* <p>This should be a valid JSON string.</p>
*
* @return the profile properties, as JSON
*/
@Nullable
public String getPropertiesJson() {
return this.propertiesJson;
}
/**
* Determines if authentication failed.
*
* <p>When {@code true}, the client connecting will be disconnected
* with the {@link #getFailMessage() fail message}.</p>
*
* @return {@code true} if authentication failed, {@code false} otherwise
*/
public boolean isFailed() {
return this.failed;
}
/**
* Sets if authentication failed and the client should be disconnected.
*
* <p>When {@code true}, the client connecting will be disconnected
* with the {@link #getFailMessage() fail message}.</p>
*
* @param failed {@code true} if authentication failed, {@code false} otherwise
*/
public void setFailed(boolean failed) {
this.failed = failed;
}
/**
* Sets the profile properties.
*
* <p>This should be a valid JSON string.</p>
*
* @param propertiesJson the profile properties, as JSON
*/
public void setPropertiesJson(@NotNull String propertiesJson) {
this.propertiesJson = propertiesJson;
}
/**
* Gets the message to display to the client when authentication fails.
*
* @return the message to display to the client
*/
@NotNull
public String getFailMessage() {
return this.failMessage;
}
/**
* Sets the message to display to the client when authentication fails.
*
* @param failMessage the message to display to the client
*/
public void setFailMessage(@NotNull String failMessage) {
Validate.notEmpty(failMessage, "fail message cannot be null or empty");
this.failMessage = failMessage;
}
@NotNull
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
@NotNull
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@@ -1,47 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
public class PlayerInitialSpawnEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
@NotNull private Location spawnLocation;
public PlayerInitialSpawnEvent(@NotNull final Player player, @NotNull final Location spawnLocation) {
super(player);
this.spawnLocation = spawnLocation;
}
/**
* Gets the current spawn location
*
* @return Location current spawn location
*/
@NotNull
public Location getSpawnLocation() {
return this.spawnLocation;
}
/**
* Sets the new spawn location
*
* @param spawnLocation new location for the spawn
*/
public void setSpawnLocation(@NotNull Location spawnLocation) {
this.spawnLocation = spawnLocation;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,106 +0,0 @@
package com.destroystokyo.paper.event.player;
import com.google.common.base.Preconditions;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Called when the server detects the player is jumping.
* <p>
* Added to avoid the overhead and special case logic that many plugins use
* when checking for jumps via PlayerMoveEvent, this event is fired whenever
* the server detects that the player is jumping.
*/
public class PlayerJumpEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
@NotNull private Location from;
@NotNull private Location to;
public PlayerJumpEvent(@NotNull final Player player, @NotNull final Location from, @NotNull final Location to) {
super(player);
this.from = from;
this.to = to;
}
/**
* Gets the cancellation state of this event. A cancelled event will not
* be executed in the server, but will still pass to other plugins
* <p>
* If a jump event is cancelled, the player will be moved or
* teleported back to the Location as defined by getFrom(). This will not
* fire an event
*
* @return true if this event is cancelled
*/
public boolean isCancelled() {
return cancel;
}
/**
* Sets the cancellation state of this event. A cancelled event will not
* be executed in the server, but will still pass to other plugins
* <p>
* If a jump event is cancelled, the player will be moved or
* teleported back to the Location as defined by getFrom(). This will not
* fire an event
*
* @param cancel true if you wish to cancel this event
*/
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
/**
* Gets the location this player jumped from
*
* @return Location the player jumped from
*/
@NotNull
public Location getFrom() {
return from;
}
/**
* Sets the location to mark as where the player jumped from
*
* @param from New location to mark as the players previous location
*/
public void setFrom(@NotNull Location from) {
validateLocation(from);
this.from = from;
}
/**
* Gets the location this player jumped to
*
* This information is based on what the client sends, it typically
* has little relation to the arc of the jump at any given point.
*
* @return Location the player jumped to
*/
@NotNull
public Location getTo() {
return to;
}
private void validateLocation(Location loc) {
Preconditions.checkArgument(loc != null, "Cannot use null location!");
Preconditions.checkArgument(loc.getWorld() != null, "Cannot use location with null world!");
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,83 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Called when a player shoots a projectile
*/
public class PlayerLaunchProjectileEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@NotNull private final Projectile projectile;
@NotNull private final ItemStack itemStack;
private boolean consumeItem = true;
private boolean cancelled;
public PlayerLaunchProjectileEvent(@NotNull Player shooter, @NotNull ItemStack itemStack, @NotNull Projectile projectile) {
super(shooter);
this.itemStack = itemStack;
this.projectile = projectile;
}
/**
* Gets the projectile which will be launched by this event
*
* @return the launched projectile
*/
@NotNull
public Projectile getProjectile() {
return projectile;
}
/**
* Get the ItemStack used to fire the projectile
*
* @return The ItemStack used
*/
@NotNull
public ItemStack getItemStack() {
return itemStack;
}
/**
* Get whether to consume the ItemStack or not
*
* @return True to consume
*/
public boolean shouldConsume() {
return consumeItem;
}
/**
* Set whether to consume the ItemStack or not
*
* @param consumeItem True to consume
*/
public void setShouldConsume(boolean consumeItem) {
this.consumeItem = consumeItem;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,50 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
/**
* Called when the locale of the player is changed.
*
* @deprecated Replaced by {@link org.bukkit.event.player.PlayerLocaleChangeEvent} upstream
*/
@Deprecated
public class PlayerLocaleChangeEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private final String oldLocale;
private final String newLocale;
public PlayerLocaleChangeEvent(final Player player, final String oldLocale, final String newLocale) {
super(player);
this.oldLocale = oldLocale;
this.newLocale = newLocale;
}
/**
* Gets the locale the player switched from.
*
* @return player's old locale
*/
public String getOldLocale() {
return oldLocale;
}
/**
* Gets the locale the player is changed to.
*
* @return player's new locale
*/
public String getNewLocale() {
return newLocale;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (c) 2017 Daniel Ennis (Aikar) MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired when a player is attempting to pick up an experience orb
*/
public class PlayerPickupExperienceEvent extends PlayerEvent implements Cancellable {
@NotNull private final ExperienceOrb experienceOrb;
public PlayerPickupExperienceEvent(@NotNull Player player, @NotNull ExperienceOrb experienceOrb) {
super(player);
this.experienceOrb = experienceOrb;
}
/**
* @return Returns the Orb that the player is picking up
*/
@NotNull
public ExperienceOrb getExperienceOrb() {
return experienceOrb;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* If true, Cancels picking up the experience orb, leaving it in the world
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,52 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Fired after a player has respawned
*/
public class PlayerPostRespawnEvent extends PlayerEvent {
private final static HandlerList handlers = new HandlerList();
private final Location respawnedLocation;
private final boolean isBedSpawn;
public PlayerPostRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnedLocation, final boolean isBedSpawn) {
super(respawnPlayer);
this.respawnedLocation = respawnedLocation;
this.isBedSpawn = isBedSpawn;
}
/**
* Returns the location of the respawned player
*
* @return location of the respawned player
*/
@NotNull
public Location getRespawnedLocation() {
return respawnedLocation.clone();
}
/**
* Checks if the player respawned to their bed
*
* @return whether the player respawned to their bed
*/
public boolean isBedSpawn() {
return isBedSpawn;
}
@Override
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright (c) 2018 Daniel Ennis (Aikar) MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Called when a player is firing a bow and the server is choosing an arrow to use.
*/
public class PlayerReadyArrowEvent extends PlayerEvent implements Cancellable {
@NotNull private final ItemStack bow;
@NotNull private final ItemStack arrow;
public PlayerReadyArrowEvent(@NotNull Player player, @NotNull ItemStack bow, @NotNull ItemStack arrow) {
super(player);
this.bow = bow;
this.arrow = arrow;
}
/**
* @return the player is using to fire the arrow
*/
@NotNull
public ItemStack getBow() {
return bow;
}
/**
* @return the arrow that is attempting to be used
*/
@NotNull
public ItemStack getArrow() {
return arrow;
}
private static final HandlerList handlers = new HandlerList();
@NotNull
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
private boolean cancelled = false;
/**
* Whether or not use of this arrow is cancelled. On cancel, the server will try the next arrow available and fire another event.
*/
@Override
public boolean isCancelled() {
return cancelled;
}
/**
* Cancel use of this arrow. On cancel, the server will try the next arrow available and fire another event.
* @param cancel true if you wish to cancel this event
*/
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
}

View File

@@ -1,67 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Triggered when a player starts spectating an entity in spectator mode.
*/
public class PlayerStartSpectatingEntityEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
@NotNull private final Entity currentSpectatorTarget;
@NotNull private final Entity newSpectatorTarget;
public PlayerStartSpectatingEntityEvent(@NotNull Player player, @NotNull Entity currentSpectatorTarget, @NotNull Entity newSpectatorTarget) {
super(player);
this.currentSpectatorTarget = currentSpectatorTarget;
this.newSpectatorTarget = newSpectatorTarget;
}
/**
* Gets the entity that the player is currently spectating or themselves if they weren't spectating anything
*
* @return The entity the player is currently spectating (before they start spectating the new target).
*/
@NotNull
public Entity getCurrentSpectatorTarget() {
return currentSpectatorTarget;
}
/**
* Gets the new entity that the player will now be spectating
*
* @return The entity the player is now going to be spectating.
*/
@NotNull
public Entity getNewSpectatorTarget() {
return newSpectatorTarget;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@@ -1,54 +0,0 @@
package com.destroystokyo.paper.event.player;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Triggered when a player stops spectating an entity in spectator mode.
*/
public class PlayerStopSpectatingEntityEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
@NotNull private final Entity spectatorTarget;
public PlayerStopSpectatingEntityEvent(@NotNull Player player, @NotNull Entity spectatorTarget) {
super(player);
this.spectatorTarget = spectatorTarget;
}
/**
* Gets the entity that the player is spectating
*
* @return The entity the player is currently spectating (before they will stop).
*/
@NotNull
public Entity getSpectatorTarget() {
return spectatorTarget;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
@Override
public HandlerList getHandlers() {
return handlers;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
}

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