Commits vergleichen

..

1185 Commits

Autor SHA1 Nachricht Datum
6d6de3ee3f Fix 1.19.3 ChunkSections
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-21 16:55:36 +02:00
54fd91c7f7 Fix 1.19
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-19 20:02:26 +02:00
2b870902a3 Fix 1.19.3
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2023-08-19 19:58:16 +02:00
6ab048cd7b Revert "Drop support for minor 1.19 versions (#2316)"
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
This reverts commit 770bb008
2023-08-19 19:50:30 +02:00
5b5fd8a229 Rollback 1.19.4 to 1.19.3
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-19 19:43:39 +02:00
f0509896e0 Rollback 1.19.4 to 1.19.3
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-19 19:39:12 +02:00
bdad5ca1b6 Fix CI
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-19 19:29:00 +02:00
c0f935ef55 Merge remote-tracking branch 'upstream/main'
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-08-19 12:43:25 +02:00
Alexander Brandes
fe33be5795
Update userdev 2023-08-18 13:40:16 +02:00
Maddy Miller
a088e6a96b Remove the Bukkit legacy data folder migration code from 11 years ago (#2383)
(cherry picked from commit EngineHub/WorldEdit@7f81aad028)
2023-08-10 19:10:04 -04:00
Alexander Brandes
acb79469fb
[ci skip] Update towny 2023-08-09 20:59:27 +02:00
Alexander Brandes
7b3c674e1c
[ci skip] Ignore snakeyaml updates 2023-08-09 20:56:15 +02:00
Alexander Brandes
a3e855882c
[ci skip] Ignore snakeyaml updates 2023-08-09 20:54:46 +02:00
Alexander Brandes
e81980651e
Cleanup dependencies 2023-08-09 20:52:18 +02:00
Jeff P
50e45f07f0
fix: Do not tab complete if command not owned by FAWE (#2386) 2023-08-02 14:08:58 +02:00
renovate[bot]
a6f1c6ac82
Update dependency com.palmergames.bukkit.towny:towny to v0.99.5.7 (#2390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-02 14:07:35 +02:00
renovate[bot]
4ca0a95e18
Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.9 (#2391)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-02 14:07:27 +02:00
renovate[bot]
0dbc0db43f
Update plugin com.modrinth.minotaur to v2.8.3 (#2392)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-02 14:07:19 +02:00
Alexander Brandes
9ae04b8d40
Update v7 notification 2023-07-31 11:44:14 +02:00
Jordan
d42854845a
fix: disallowed regions can be length 0 (#2368) 2023-07-27 11:02:41 +02:00
Jordan
8b39e41a1a
fix: don't warn on release build (#2369) 2023-07-27 10:59:11 +02:00
dordsor21
48be6ac94b
fix: processorExtent can be null when setting masks too
- fixes #2379
2023-07-22 17:44:05 +01:00
dordsor21
2f6de996e3
fix: processorExtent can be null in editsession
- fixes #2375
2023-07-22 13:14:01 +01:00
Alexander Brandes
006ccd6887
Back to snapshot for development 2023-07-22 12:44:37 +02:00
Alexander Brandes
37bfe426bc
Release 2.7.0 2023-07-22 12:27:54 +02:00
renovate[bot]
f58f00e97f
Update plugin com.modrinth.minotaur to v2.8.2 (#2374)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-22 12:21:08 +02:00
renovate[bot]
34a98a03c1
Update dependency gradle to v8.2.1 (#2373)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-22 10:02:22 +00:00
Alexander Brandes
c91b477e29
Update PlotSquared integration to v7 (#2075)
Co-authored-by: dordsor21 <dordsor21@gmail.com>
2023-07-22 12:01:33 +02:00
renovate[bot]
4bdcf9a510
Update dependency com.palmergames.bukkit.towny:towny to v0.99.5.4 (#2372)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-22 10:00:15 +00:00
Jordan
9543adc776
Implement async notify queue that submits to a KeyQueuedExecutorService (#2334) 2023-07-20 17:58:01 +02:00
Jordan
18df87a4e8
feat: implement a new "type swap" pattern (#2346) 2023-07-20 17:57:48 +02:00
Jordan
0a8a479214
fix: do not clash ChunkHolder recycling with processors that extend outside the chunk (#2353) 2023-07-20 17:57:29 +02:00
Jordan
fe1859e9d2
fix: do not retain clipboards that completed exceptionally (#2358) 2023-07-20 17:56:30 +02:00
Jordan
f65c4743bd
fix: make IdMask thread-safe (#2361) 2023-07-20 17:56:11 +02:00
Jordan
cdd546ee5e
fix: correct NBT for spawners (#2362) 2023-07-20 17:55:59 +02:00
Paul
5167073326
fix: regions not trimming Y correctly when restricted (#2363) 2023-07-17 21:47:47 +01:00
Chris Lang
e0507e6440
Added cone generation command (#2251)
* Added cone generation command

* Fix formatting problems

---------

Co-authored-by: Madeline Miller <mnmiller1@me.com>
2023-07-15 21:18:09 +01:00
Jordan
b1e0ad4ef7
feat: re-submit chunk load request after 10s after checking world is loaded (#2339)
- #2332 makes it seem like paper forgets to load a chunk sometimes
 - resubmit chunk load request after a second to attempt to counter this
2023-07-15 16:41:04 +01:00
Jordan
e6b1308590
feat: synchronise disk clipboard loading and deletion to clipboardLock (#2342)
- another possible help towards the OverlappingFileLockException
2023-07-15 16:40:52 +01:00
Jordan
f4da4b0287
fix: fix adding/getting masks to/from MaskExtent when it is a processor (#2351)
- fixes #2350
2023-07-15 16:40:29 +01:00
dordsor21
8da530ee80
gracefully handle error in EntityInBlockRemovingProcessor
-  ensures edit continues on chunk correctly
2023-07-15 12:27:33 +01:00
Alexander Brandes
1745c50878
Improve error behaviour of //generate 2023-07-15 09:26:00 +02:00
dordsor21
a680c7ce97
fix: fix #2352 2023-07-13 17:08:18 +01:00
dordsor21
0a19f643b6
fix #2349 2023-07-11 16:39:53 +01:00
Jordan
c0e20a6fe5
feat: provide some information upon OverlappingFileLockException (#2341) 2023-07-10 23:16:05 +02:00
Jordan
1f29ab3b79
fix: fix command brush (#2347) 2023-07-10 22:04:33 +01:00
Jordan
685248d8de
chore: deprecate some methods that ought to be removed (#2340) 2023-07-09 15:16:30 +01:00
Hannes Greule
68eb4e214a
refactor: use HttpClient for update check (#2331) 2023-07-08 18:41:20 +01:00
Alexander Brandes
90587e56fc
Deprecate support for 1.16.5 (#2338) 2023-07-07 16:38:10 +00:00
Jordan
d78092b4ca
fix: ensure chunk is loaded when getting entities (#2323) 2023-07-07 18:36:12 +02:00
Jordan
6fbdef5252
feat: allow bracketless '%' pattern definition (#2322) 2023-07-07 18:36:02 +02:00
Jordan
f38c81aa2a
fix: correctly invalidate mask after a plot is merged (#2333) 2023-07-07 18:27:10 +02:00
Jordan
888683d83b
fix: ignore clipboard origin when pasting to match P2 behaviour (#2336) 2023-07-07 18:23:37 +02:00
dordsor21
a669be2041
fix #2319 2023-07-05 22:03:13 +01:00
Alexander Brandes
67fd31ce4c
Update bom 2023-07-05 16:06:15 +02:00
renovate[bot]
ccdb002ade
Update dependency gradle to v8.2 (#2326)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-05 15:50:49 +02:00
renovate[bot]
34ead35e03
Update dependency net.minecrell.plugin-yml.bukkit to v0.6.0 (#2327)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-05 15:50:20 +02:00
renovate[bot]
52a51753dd
Update dependency com.palmergames.bukkit.towny:towny to v0.99.2.7 (#2329)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-05 15:50:09 +02:00
Jordan
d7cc65d2f2
refactor: some changes that may help #2289 (#2307) 2023-07-03 16:37:42 +01:00
renovate[bot]
a0acbc7168
Update dependency org.mockito:mockito-core to v5.4.0 (#2328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 18:49:40 +02:00
renovate[bot]
e680e8fe1f
Update dependency com.palmergames.bukkit.towny:towny to v0.99.2.5 (#2325)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 08:47:03 +00:00
renovate[bot]
4583acda6b
Update auto.value to v1.10.2 (#2324)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 08:46:19 +00:00
Alexander Brandes
c880badaf4
[ci skip] Update renovate.json 2023-07-01 10:32:39 +02:00
dordsor21
83a4987252
chore: queue progress messages are not implemented 2023-06-30 19:36:35 +01:00
Alexander Brandes
903064fd41
Back to snapshot for development 2023-06-29 12:46:35 +02:00
Alexander Brandes
e5cbf33317
Release 2.6.4 2023-06-29 12:29:37 +02:00
Alexander Brandes
770bb0087a
Drop support for minor 1.19 versions (#2316)
* Drop support for minor 1.19 versions

* More work
2023-06-29 12:23:26 +02:00
Jordan
24325d91ba
feat: improve (region) fawe mask handling (#2312)
* feat: improve fawe mask handling
 - Actually cache masks, even if the player has left the region
 - Fix P2 isValid test for single plots
 - Fixes #1946

* Fix incorrect delegated method
2023-06-28 09:24:20 +01:00
Jordan
0554b31f11
feat: implement removal of entities if they would be in a block after the edit (#2311)
- Includes some refactoring to EditSessionBuilder to prevent doubling-up of processors that are also extents
 - Better ordering of the EditSessionBuilder process/extent code to match where extents actually end up in the stack
 - Fixes #1941
2023-06-27 18:37:09 +02:00
Jordan
476ba4ab41
refactor: efficiency improvements to some editsession methods (#2304) 2023-06-27 18:36:54 +02:00
Alexander Brandes
97ee71bbd0
Update settings name in queue.target_size warning 2023-06-27 13:56:30 +02:00
dordsor21
924805af8f
fix: fix obnoxious error message if using p2 v7 with FAWE main branch 2023-06-25 13:52:13 +01:00
dordsor21
05d5ad161a
chore: add obnoxious error message if using p2 v7 with FAWE main branch 2023-06-23 21:57:51 +01:00
Alexander Brandes
c0037aa083
[ci skip] Remove unsupported versions from template 2023-06-23 14:56:47 +02:00
Jordan
9f0a0dbd35
fix: ensure mask is initialised upon visiting a point in BreadthFirstSearch (#2314)
fix: ensure mask is initialised upon visiting a point in BreadFirstSearch
2023-06-22 21:32:54 +02:00
Jordan
d961aa91bc
fix: fix regex block masking (#2242) 2023-06-22 11:24:03 +01:00
Jordan
88533118bc
fix: uncache the chunk SET at a better time in ChunkHolder to prevent "lost" changes (#2300)
- blocks could still be set to the ChunkHolder during a call
 - create a new chunk SET in that case
 - make cached get/set volatile to improve thread safety
2023-06-19 22:46:10 +02:00
Jordan
8ca25fa7d7
fix: towny max bounds are exclusive (#2301)
fix: towny max bounds are exlusive
 - Fixes #2293
2023-06-19 22:46:01 +02:00
Jordan
01be53ed65
fix: add missing BlockType constructor (#2306)
- Deprecate public BlockType constructors
 - People really should not be initialising their own block types. This can and most likely will cause issues.
 - Fixes #2290
2023-06-19 14:36:47 +01:00
Jordan
a8c8a0fbd6
fix: always return the changeset from EditSessionBuilder (#2302)
- Ensure history will actually always be closed if combine-stages is false
- Fixes #2148
2023-06-19 14:34:54 +01:00
Jordan
1ede11b129
fix: use new array when creating palette (#2305)
- Fixes #2291
2023-06-19 14:34:02 +01:00
Jordan
39de48cdb1
chore: Address kotlin String#capitalize() deprecation (#2308)
* chore: Address kotlin String#capitalize() deprecation
 - Fixes #2283
 - Don't bother with the longer version that allows Locales, we don't need that

* Address comments
2023-06-18 16:31:49 +00:00
Jordan
f0aef98870
fix: don't "double-up" a setblocks if a region is being set (#2299)
- Fixes #2294
2023-06-18 18:08:31 +02:00
dordsor21
135c77cfb5
chore: minor changes
- null check get tile in ThreadUnsafeCharBlocks
 - 0 to reserved ID
2023-06-18 15:03:51 +01:00
renovate[bot]
78fb74665f
Update plugin com.modrinth.minotaur to v2.8.1 (#2298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-17 16:36:57 +02:00
Alexander Brandes
7a7373fd3d
Update paperweight 2023-06-17 16:16:16 +02:00
Jordan
51e238c352
feat: add new tree types to tree tool and brush (#2286)
* feat: add new tree types
 - implements #2197

* Remove nonsensical test case

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-06-15 10:18:01 +02:00
Jordan
79a2c14caa
fix #2292 2023-06-13 19:12:24 +02:00
Alexander Brandes
d9463ce8b5
Add support for 1.20.1 2023-06-12 16:36:06 +02:00
Jordan
dae6c69e54
feat: send one of an error message during edits if otherwise squashed by LimitExtent (#2246)
* feat: send one of an error message during edits if otherwise squashed by LimitExtent

* no region is not ingorable
2023-06-12 12:14:24 +02:00
Alexander Brandes
ed128797ec
Back to snapshot for development 2023-06-12 12:13:49 +02:00
Alexander Brandes
956a518238
Release 2.6.3 2023-06-12 11:58:38 +02:00
Jordan
e449910af5
feat: prevent edits outside +/- 30,000,000 blocks (#2285)
* feat: prevent edits outside +/- 30,000,000 blocks

* Remove import
2023-06-12 11:27:07 +02:00
LlmDl
ca4080eea7
Update & Fix TownyFeature support. (#2279) 2023-06-11 22:55:11 +01:00
Alexander Brandes
71c172cced
[ci skip] Update bug_report.yml 2023-06-11 12:09:27 +02:00
Hannes Greule
083f8a4dd8
Set proper field access and use mappings for entities on spigot (#2282)
set proper field access and use mappings
2023-06-10 22:47:22 +02:00
Alexander Brandes
689c7f62b8
Fixed setting sign text on 1.20 2023-06-09 15:27:02 +02:00
Alexander Brandes
bb14d93a8d
Add Console/CommandBlock support to Fabric/Forge/Sponge (2317) 2023-06-09 13:58:45 +02:00
Alexander Brandes
e7876c4eba
Update to 1.20 (#2276)
* Towards 1.20

* Init bukkit

* Update YAML to 2.0

* Fixes for 1.20 adapters

* Update obfuscated field names

* Remove getHandle workaround

* entityManager is obfuscated

* Update paperweight

* [ci-skip] Add 1.20 to modrinth task

---------

Co-authored-by: Phillipp Glanz <p.glanz@madfix.me>
Co-authored-by: SirYwell <hannesgreule@outlook.de>
2023-06-09 12:53:42 +02:00
Hannes Greule
152d870cdb
Improve exception handling on adapter loading (#2277) 2023-06-08 08:24:44 +00:00
Alexander Brandes
9be1a58bf3
Back to snapshot for development 2023-06-07 11:30:06 +02:00
Alexander Brandes
3b7d126718
Release 2.6.2 2023-06-07 11:11:54 +02:00
Alexander Brandes
832f93c0f3
Optimize PR builds (#2273)
* Optimize PR build

* Update codeql.yml
2023-06-07 00:51:56 +02:00
renovate[bot]
c5f66c342b
Update dependency com.palmergames.bukkit.towny:towny to v0.99.1.2 (#2272)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-07 00:35:50 +02:00
Jordan
1356cd5caa
feat: implement a player-specific queue for clipboard IO tasks (#2267)
* feat: implement a player-specific queue for clipboard IO tasks
 - Addresses #2222 (hopefully fixes)

* Address comments

* Add since

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-06-07 00:35:37 +02:00
Jordan
84872cf9a2
chore: improve queue documentation and submit history to better queue (#2266) 2023-06-06 19:22:25 +02:00
Jordan
b7719d17bd
fix: correctly processSet with blacklist when required (#2270)
* fix: correctly processSet with blacklist when required

* Fix incorrect region
2023-06-06 19:21:18 +02:00
Jordan
5504811f11
chore: minor improvements to processing-related code (#2271) 2023-06-06 19:21:02 +02:00
Alexander Brandes
bdb170a5ca
Explicit call repository task 2023-06-06 19:18:01 +02:00
dordsor21
5da5b216f3
fix #2268
-.-
2023-06-05 22:26:41 +01:00
Alexander Brandes
4b06796e76
Archive PR artifacts (#2269)
* Archive PR artifacts

* Fix artifact path
2023-06-05 10:51:26 +02:00
dordsor21
e5d27c27bb
chore: replace some hardcoded ordinals 2023-06-05 00:17:13 +01:00
dordsor21
46e8a37cf0
fix: improve test for polygonal region containment of cuboid
- Possibly fixes #2265
2023-06-04 23:57:51 +01:00
Jordan
e9fed5a066
feat: improve error when loading biomes (#2241) 2023-06-04 18:50:08 +02:00
Jordan
0e215e98d5
fix: minor changes to fix loading blocks outside stored range in ThreadUnsafeCharBlocks (#2260)
- Fixes #2258
2023-06-04 17:22:21 +02:00
EpicPlayerA10
97d4244126
Fix BlockEntity#remove spigot mapping (#2264)
Fix spigot mapping
2023-06-04 13:14:50 +00:00
Alexander Brandes
b7dc5f7ae5
[ci skip] Update Java tooling name 2023-06-04 13:29:07 +02:00
Alexander Brandes
c9a4a9c8b4
Update gradle to 8 (#2262)
* Update gradle to 8

* Update codeql.yml
2023-06-04 12:34:03 +02:00
dordsor21
048dcaf327
fix: do not always set random rotate to true
- Fixes #2259
 - How'd that even get through
2023-06-03 16:34:23 +01:00
Hannes Greule
4fa927f996
Extract common code when resizing arrays (#2257) 2023-06-02 19:39:00 +02:00
renovate[bot]
82418155f6
Update dependency com.github.TownyAdvanced:Towny to v0.99.1.0 (#2254)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: dordsor21 <dordsor21@gmail.com>
2023-06-02 12:21:16 +00:00
Hannes Greule
7646a067eb
Avoid many threads blocking on AbstractChangeSet#processSet (#2226) 2023-06-02 10:40:34 +01:00
renovate[bot]
03c4bafc45
Update antlr4 to v4.13.0 (#2256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 23:01:56 +02:00
Jordan
228e84e555
fix: Improve edit processing (#2247) 2023-06-01 15:11:16 +01:00
renovate[bot]
7ce17e5834
Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.8 (#2255)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 09:23:17 +02:00
Jordan
03487718e7
feat: configurable image hosts (#2243) 2023-05-31 16:48:45 +01:00
Jordan
a553961c05
refactor: switch to EnumSet for heightmaps to improve performance (#2248) 2023-05-27 14:25:07 +02:00
Jordan
3041ff3e50
feat: add -r (random rotate) flag to schem load and clipboard brush (#2244)
- Implements #1873
2023-05-25 19:06:20 +02:00
dordsor21
362f6cc6e1
fix #2009 2023-05-22 19:43:21 +01:00
Jordan
5dca925bc3
feat: make more commands unqueued (#2235)
* feat: make more commands unqueued
 - Effectively fixes the very specific "issue" in #2223 I guess
 - Use this opportunity to clean up the command classes a bit

* Address comments
2023-05-22 20:33:59 +02:00
Jordan
435161d566
fix: only send invalid region messages with debug true (#2238)
- Addresses #2188
2023-05-22 20:33:15 +02:00
Jordan
7c01c1e95e
feat: allow captions in SuggestInputParseException (#2239)
- Deprecate for removal methods using string message
 - Fixes #2026
2023-05-22 20:32:56 +02:00
Jordan
74aff920a8
fix: fix universal disallowed blocks logic in limit and EditSession compilation (#2237)
- Fixes #2184
2023-05-22 20:32:36 +02:00
Alexander Brandes
2bdc925b0f
Add regression tests to the round Expression function 2023-05-21 09:51:59 +02:00
Alexander Brandes
4c0b535e6e
Ensure non-Double types are boxed in expression function calls. 2023-05-21 09:50:10 +02:00
Alexander Brandes
86f06b7527
Add -Penginehub.obf.none=true gradle property to build mojmap worldedit-bukkit. 2023-05-20 21:01:34 +02:00
Alexander Brandes
5e3222c55d
Ensure blockmap uniqueness across TE values 2023-05-20 21:00:35 +02:00
Alexander Brandes
7f43e448d5
fix(core): Properly reinit convex CUI selection on primary click 2023-05-20 20:58:47 +02:00
Jordan
2c7b529f67
fix: create single threaded executor for use with non-concurrent generators (#2236)
- Fixes #2228
2023-05-20 20:56:46 +02:00
Alexander Brandes
3cac28ea84
Keep extending cuboid selector after //cli selectworld 2023-05-20 20:56:37 +02:00
Alexander Brandes
85214c944f
Keep extending cuboid selector after //paste -s/n 2023-05-20 20:54:52 +02:00
Alexander Brandes
264185a323
Add method to check initialize state in PlatformManager, deny access to registries when uninitialized 2023-05-20 20:52:03 +02:00
Jordan
85f5006a0b
fix: correctly handle creation of extents in EditSessionBuilder (#2232)
- Add regionExtent process to the queue (fixes #2227)
 - Correctly wrap extents in each other
2023-05-20 20:33:18 +02:00
Jordan
1b0fb9ed48
fix: more intuitive limit permissions (#2233)
- immediately return limit if unlimited (limit combination take the "higher" value)
 - add fawe.limit.unlimited permission and it's an intuitive permission to give
2023-05-20 20:32:38 +02:00
Jordan
3a13c4aaa7
chore: remove firework-chunk-loading prevention and default tick limiter to false (#2234)
- It's very resource-intensive and probably doesn't work anyway
 - Tick limiter should not be enabled by default, it confuses a lot of people with the console logs
2023-05-20 16:25:24 +02:00
Jordan
e9b781d127
fix: correctly in initialise unlimited limit (#2231) 2023-05-20 16:22:02 +02:00
Jordan
2a08ad28a4
fix: correct issues with processor scopes (#2230) 2023-05-20 16:21:11 +02:00
Marco Neuhaus
52723439dd
Fix reading of tile entities with "id" instead of "Id" tag (#2211) 2023-05-20 09:57:13 +00:00
Hannes Greule
a14035d430
Revert "Actually delegate in AbstractDelegateExtent" (#2229) 2023-05-16 10:32:03 +02:00
Alexander Brandes
319cb636e5
Simplify Java location in Jenkinsfile (#2221) 2023-05-12 23:46:38 +02:00
Hannes Greule
71bac009db
Properly scale the random in SimpleRandomCollection (#2220) 2023-05-12 23:13:35 +02:00
Phillipp Glanz
c57fee5b86
Fixes command context for bukkit console command sender (#2193) 2023-05-12 12:12:08 +01:00
dordsor21
dd6197922c
fix: remove invalid file length check
- NBT is stored at the end of the clipboard file
 - Fixes #2209
2023-05-10 17:27:44 +01:00
Hannes Greule
2987550e9b
Actually delegate in AbstractDelegateExtent (#2196)
* actually delegate in AbstractDelegateExtent

* exclude enableHistory method
2023-05-04 18:33:04 +02:00
Phillipp Glanz
e08720b310
Improve git ignore (#2206)
* Exclude run-server for all version

* Exclude run-server for all version

* Exclude run-server for all version

* Exclude run-server for all version

* Exclude run-server for all version

* Remove unsless entry
2023-05-04 18:30:10 +02:00
renovate[bot]
92a6ff5f88
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.5.5 (#2201)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 10:22:27 +02:00
renovate[bot]
950a3f9430
Update dependency com.github.TownyAdvanced:Towny to v0.99.0.5 (#2202)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 10:22:18 +02:00
renovate[bot]
4779bd4916
Update plugin xyz.jpenilla.run-paper to v2.1.0 (#2205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 10:20:24 +02:00
renovate[bot]
909b7d27b8
Update dependency org.ajoberstar.grgit:grgit-gradle to v5.2.0 (#2203)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 10:04:49 +02:00
renovate[bot]
ffe704d890
Update dependency org.mockito:mockito-core to v5.3.1 (#2204)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-01 10:03:49 +02:00
Alexander Brandes
9f3c909254
Back to snapshot for development 2023-04-23 23:01:03 +02:00
Alexander Brandes
abe120291f
Release 2.6.1 2023-04-23 22:47:30 +02:00
Hannes Greule
c86dfe45df
Ensure regen step not running on the main thread (#2185) 2023-04-23 22:15:37 +02:00
360shvit
488a2e5de4
Add an explanation to Disallowed-Blocks Comment (#2186)
Improve user experience by adding an explanation to Disallowed-Blocks Configblock (#2183)
2023-04-22 16:48:59 +00:00
Jordan
8cfb8cb322
chore: add chunk tickets to all chunks accessed (#2163)
- This isn't necessarily targeting any fix, but I think we should be ensuring a ticket is being added to chunks "access asynchronously", as done by the getChunkAtAsync method
2023-04-22 09:45:02 +00:00
Hannes Greule
05afaf00a9
Address incompatibilities after CraftChunk changes in spigot (#2179) 2023-04-21 23:21:50 +01:00
Hannes Greule
86acb1c4d4
Simplify command dispatch to ensure command order (#2131) 2023-04-18 16:28:38 +01:00
Jordan
5cd9616507
fix: Ensure BaseBlock is not returned when a BlockState is wanted in BlockTransformExtent (#2161
- NBT will be handled appropriately at another point
 - Fixes #2085
2023-04-13 17:34:16 +01:00
Jordan
e4158ac084
fix: invalidate cached FaweMask when a plot is unlinked (#2157)
* fix: invalidate cached FaweMask when a plot is unlinked
 - Fixes IntellectualSites/PlotSquared#3998

* Use a weakly-referenced copy of the copnncted plots set
2023-04-13 17:34:05 +01:00
6a7f51bba0 Update CI + Rebuild
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-04-11 12:50:25 +02:00
cdd4df37c6 Merge remote-tracking branch 'upstream/main'
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2023-04-11 11:58:22 +02:00
Phillipp Glanz
da4d966d9e
Fix Misaligned SVG In IJ project view (#2174) 2023-04-10 11:54:46 +02:00
Alexander Brandes
a42864e780
[ci skip] Move renovate config to .github folder 2023-04-07 15:12:55 +02:00
Alexander Brandes
2dc8f7bca9
Update paperweight version for 1.19.4 (#2166)
Update paperweight version
2023-04-07 15:11:12 +02:00
renovate[bot]
bb8c9d216b
Update dependency org.bstats:bstats-base to v3.0.2 (#2170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-07 15:10:46 +02:00
Phillipp Glanz
2b51896a01
Improve testability by adding more versions of runPaper to the build scripts (#2172)
* Improve testability

* Change to import
2023-04-07 15:10:14 +02:00
Alexander Brandes
b42f6a2f5e
Update renovate.json (#2167) 2023-04-01 17:53:36 +02:00
Jordan
a9e1d5009c
fix: add null-check for brush in traceMask (#2160)
* fix: add null-check for brush in traceMask
 - Fixes #2149

* Switch to print from printError

Co-authored-by: Alexander Brandes <mc.cache@web.de>

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-03-31 20:45:34 +02:00
Jordan
508b94ddc3
feat: improvements to clipboard on disk (#2162)
* feat: improvements to clipboard on disk
 - close clipboard on instantiation failure
 - set canHaveBiomes when loading clipboard from disk (only possible cause I can find for #2151 ..?)
 - check file length and give more appropriate error if it exceeds maximum. Fixes #2151 I guess?#
 - set byteBuffer to null before invoking cleaning. Addresses #1985
 - don't catch and print all exceptions when getBlock fails - prevents large console output for what is likely to be a failed operation anyway

* Fix comments
2023-03-30 00:13:50 +02:00
dordsor21
d82bf0527e
fix: use correct string for disallowed property use 2023-03-22 17:28:50 +00:00
Alexander Brandes
eb1c9dc4db
Apply stash 2023-03-19 10:34:49 +01:00
Alexander Brandes
9d63cb8102
Release 2.6.0 2023-03-19 00:34:10 +01:00
Alexander Brandes
efc917e6df
Add support for 1.19.4 (#2154)
* Add paper adapter for 1.19.4

* Add paper module for 1.19.4

* Port 1.19.3 to 1.19.4

* Switch to Paperweight release

* Update worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java

Co-authored-by: Antti Koponen <koponen942@outlook.com>

* Update worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java

Co-authored-by: Antti Koponen <koponen942@outlook.com>

* Add 1.19.4 to release template

* Update refractions for regen support

* Bump paperweight

---------

Co-authored-by: TheMeinerLP <p.glanz@madfix.me>
Co-authored-by: Antti Koponen <koponen942@outlook.com>
2023-03-18 15:25:04 +01:00
Phillipp Glanz
b54e3a5112
Add nether tress into floating tree remover (#2146)
* Add nether tress into floating tree remover

* Add nether stems
2023-03-17 21:58:53 +00:00
Alexander Brandes
09b899c7a9
[ci skip] Temp disable dc workflow 2023-03-17 22:25:41 +01:00
Jordan
7ab04317fa
fix: clear above and below plot gen heights if build heights are larger (#2153) 2023-03-17 21:56:48 +01:00
Phillipp Glanz
e32a8c40c6
Bump run paper to 1.19.3 and replace path with better solution (#2150) 2023-03-16 09:45:22 +00:00
renovate[bot]
df99226313
Update dependency com.github.TechFortress:GriefPrevention to v16.18.1 (#2142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-13 17:09:18 +01:00
renovate[bot]
5313f9c588
Update dependency org.mockito:mockito-core to v5.2.0 (#2144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-13 17:08:23 +01:00
renovate[bot]
0146b952c6
Update plugin io.github.gradle-nexus.publish-plugin to v1.3.0 (#2145)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-13 17:08:11 +01:00
Alexander Brandes
bfd919b3cb
Update paperweight 2023-03-07 15:39:22 +01:00
Alexander Brandes
b05e64a7ec
Fetch userdev plugin from plugin portal (#2136) 2023-03-07 15:35:33 +01:00
Alexander Brandes
ccb503e49d
[ci skip] Update CF workflow 2023-03-07 00:14:47 +01:00
Alexander Brandes
f7026338e9
Update adventure javadoc URL 2023-03-07 00:04:44 +01:00
Alexander Brandes
992eaf2b4c
Misc. dependency update to align with libs.versions.toml (#2134) 2023-03-06 15:44:21 +01:00
Hannes Greule
90baa790c3
Make custom toArray methods fulfill the method contract (#2089)
* Make PropertyKeySet#toArray(T) fulfill the method contract

* Make LocalBlockVectorSet#toArray(T) fulfill the method contract
2023-03-06 13:57:40 +01:00
Alexander Brandes
a63037b92d
Update renovate.json 2023-03-06 13:55:02 +01:00
Hannes Greule
8a3052683e
Use unsynchronized buffered OutputStream for history (#2127)
* Use unsychronized buffered OutputStream

* Add note

* Avoid synchronization on DataOutputStream#write
2023-03-06 13:54:35 +01:00
eztaK-red
211e8034ff
Fix off by one error for negative coordinates when using -r with //deform (#2092)
The problem: Off by one error for negative coordinates. Source: Behaviour of rounding coordinates (doubles) after deform.

The off by error came down to rounding using casts (int) and rounding using Math.floor()

(int)( 1.8) = 1
(int)(-1.8) = -1
(int)Math.floor( 1.8) = 1
(int)Math.floor(-1.8) = -2

Looking at the original WorldEdit implementation a Math.floor call is present too. It was missing FAWE which resulted in the bug.

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-03-06 13:53:07 +01:00
Alexander Brandes
94f57799d0
Pin GH actions to SHA to avoid mutable refs (#2126) 2023-03-06 13:51:53 +01:00
renovate[bot]
7152fd2032
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.5.3 (#2129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-06 13:47:13 +01:00
Alexander Brandes
84e1886672
Update developers field 2023-03-02 20:52:12 +01:00
Alexander Brandes
a1d35e26fa
Update developers field 2023-03-02 20:50:01 +01:00
renovate[bot]
214495f8f5
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.5.2 (#2122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-02 00:47:41 +01:00
Hannes Greule
526e1902ca
Fix FAWE using exclusive build height from PlotSquared (#2123)
Use inclusive build height maximum
2023-03-02 00:47:28 +01:00
renovate[bot]
6a31f4179c
Update dependency gradle to v7.6.1 (#2111)
* Update dependency gradle to v7.6.1

* Update gradle/wrapper/gradle-wrapper.properties

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-02-27 21:22:51 +01:00
Hannes Greule
1904b1fdd6
Fix reading block states in no redo mode (#2119) 2023-02-27 16:31:15 +01:00
renovate[bot]
c0dc42ed3f
Update dependency org.bstats:bstats-base to v3.0.1 (#2093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-25 11:11:09 +01:00
renovate[bot]
f95383e837
Update dependency org.ajoberstar.grgit:grgit-gradle to v5 (#2114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-25 11:10:23 +01:00
Alexander Brandes
c7ddee12d9
Revert "Update dependency gradle to v8 (#2094)"
This reverts commit b293a5eea3.
2023-02-25 10:42:01 +01:00
Alexander Brandes
7f6a27d083
Revert "Update dependency gradle.plugin.com.github.johnrengelman:shadow to v8 (#2113)"
This reverts commit 7a667131ba.
2023-02-25 10:41:49 +01:00
Alexander Brandes
184eb215b6
Move Jenkinsfile from ps-v7 to general branch (#2098)
* Move Jenkinsfile from ps-v7 to general branch

* Update Jenkinsfile
2023-02-25 10:31:33 +01:00
renovate[bot]
7a667131ba
Update dependency gradle.plugin.com.github.johnrengelman:shadow to v8 (#2113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-25 10:26:24 +01:00
renovate[bot]
b293a5eea3
Update dependency gradle to v8 (#2094)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-25 10:01:24 +01:00
renovate[bot]
f70e1a215a
Update dependency net.minecrell.plugin-yml.bukkit to v0.5.3 (#2112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-25 01:07:59 +01:00
9d5e96946c Merge pull request 'main' (#6) from Mirrors/FastAsyncWorldEdit:main into main
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #6
2023-02-23 10:18:59 +01:00
renovate[bot]
a464f1271d
Update plugin io.github.gradle-nexus.publish-plugin to v1.2.0 (#2109)
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-22 23:46:11 +01:00
renovate[bot]
b72c6902e2
Update antlr4 to v4.12.0 (#2103)
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-20 10:49:54 +01:00
renovate[bot]
8832820b6c
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.5.1 (#2095)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-19 12:11:04 +01:00
renovate[bot]
783dc353c4
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.5.0 (#2090)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-10 16:48:52 +01:00
Alexander Brandes
1e5b2fe0de
Back to snapshot for development 2023-02-07 23:25:17 +01:00
Alexander Brandes
19ed349740
Release 2.5.2 2023-02-07 23:13:05 +01:00
Hannes Greule
321a39f121
Remove PlayerMoveEvent listener and deprecate MovableTool (#2083)
Remove PlayerMoveEventListener and deprecate MovableTool
2023-02-07 23:07:57 +01:00
Hannes Greule
f9d6b127e6
Use Pattern Matching for instanceof in PropertyKeySet (#2086) 2023-02-07 23:07:31 +01:00
Alexander Brandes
07217d0b81
[ci skip] Document metrics addition 2023-02-07 22:50:21 +01:00
Alexander Brandes
b65f3ce1f8
Add metrics for Residence (#2081) 2023-02-07 10:47:49 +01:00
9f97dc2a3c Merge pull request 'Update upstream (for 1.19.3 support)' (#4) from upstream into main
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #4
2023-02-02 11:32:52 +01:00
1889f94a39 Fix ci
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2023-02-02 11:32:08 +01:00
b87a861098 Merge remote-tracking branch 'upstream/main' into upstream
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2023-02-02 11:20:09 +01:00
renovate[bot]
cd00bf9771
Update dependency org.mockito:mockito-core to v5.1.1 (#2078)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-31 11:21:29 +01:00
Hannes Greule
158e51191f
Linear Patterns require flooring division (#2079)
Use floorDiv in linear patterns
2023-01-31 11:21:11 +01:00
Alexander Brandes
214954bb09
Back to snapshot for development 2023-01-23 12:51:38 +01:00
Alexander Brandes
09d405935a
Release 2.5.1 2023-01-23 12:37:45 +01:00
95a06eb639 „steamwarci.yml“ ändern
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-01-18 21:04:30 +01:00
0c9317bb8c Deploy to maven repo
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2023-01-18 20:53:13 +01:00
Bernhard
5e8bc5c2ad
fix regex and remove forbidden windows characters (#2012)
refactor: fix regex and remove forbidden windows characters
2023-01-16 00:34:53 +01:00
TheJonstone✓
0f558425f5
Fix: remove unnecessary bypass permission (#2060)
Fix: remove unnecessary permission
2023-01-16 00:34:28 +01:00
Jordan
ae57ac5d50
fix: don't quash a cancellation FaweException in LimitExtent (#2068)
- This allowed some edits to continue after a player left the server when they shouldn't
 - Possible sort-of fix for #1985
 - Possible fix for #1955
2023-01-16 00:33:44 +01:00
Alexander Brandes
98c2d2124e
Split workflows (#2071) 2023-01-16 00:33:13 +01:00
Alexander Brandes
c0563b6574
Terminate process if .git folder does not exist (#2070)
Terminate process if folder is not a repository
2023-01-15 20:24:51 +01:00
renovate[bot]
606ffad12b
Update dependency org.mockito:mockito-core to v5 (#2069)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-14 10:46:24 +01:00
Hannes Greule
bb0e201c52
Remove usages of JoinedCharSequence (#2062) 2023-01-11 00:07:24 +01:00
renovate[bot]
452f968f07
Update antlr4 to v4.11.1 (#2064)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-09 16:52:48 +01:00
renovate[bot]
3ad70a8ef4
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.4.1 (#2063)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-09 16:33:32 +01:00
renovate[bot]
afe601bf93
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.18 (#2057)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-31 01:02:41 +01:00
renovate[bot]
7db1e9c7d6
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.17 (#2053)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-29 13:44:41 +01:00
renovate[bot]
b98c3efc88
Update dependency org.mockito:mockito-core to v4.11.0 (#2055)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-29 13:42:56 +01:00
Alexander Brandes
a9ed8431cd
Use the connection field on 1.19->1.19.3 rather than networkManager 2022-12-27 14:05:41 +01:00
renovate[bot]
a7c402d8dd
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.15 (#2050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-24 12:01:29 +01:00
renovate[bot]
f8acaf5ec2
Update dependency org.mockito:mockito-core to v4.10.0 (#2047)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-15 22:38:17 +01:00
Alexander Brandes
b0ac500fa1
Bump paperweight 2022-12-13 22:52:30 +01:00
renovate[bot]
83e0c84616
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.4.0 (#2044)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-13 22:44:47 +01:00
Alexander Brandes
26d5f10c04
Back to snapshot for development 2022-12-11 19:28:44 +01:00
Alexander Brandes
d6599fd332
Release 2.5.0 2022-12-11 19:10:40 +01:00
Bernhard
c3ce162fd5
Feature: add "h" as alias for "hand" and "oh" for "offhand" (#2033) 2022-12-11 18:36:33 +01:00
Alexander Brandes
f98e526fa0
Add support for 1.19.3 (#2042)
* 1.19.3

* More fixes

* fix: compile time issues for 1.19.3

* fix: new mappings and GeneratorStructureState

* Add 1.19.3 to release and issue template

* Update dependencies for 1.19.3

* Update worldedit-bukkit/adapters/adapter-1_19_3/build.gradle.kts

Co-authored-by: Pierre Maurice Schwang <mail@pschwang.eu>
2022-12-11 18:36:13 +01:00
Alexander Brandes
62f561cb56
Update dev bundle versions (#2040) 2022-12-09 12:38:10 +01:00
renovate[bot]
62345bb64e
Update plugin xyz.jpenilla.run-paper to v2.0.1 (#2039)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-09 10:10:09 +01:00
Hannes Greule
79c23e06c3
Clean up starlight usage (#2029)
clean up starlight usage
2022-12-04 18:56:41 +01:00
renovate[bot]
e0e66ce2db
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.4 (#2028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-30 10:09:39 +01:00
Alexander Brandes
41ea21f91d
Run announcement workflow after release workflow 2022-11-28 11:34:09 +01:00
Alexander Brandes
faa0908ba8
Run announcement workflow after 'build' workflow 2022-11-28 11:30:32 +01:00
renovate[bot]
eda5bced65
Update dependency gradle to v7.6 (#2027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-25 19:25:01 +01:00
renovate[bot]
c1bfadd328
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.3 (#2025)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-25 19:24:10 +01:00
renovate[bot]
b432faef36
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.11 (#2023)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-20 00:49:37 +01:00
renovate[bot]
6cb9f0e485
Update auto-value to v1.10.1 (#2019)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-20 00:44:22 +01:00
renovate[bot]
6f6c0508df
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.10 (#2022)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-20 00:39:43 +01:00
Alexander Brandes
15b351930d
Back to snapshot for development 2022-11-16 11:29:57 +01:00
Alexander Brandes
1771a04ef9
Release 2.4.10 2022-11-15 19:35:25 +01:00
Alexander Brandes
34dbaa633a
Add CF upload task (#2018) 2022-11-15 19:25:03 +01:00
renovate[bot]
fc701b9260
Update plugin xyz.jpenilla.run-paper to v2 (#2017)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-15 19:12:08 +01:00
renovate[bot]
77b1c7eb9c
Update dependency org.mockito:mockito-core to v4.9.0 (#2016)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-15 19:04:13 +01:00
Pierre Maurice Schwang
f33d93591a
Fix Chorus-Plant tree type generation (#2015)
fix: chorusplant tree type must generate inside end_stone
2022-11-14 22:58:54 +01:00
renovate[bot]
f9527ce2b7
Update plugin xyz.jpenilla.run-paper to v1.1.0 (#2007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-13 12:14:14 +01:00
renovate[bot]
7f8b0a7e21
Update dependency com.github.TownyAdvanced:Towny to v0.98.4.0 (#2008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-13 11:59:17 +01:00
Pierre Maurice Schwang
4c2119e404
Fix error on latest paper while copying entities (#2006) 2022-11-10 17:45:35 +00:00
renovate[bot]
1aa213fb4c
Update dependency com.github.TownyAdvanced:Towny to v0.98.3.19 (#2003)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-06 11:15:01 +01:00
Alexander Brandes
983e4407b5
Back to snapshot for development 2022-11-02 09:52:28 +01:00
Alexander Brandes
0ee18597ae
Release 2.4.9 2022-11-02 09:45:48 +01:00
Pierre Maurice Schwang
2fe54a04b5
Adjust platform specific code to recent changes (#1997)
* chore: remove usage of MCUtil in StarlightRelighter

* chore: cleanup of unused imports

* hacky shit-fuckery for papers new chunksystem und refactor

* chore: address review comments

* Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.9 (#2001)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* fix: suppress exceptions for field retrieval, cache fields / methods

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-02 09:41:20 +01:00
Hannes Greule
bbc1db9bd2
Read minecraft version from paper if available (#2002)
* read version from paper if available

* fix for versions without release information
2022-11-01 23:39:42 +01:00
renovate[bot]
e305c5d5ab
Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.9 (#2001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-01 22:45:58 +01:00
renovate[bot]
8127d57158
Update dependency com.github.TownyAdvanced:Towny to v0.98.3.15 (#1993)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-25 23:58:53 +02:00
Jordan
0d112b2913
fix: move main-thread call to be implementation from WorldWrapper (#1991)
- Fixes #1990
2022-10-23 21:22:53 +02:00
Jordan
bf28ab47b8
fix: bring default min/max y in line with upstream in AbstractRegion (#1992)
- Fixes #1987
2022-10-23 21:22:43 +02:00
renovate[bot]
e36b838227
Update dependency org.mockito:mockito-core to v4.8.1 (#1988)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-22 10:25:54 +02:00
Alexander Brandes
4f74cc671f
Back to snapshot for development 2022-10-18 23:25:52 +02:00
Alexander Brandes
dce86ec046
Release 2.4.8 2022-10-18 23:23:35 +02:00
Jordan
2082df4141
fix: Add blocked blocks to the correct set (#1975)
* fix: Add blocked blocks to the correct set

* Address comment
2022-10-13 19:21:25 +02:00
Jordan
8971d7064c
feat: Reduce any spam caused by exceptions thrown when writing history (#1976)
- Closes #1960
2022-10-13 19:21:02 +02:00
Jordan
ccb31c0ecc
fix: Do not cast y to byte in history database (#1978)
- y is/was already stored as an int
 - Fixes #1931
2022-10-13 19:20:17 +02:00
Hannes Greule
13eb1f815f
Fix mappings issue with biome-based regen on 1.18.2 (#1982)
access correct fields
2022-10-13 19:20:01 +02:00
Jordan
878509406b
fix: Add items to a player's inventory on the main thread (#1977)
- Fixes #1954
2022-10-12 20:48:56 +02:00
Alexander Brandes
33be942176
[ci skip] Rewrite README for modrinth (#1979)
docs: Rewrite README for modrinth
2022-10-09 16:41:22 +02:00
Alexander Brandes
f356f64c3d
[ci skip] chore: Announce releases on discord (#1980) 2022-10-09 16:40:04 +02:00
Pierre Maurice Schwang
598cd6ba19
Don't error when NPC-annotated "entity" leaves the server (#1969)
fix: no need to remove never-added attachment
2022-10-08 13:34:50 +02:00
Alexander Brandes
292d9f2439
chore: Re-enable CodeQL (#1973) 2022-10-08 13:34:25 +02:00
Alexander Brandes
a62b3158a7
Back to snapshot for development 2022-10-04 14:21:55 +02:00
Alexander Brandes
18bf911fdc
Release 2.4.7 2022-10-04 14:05:36 +02:00
Alexander Brandes
ad38d88642
[ci skip] Link to GH releases (#1970)
chore: Link to GH releases
2022-10-04 13:28:10 +02:00
Aurélien
2e386ea391
Fix region restrictions with methods non-overriden (#1948)
Fix region registrictions with methods non-overriden
See https://github.com/IntellectualSites/fastasyncvoxelsniper/issues/195 for context
2022-10-03 11:20:53 +02:00
Alexander Brandes
a32d8dcbdb
Release to Modrinth (#1968)
* feat: Release to Modrinth

* chore: List-ify gameVersions
2022-10-02 21:50:16 +02:00
Alexander Brandes
87f680683d
Update Upstream
0ef38b5 Use SnakeYaml 1.32+, set loader code point limit. (2194)

Defaults to 64MB, can be set via -Dworldedit.yaml.codePointLimit sysprop.
2022-09-26 23:45:06 +02:00
942570c754 Merge pull request 'Move Clipboards to /tmp + Update upstream' (#3) from upstream into main
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #3
Reviewed-by: YoyoNow <jwsteam@nidido.de>
2022-09-24 19:48:09 +02:00
ae66ccfa8f Fix ci
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2022-09-24 19:32:14 +02:00
c0a135acc9 Merge remote-tracking branch 'upstream/main' into upstream 2022-09-24 19:28:53 +02:00
Alexander Brandes
10b852d416
Back to snapshot for development 2022-09-21 16:45:40 +02:00
Alexander Brandes
4f26561cc1
Release 2.4.6 2022-09-21 16:41:07 +02:00
Pierre Maurice Schwang
ab55d07ffd
Fix #saturate-Pattern (#1944)
* fix: block type access + resources in #saturate pattern

* chore: no need to download jar file in loadModTextures
2022-09-21 16:17:41 +02:00
Alexander Brandes
1706d64ddf
Retrieve the latest asset release version automatically (#1947)
* feat: retrieve the latest release version automatically

(cherry picked from commit a8885a349a567849f6db29565cc65b14e3dab155)

* feat/fix: validate hash of downloaded asset file

* chore: address review comments
Usage of nio Path instead of direct File access
Usage of HexFormat instead of custom implementation
No need for usage of channels

* chore: simplified sha-1 calculation logic

Co-authored-by: Pierre Maurice Schwang <mail@pschwang.eu>
2022-09-15 21:19:31 +02:00
renovate[bot]
c819031d1f
[ci skip] Update dependency com.github.TownyAdvanced:Towny to v0.98.3.8 (#1936)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-12 11:18:46 +02:00
renovate[bot]
2547fd590d
Update dependency org.mockito:mockito-core to v4.8.0 (#1940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-12 11:16:14 +02:00
dd8ed8d5c6 Move clipboards to temp
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2022-09-06 21:34:13 +02:00
2553f169aa Merge pull request 'main' (#2) from Mirrors/FastAsyncWorldEdit:main into upstream
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
Reviewed-on: #2
2022-09-06 21:32:29 +02:00
Alexander Brandes
673b467ad9
Back to snapshot for development
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2022-09-05 11:29:51 +02:00
Alexander Brandes
122b32b9f0
Release 2.4.5 2022-09-05 11:26:31 +02:00
Hannes Greule
5da558e24c
feature: support paper chunk system (#1884)
* avoid usage of ticking chunk future on paper

* fix entity handling

* fix entity handling but on spigot

* seems like no one uses spigot

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-09-04 23:30:32 +02:00
Alexander Brandes
3b109ba3ff
Upload files to curseforge on release (#1929)
* chore: Upload files to curseforge on release

* chore: Use direct artifact path
2022-09-04 23:30:02 +02:00
renovate[bot]
8233f132d4
Update dependency com.github.TownyAdvanced:Towny to v0.98.3.6 (#1926)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-29 21:31:06 +02:00
Alexander Brandes
aa216a990a
Update upstream
7e61ff1 Work around invalid legacy values in schematics (2171)
2022-08-29 17:21:21 +02:00
Hannes Greule
a51863c6f0
fix: use proper level data for regen (#1921) 2022-08-27 15:49:01 +01:00
Hannes Greule
a6a0b5eb66
fix: avoid recursive LegacyMapper initialization (#1922) 2022-08-27 15:48:54 +01:00
d5722fe9a5 Fix ci
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2022-08-27 11:44:59 +02:00
c3b43e13e3 Improve initialisation performance
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2022-08-27 11:35:56 +02:00
8348c0bf19 Merge remote-tracking branch 'upstream/main' 2022-08-27 11:34:50 +02:00
Alexander Brandes
dc2db5f07f
Back to snapshot for development 2022-08-24 10:07:22 +02:00
Alexander Brandes
37bbebcc9d
Release 2.4.4 2022-08-24 10:06:31 +02:00
Alexander Brandes
d5acb4ec51
fix: Lazy fix macro stacktrace (#1911) 2022-08-24 10:02:25 +02:00
e5833aff58 Merge remote-tracking branch 'origin/main'
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2022-08-21 17:58:20 +02:00
113c02ec3f Fix demon 2022-08-21 17:57:41 +02:00
0f74e2a0bb Merge pull request 'Remove Schematic Command' (#1) from remove_schematic_command into main
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #1
Reviewed-by: Lixfel <lixfel@steamwar.de>
2022-08-21 17:50:28 +02:00
Chaoscaot
d4c8bd084e Remove Schematic Command
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2022-08-21 17:40:19 +02:00
d67ec4fd63 Add CI
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2022-08-21 17:31:44 +02:00
Alexander Brandes
60ad2b51e8
[ci skip] chore: Add renovate schema URL 2022-08-20 15:31:42 +02:00
Hannes Greule
ab659eadde
fix: upstream missing Region#getBoundingBox() (#1908)
Use block change limit for //copy and //cut

(cherry picked from commit fd8dbdd7b7b8b561db98a45b4eae3810dedb1551)
2022-08-19 13:41:24 +02:00
renovate[bot]
cc1b466a04
build: Update dependency com.github.TownyAdvanced:Towny to v0.98.3.5 (#1906)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-15 23:49:00 +02:00
renovate[bot]
26bd9ec5ee
build: Update dependency org.mockito:mockito-core to v4.7.0 (#1904)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-13 17:16:52 +02:00
Alexander Brandes
5c2679f95d
Update Upstream
55e2d3d Catch InvalidPathException in safeFile handler (2167)

Closes #1872
2022-08-10 09:47:53 +02:00
Alexander Brandes
129f4f37a3
chore: Update assets to 1.19.2 (#1900) 2022-08-07 11:44:40 +02:00
Alexander Brandes
c520e1a686
Update upstream
54ed9e8 Add support for Y-offsets with back direction (2164)
2022-08-07 09:13:09 +02:00
Alexander Brandes
e78277e158
build: Update paperweight (#1901) 2022-08-06 22:41:03 +02:00
Alexander Brandes
86a9866455
build: Back to snapshot for development 2022-08-06 16:21:56 +02:00
Alexander Brandes
2a55bb5cfc
build: Release 2.4.3 2022-08-06 16:19:53 +02:00
renovate[bot]
8c8d5d5064
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.3.4 (#1897)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-06 13:54:03 +02:00
Alexander Brandes
a91519e09d
Update bug_report.yml 2022-08-06 13:48:49 +02:00
renovate[bot]
a0b35c9cda
build: Update dependency gradle to v7.5.1 (#1899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-06 13:48:24 +02:00
Alexander Brandes
a414fd308e
Add 1.19.2 (#1898)
feat: Add 1.19.2
2022-08-05 17:05:15 +02:00
Aurélien
e942175559
Improve `MainUtil#copyFile` (#1888) 2022-08-02 11:25:56 +02:00
Alexander Brandes
7a498497c5
chore: Use 1.19.1 asset URL (#1889) 2022-08-01 09:50:27 +02:00
Alexander Brandes
8b95c25194
Update bug_report.yml 2022-07-29 19:01:55 +02:00
Alexander Brandes
8d57c0b888
build: Back to snapshot for development 2022-07-28 10:32:10 +02:00
Alexander Brandes
8414e64bab
build: Release 2.4.2 2022-07-28 10:29:59 +02:00
Alexander Brandes
50ee45fedd
feat: Add support for 1.19.1 (#1887) 2022-07-28 10:26:43 +02:00
Alexander Brandes
e10774598e
chore: Reword light command messages (#1885) 2022-07-25 18:49:18 +02:00
peaches
77a929f6a1
fix: use servers removeGameEventListener instead of reimpl (#1881)
* fix: use servers removeGameEventListener instead of reimpl

* fix: 1.18.2 impl
2022-07-25 18:49:10 +02:00
dordsor21
a1babd5ec9
biomes is now an two-dimensional array in CharSetBlocks
- Fixes #1878
2022-07-17 17:33:51 +01:00
renovate[bot]
72f9b34f15
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.3.2 (#1877)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-17 16:38:51 +02:00
Alexander Brandes
4fc2a25a9a
Update Upstream
d7b3c4c Clone the returned getRegion on BlockArrayClipboard (2144)
2022-07-16 11:08:42 +02:00
renovate[bot]
7a1a33aff0
build: Update dependency gradle to v7.5 (#1875)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-14 17:02:10 +02:00
Alexander Brandes
282e47dd19
build: Return to snapshot for development 2022-07-12 22:30:40 +02:00
Alexander Brandes
4aa84776ba
build: Release 2.4.1 2022-07-12 22:29:45 +02:00
renovate[bot]
4013eceb8e
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.3.1 (#1860)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-12 22:22:50 +02:00
Alexander Brandes
42956839ee
[ci skip] chore: Update renovate excludes
Closes #1870
2022-07-03 13:52:33 +02:00
Aeliios
92518f71be
Correct return type for CuboidRegion#getFaces() upstream compatibility (#1866) 2022-07-03 12:43:13 +01:00
Aeliios
902f153929
Getting correct String from CompoundTag (#1867) 2022-07-03 12:43:03 +01:00
Alexander Brandes
def84a80c6
docs: Use rootProject.name over project.name for javadocs title (#1859)
* docs: Use rootProject.name over project.name for javadocs title

* docs: Add module name as well
2022-06-29 23:18:39 +02:00
Alexander Brandes
ffd98ad6d9
build: Update paperweight
Follow up to renovate PR
2022-06-28 17:38:46 +02:00
renovate[bot]
db37c28a2f
[ci skip] build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.8 (#1855)
* build: build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.8

* Update renovate.json

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-06-28 10:17:22 +02:00
Alexander Brandes
1400ce9958
[ci skip] chore: Exclude unused modules from renovate 2022-06-27 18:54:15 +02:00
Alexander Brandes
dbfb521795
build: Update bom to 1.9 2022-06-27 16:52:27 +02:00
dordsor21
3212dddb2d
Fix BlendBall for no mask 2022-06-27 13:38:22 +01:00
Alexander Brandes
041f4505a3
build: Back to snapshot for development 2022-06-27 13:57:35 +02:00
Alexander Brandes
f812fc14ab
build: Release 2.4.0 2022-06-27 13:52:50 +02:00
renovate[bot]
edfc5a7a01
[ci skip] build: build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.6 (#1843)
build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.6

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-27 09:51:50 +02:00
Jordan
34ea713d29
Fix walls command on 1D/2D selection (#1821) 2022-06-24 15:04:11 +01:00
dordsor21
38d1a64bf5
Correctly recycle CharSetBlocks 2022-06-24 15:03:48 +01:00
dordsor21
9762e4e220
Add Object2ObjectArrayMap to "DoNotMinimiseThese" class
- Fixes #1839
2022-06-24 10:43:21 +01:00
Jordan
8094b68967
Actually implement ChunkHolder/ChunkSet pools (#1840) 2022-06-24 10:13:58 +01:00
Jordan
800988aae7
Assume a file not being in a subdirectory of root means a symlink is used (#1838) 2022-06-23 17:32:21 +01:00
dordsor21
010611c4ac
Don't hide ChunkHolder generic "T" type paramter 2022-06-23 16:10:30 +01:00
Jordan
704f87da23
Re-implement incremental schematic names in a folder (#1833)
* Re-implement incremental schematic names in a folder
 - Fixes #1545

* Move fawe end comment

* Slight cleanup
2022-06-23 10:23:22 +02:00
Jordan
100288ada5
Implement a "sensitivity" setting, a mask, and an option to only distinguish air vs blocks to blendball (#1832) 2022-06-22 12:50:22 +01:00
Jordan
d498996cbd
Use Material rather than legacy int/data when specifying block break effect type (#1829) 2022-06-22 12:50:09 +01:00
NotMyFault
e3f2d5f737
[ci skip] docs: Add JB to Readme 2022-06-21 21:30:14 +02:00
Jordan
968799503f
Re-implement full Entity support in history, entity removal, entity creation, etc. (#1812)
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-06-21 14:52:02 +01:00
dordsor21
d62c88a2ca
Remove unused import 2022-06-21 13:00:19 +01:00
dordsor21
8b05738929
Remove P2 apidescription annotation 2022-06-21 12:58:21 +01:00
Jordan
c5073d79e7
Account for use of MutableBlockVector3 in Spline Brush (#1831) 2022-06-21 12:56:02 +01:00
Jordan
3f103eea9b
Set the correct delegate to the ChunkHolder when using get or set in NULL delegate (#1830) 2022-06-21 12:55:51 +01:00
renovate[bot]
fe90142f1f
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.5 (#1834)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-21 10:12:19 +02:00
Alexander Brandes
2ecf32b37c
chore: Add runServer task (#1835) 2022-06-20 17:56:51 +02:00
Jordan
dacb89a480
Bring stack in line with upstream using offset rather than direction (#1822)
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-06-20 10:46:19 +02:00
Jordan
396faf6732
Support using //distr on console properly (#1827) 2022-06-19 22:35:36 +01:00
Jordan
dac3610bcf
Implement generation of biome decorations to //regen <biome> and add option for a random seed to be used (#1819) 2022-06-19 22:33:16 +01:00
Jordan
692a010c39
Actually apply source mask when using //paste -m <mask> (#1810) 2022-06-19 22:33:01 +01:00
Jordan
84f6039f41
Fix #fullcopy -r (#1816) 2022-06-19 00:59:11 +01:00
Jordan
aadd35c0c4
Don't limit split size for extra block data (signs, spawner, etc.) (#1818) 2022-06-19 00:58:59 +01:00
Jordan
8e5204c311
Allow editing solely of tiles/entities/heightmaps (#1817) 2022-06-19 00:58:54 +01:00
Jordan
003cec30be
Fix saving entities in DiskOptimizedClipboard when no tiles are present (#1815) 2022-06-19 00:58:47 +01:00
Jordan
907ad8528e
Don't do the unbelievable bad use of a MutableBlockVector2 in the creation of a set (#1825)
* Don't do the unbelievable bad use of a MutableBlockVector2 in the creation of a set
 - Fixes IntellectualSites/PlotSquared#3683

* Clean up remnants of the use of MutableBlockVector2
2022-06-17 23:41:25 +02:00
Jordan
d2b4154cc0
Properly support extended world heights (y > 255) in tripleBlockCoord (#1805) 2022-06-17 15:39:27 +01:00
Alexander Brandes
5b72f396bb
docs: Publish javadocs to GH pages (#1824)
* docs: Publish javadocs to GH pages

* chore: Use up to date URLs

* chore: Update README url
2022-06-17 15:09:32 +02:00
Jordan
fd00635533
Fixes to BlockMask and "char" masks (#1787)
* If a char mask  is successfully created from the full input, return it

* Don't double-up adding a block to a BlockMaskBuilder (if adding by regex is successful)
 - InputParseException is thrown if unsuccessful

* Fix optimisation of BlockMask for negation of a single block type
 - Fixes #1755

* Allow early returning of an optimized MaskIntersection to avoid unnecessary work

* Actually allow underscore in isAlphanumericUnd
 - Fixes #1626

* Replace a few more hard-coded air internal IDs

* Don't fail silently if BlockMaskBuilder#addRegex doesn't work when testing all block types

* Remove unused import
2022-06-16 16:24:48 +02:00
Jordan
f2bab901f4
The extent minY check in clipboard paste is un-needed as it is handled gracefully by FAWE (#1806)
- Fixes #1771
2022-06-16 16:24:00 +02:00
Jordan
1da987d594
Fix PNGWriter exporting blank PNGs (#1807)
* Fix horrendous variable assignment in PNGWriter
 - Fixes #1679

* More detailed information on PNG format

* Avoid a larger number of blocks that do nto have a color assigned in TextureUtil

* Don't error in PNGWriter if biomes aren't saved to clipboard and grass is present
2022-06-16 16:23:52 +02:00
Jordan
ac11da855a
Processor should be added to queue, not extent (#1809)
- Fixes #1559 root cause
2022-06-16 16:23:45 +02:00
Jordan
9395b3c575
Prevent unhinged tree generation by doing a sanity check on the block below/block of the tree placement (#1811) 2022-06-16 16:23:37 +02:00
dordsor21
462bba4f87
Fix biome history on 1.19 2022-06-15 18:52:49 +01:00
Jordan
cb6e200ca6
Use the correct CuboidRegion constructor to prevent clipboard height being limited when loading schematics (#1798)
Use the correct CuboidRegion constructor to prevent clipboard height being limited when loading schematicsd
 - Fixes #1757
2022-06-15 13:37:32 +02:00
Jordan
ea434163c4
Only create entities during a restore if they are contained by the region and the editsession's mask (#1800) 2022-06-15 13:37:20 +02:00
Alexander Brandes
5b2f8502fb
fix: Run GriefPrevention region check in sync (#1804)
* fix: Run GP check in sync

Fixes #1692

* refactor: Sync on last condition only
2022-06-15 13:37:08 +02:00
Alexander Brandes
1a3b0dc133
chore: Rename legacy adapters artifact to improve matching with FAWE (#1813)
chore: Rename adapters artifact
2022-06-14 23:59:53 +02:00
dordsor21
111d604075
Follow up to 39e1a811f7 to fix DOC loading 2022-06-14 17:20:59 +01:00
Alexander Brandes
aae696686d
fix: Don't export Paster transitively on the core module (#1808) 2022-06-14 17:02:11 +02:00
Alexander Brandes
8a85225523
fix: Suppress Tuinity light exception on 1.16 (#1801)
* fix: Suppress Tuinity light exception on 1.16

Fixes #1591

* chore: mv'd to the right directory
2022-06-14 09:21:31 +02:00
Owen
39e1a811f7
Don't apply offset to SimpleClipboard (#1751)
* Fix offset

* Don't apply offset in SimpleClipboard

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-06-13 23:42:50 +02:00
Jordan
b797655d0c
Only implement cache to MaskingExtent when off main thread (#1789)
* Only implement cache to MaskingExtent when off main thread
 - It's possible for a [Chunk/Char]FilterBlock to be used multiple times in the same "tree" of method calls meaning the mutable paramets (particularly index) get increased within a loop, causing AIOOBs and other issues
 - This is only possible on the main thread due to the handling of submissions in SingleThreadQueueExtent, as it ensures all operation remains on the main thread to prevent deadlocks
 - Therefore safe usage of FilterBlocks requires that main-threaded operation create a new [Chunk/Char]FilterBlock instance each time
 - Further fixes #1681

* Fix typos

* Switch to LongFunction
2022-06-13 23:42:40 +02:00
Jordan
97ab47c90b
Command block messages should be sent on the main thread as it causes a block update (#1796)
- Fixes #1786
2022-06-13 23:42:26 +02:00
dordsor21
f8583fb7cb
Remove erroneous world height 256 limit 2022-06-13 15:11:39 +01:00
Alexander Brandes
a6b1b411d5
chore: Update upstream
3433e40 Fix CB watchdog, fail early if it breaks
2022-06-13 15:09:24 +02:00
Alexander Brandes
99a57f31b2
[ci skip] chore: Exclude doctools dependencies
Closes #1795
2022-06-13 09:07:47 +02:00
Jordan
63f031b01a
Only synchronise tree generation at the very lowest level (#1788)
* Only synchronise tree generation at the very lowest level
 - Fixes #1681

* Perform the generate inside try-finally and actually use the resultant copied map to place blocks to the editsession

* Check result of generateTree and return null if failed
2022-06-13 09:05:18 +02:00
Jordan
02a6bb9b27
Implement limits to image size and load times (#1790)
* Implement limits to image size and load times
 - Prevents issues caused by users attempting to load large images
 - Implements #1729

* Check dimensions given before attempting to load image
2022-06-13 09:04:59 +02:00
renovate[bot]
8377b0987c
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.3 (#1791)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-13 09:04:30 +02:00
renovate[bot]
ab4f779445
[ci skip] build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.7 (#1792)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-13 09:04:13 +02:00
Alexander Brandes
ccc936534b
[ci skip] chore: Update renovate ignores
Closes #1794
2022-06-13 09:03:17 +02:00
renovate[bot]
c3cb2c5ed7
[ci skip] build: Update dependency net.minecrell.plugin-yml.bukkit to v0.5.2 (#1793)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-13 09:01:54 +02:00
Alexander Brandes
c62f0c197f
build: Back to snapshot for development 2022-06-10 23:45:42 +02:00
Alexander Brandes
e54cae33f1
build: Release 2.3.0 2022-06-10 23:34:05 +02:00
Alexander Brandes
aa94612b70
feat: Add support for 1.19 (#1783)
* feat: Add support for 1.19

* build: Update paperweight version

* fix: obfuscated names, invalid method signatures

* avoid NPE on config access

* build: Update paperweight

* implement no-op light engine to avoid stalled tasks that never complete

* Apply DelegateSemaphore fixes to 1.19 (#1782)

* Apply DelegateSemaphore fixes to 1.19

* Fixes

* Avoid using PalettedContainerRO#recreate as much as possible. Show an error or warning when we're forced to use it to help fix (#1784)

Co-authored-by: Pierre Maurice Schwang <mail@pschwang.eu>
Co-authored-by: SirYwell <hannesgreule@outlook.de>
Co-authored-by: Jordan <dordsor21@gmail.com>
2022-06-10 23:22:06 +02:00
Jordan
da3fc2e6ea
Fix DelegateSemaphore synchronisation issues on Spigot (#1781)
* Fix DelegateSemaphore synchronisation issues on Spigot
 - Also effectively nullify it on paper - the synchronisation on the object is enough

* Remove unneeded imports
2022-06-10 19:50:16 +02:00
Alexander Brandes
7f8ce69563
[ci skip] docs: Add 1.19 to the issue template
Touches #1780
2022-06-10 15:39:00 +02:00
Alexander Brandes
3ec17f3507
chore: Drop WEManager#cancelEditSafe() logger (#1779) 2022-06-10 01:26:59 +02:00
Alexander Brandes
c5a50179f2
[ci skip] build: Switch to bom (#1778)
* build: Switch to bom

* chore: Use javax over checkerframework
2022-06-10 01:26:48 +02:00
Alexander Brandes
d7d43869e6
chore: Update upstream
31e5298 Fixed //stack erroring when given a count of 0 (2108)
2022-06-10 01:05:51 +02:00
Alexander Brandes
9b3608aada
chore: Update upstream
c515eb5 Cache properties to reduce startup memory (2103)
2022-06-10 01:02:03 +02:00
Jordan
0b33fa8757
Allow NBT stored in DiskOptimizedClipboards to be written to disk as a compressed byte array at the end of the file (#1745)
* Allow NBT stored in DiskOptimizedClipboards to be written to disk as a compressed byte array at the end of the file

* Add some deprecations/javadocs and provide the expected clipboard version on error

* Javadoc since tags and add location of clipboard folder to error

* Refactor load-from-file method into DOC class

* Refactor nbt loading code into separate method in DOC
2022-06-09 12:48:35 +02:00
Owen
af234b284b
Add block break effect to area pickaxe (#1770)
* Add block break effect to area pickaxe

* Create pos lower

* Check before queueing block effect

* comment
2022-06-09 12:48:24 +02:00
Owen
a16074cbe4
Fix //snowsmooth not working below Y0 (#1769)
* Use min y instead of 0 for SnowHeightMap

* Correctly handle rounding for height

* Revert old fix

* Use y instead of newHeight

* Remove line diff
2022-06-07 12:06:03 +02:00
renovate[bot]
d5a84d6e44
build: Update dependency org.mockito:mockito-core to v4.6.1 (#1773)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-06 09:49:00 +02:00
Jordan
32231b48fe
Avoid int overflow when using fillr in negative coords (#1711)
Fix int overflow when using fill and fillr in negative y-coordinates
2022-06-05 20:52:36 +02:00
Jordan
198c6b7800
Some fixes and improvements to internal queuing (#1715)
* the set array given in NMSAdapter should have get data written to it
 - Fixes #1664
 - May fix #1700

* Having target size >= 2* parallel threads allows for adjacent chunks to be loaded with issues

* "empty" chunk section doesn't need to be localised to the chunk and may be static

* Switch to slightly more performant stream method for testing for non-empty sections

* Implement lock into ChunkHolder preventing any modification to occur whilst the edit is being applied to the world
 (when ChunkHolder is called)

* Add config note about target-size

* set ordinal equal to air if both set and get are `__reserved__`

* Add note to checkAndWaitOnCalledLock method of its use

* Don't print exception and throw

* Switch to a wrapped StampedLock allowing reentrant behaviour
 - StampedLock is not reentrent
 - Allow unlock from a different thread only if it provides the correct stamp
 - This stamp can only be retrieved by the thread owning the lock

* Avoid some "doubling-up" of using checkAndWaitOnCalledLock

* Unbloat `checkAndWaitOnCalledLock`

* Add since tags
2022-06-05 20:52:28 +02:00
Jordan
8228b798e5
Implement biomes to filter blocks and use in Clipboard pasting (#1743)
- Fixes #1741
2022-06-05 20:52:14 +02:00
renovate[bot]
02eea35c3f
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.2 (#1766)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-31 18:13:02 +02:00
Alexander Brandes
9804158865
[ci skip] chore: Update renovate schedule 2022-05-31 00:28:11 +02:00
renovate[bot]
69eae2e4bd
[ci skip] build: Update dependency org.mockito:mockito-core to v4.6.0 (#1765)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-30 13:59:56 +02:00
renovate[bot]
f9c56d94c5
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.2.1 (#1764)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-30 13:58:43 +02:00
Alexander Brandes
a43fa912d6
[ci skip] build: Update renovate schedule 2022-05-30 13:57:26 +02:00
Alexander Brandes
8f01a5e4be
[ci skip] feat: Update Readme SVG (#1763) 2022-05-30 13:47:36 +02:00
renovate[bot]
6bb58dc113
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.13 (#1759)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-23 13:10:57 +02:00
BlockyTheDev
d1f3ac8f76
chore: Update PaperMC repository URL (#1756)
* Migrate PaperMC Repository Endpoints

* Migrate PaperMC JavaDocs endpoints
2022-05-21 12:08:10 +02:00
Alexander Brandes
14811169e3
[ci skip] Attach assets to GH releases (#1754)
* ci: Upload release assets

* chore: Update workflow name
2022-05-19 16:17:45 +02:00
Alexander Brandes
ace325a90e
build: Back to snapshot for development 2022-05-18 21:58:07 +02:00
Alexander Brandes
3a65c64977
chore: Use correct since annoation dates 2022-05-18 21:50:20 +02:00
Alexander Brandes
3c4695bb73
build: Release 2.2.0 2022-05-18 21:46:22 +02:00
renovate[bot]
0d2ed796d8
build: Update release-drafter/release-drafter action to v5.20.0 (#1748)
* build: Update release-drafter/release-drafter action to v5.20.0

* Update release-drafter.yml

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-05-18 17:21:27 +02:00
Jordan
84f975559c
[ci skip] Add jenkins to downloads list (#1750) 2022-05-18 17:20:41 +02:00
Pierre Maurice Schwang
39d77091d9
Don't error when loading a schematic fails (#1744)
fix: Throwable#getMessage may be null
2022-05-16 13:23:21 +01:00
Alexander Brandes
2c1ffd4ef4
Ignore .DS_Store files (#1746)
chore: Ignore ds store files
2022-05-15 12:30:39 +02:00
Jordan
deaf5ad2d6
Respect clipboard settings (disk vs memory) when loading a schematic (#1742) 2022-05-14 21:10:13 +01:00
Jordan
1c7643bb58
Allow use of BlockVectorSet for large //line selections instead of LocalBlockVectorSet (#1713) 2022-05-11 13:22:10 +01:00
dordsor21
059c5f046d
"Empty" side effects is default, and default does "apply" side effects 2022-05-10 17:28:09 +01:00
Jordan
b237ddf076
Cherry pick upstream commits to fix SideEffectSet (#1737)
* Fix SideEffectSet.none() being the default set (#1620)

* Fix SideEffectSet.none() being the default set

* Remove the unnecessary private empty constructor for SideEffectSet

* Back to ImmutableMap.of

* Speed up Fast Reorder Mode and make it default (#1653)

* Speed up Fast Reorder Mode and make it default

* Make non-exposed side effects internal

* Docs on isExposed

Co-authored-by: Matthew Miller <mnmiller1@me.com>
2022-05-10 10:11:12 +02:00
Jordan
d7543884a5
Check cached bukkit player is the same as the current player online (#1732)
* Check cached bukkit player is the same as the current player online
 - If plugins do silly things like teleport, deop (anything that requires a perm-recheck) (anything that ultimately requires a BukkitPlayer at some point) then the retention of metadata by the server (as it's stored based on a string value indescriminate of player a player relogging) means that a BukkitPlayer caching an old player object will be kept, cached and retrieved by FAWE. Adding a simple memory-based equality check when the player rejoins, and then "invaliding" (redoing) the cache if the players are not equal, fixes this.
 - Fixes #1730

* Address comments

* Add comment explaining reference equality check to code
2022-05-10 10:10:59 +02:00
renovate[bot]
ec97fca440
build: Update dependency org.mozilla:rhino-runtime to v1.7.14 (#1733)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-09 18:55:39 +02:00
renovate[bot]
ffeb940aff
build: Update plotsquared to v6.7.0 (#1739)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-09 16:20:59 +02:00
renovate[bot]
776dc3b69d
build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.12 (#1735)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-09 16:18:32 +02:00
Jordan
267dc153f0
Don't initialise a DiskOptimisedClipboard before checking for an existing one in the LocalSession when using loadClipboardFromDisk (#1731) 2022-05-09 12:50:19 +01:00
Alexander Brandes
b85888806a
[ci skip] chore: Update my name 2022-05-07 16:14:40 +02:00
Jordan
210ee9f2ef
Implement getNameUnsafe method to allow an unloaded world's name to be accessed (#1712)
* Implement getNameUnsafe method to allow an unloaded world's name to be accessed
 - Fixes #1671 and #504

* Add javadoc since tag

Co-authored-by: Alexander Brandes <mc.cache@web.de>

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-05-05 21:39:45 +02:00
renovate[bot]
c1b5f8c84a
[ci skip] build: Update org.antlr to v4.10.1 (#1699)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-05-03 10:06:46 +02:00
renovate[bot]
a51bc6eab3
build: Update dependency org.checkerframework:checker-qual to v3.22.0 (#1728) 2022-05-03 09:59:19 +02:00
renovate[bot]
091d64f723
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.11 (#1727)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-02 12:40:48 +02:00
renovate[bot]
546e42aab5
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.10 (#1723)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-30 14:14:29 +02:00
renovate[bot]
617b0ac95c
[ci skip] build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.6 (#1720)
* build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.6

* build: Update paperweight

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2022-04-25 17:17:23 +02:00
renovate[bot]
a227e2618f
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.9 (#1719)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-25 16:55:20 +02:00
renovate[bot]
3a22389d35
[ci skip] build: Update dependency org.mockito:mockito-core to v4.5.1 (#1721)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-25 16:23:27 +02:00
Jordan
e294245ec4
Fix some horrendous code where methods supposed to return a boolean only ever return true (#1718) 2022-04-24 18:03:40 +02:00
dordsor21
82ba96bf71
Add constraints to //asc and //desc 2022-04-24 00:11:57 +01:00
Octavia Togami
f2df511263
Bump paperdev 1.17.1 version (fixes yarn dependency resolution) 2022-04-23 14:39:26 +01:00
Alexander Brandes
3f970cdaef
Rename codeql.yml to codeql.yml.disabled 2022-04-21 13:11:39 +02:00
Jordan
65349392a6
Set empty block count when using fastmode on 1.17 (#1710)
* Set empty block count when using fastmode on 1.17
Fixes #1666

* Update legacy adapters
2022-04-21 13:11:23 +02:00
dordsor21
f5ef0cadb6
Clean up remaining byte casts from 39081e62c9 2022-04-20 23:47:09 +01:00
NotMyFault
c94cbf25a6
build: Back to snapshot for development 2022-04-19 09:14:45 +02:00
NotMyFault
9fdce09a4c
build: Release 2.1.2 2022-04-19 09:04:35 +02:00
Orlaando
3610af15e8
Show number of affected blocks in //set command (#1703)
* Show # of blocks affected in //set

* Fix typo

* fix: Add amount of blocks affected to strings.json

Co-authored-by: NotMyFault <mc.cache@web.de>
2022-04-19 08:55:19 +02:00
Alexander Brandes
27ee46047e
style: Emphasize project icon in idea selection (#1708) 2022-04-19 00:49:39 +02:00
renovate[bot]
ebf84c523c
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.8 (#1707)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-18 21:58:46 +02:00
Pierre Maurice Schwang
bb71a18c8c
fix: update adapters (FastAsyncWorldEdit-Adapters#67) (#1706) 2022-04-18 21:58:02 +02:00
renovate[bot]
4fd676b931
build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.7 (#1705)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-18 09:19:05 +02:00
Pierre Maurice Schwang
6e26741fdc
fix: respect block categories in RichMaskParser (#1694) 2022-04-11 13:59:54 +02:00
Hannes Greule
8f1ca48bfc
lock is in PalettedContainer in 1.17 (#1697) 2022-04-11 13:59:37 +02:00
renovate[bot]
a9e43a6d78
[ci skip] build: Update dependency com.github.TownyAdvanced:Towny to v0.98.1.6 (#1698)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-11 13:59:21 +02:00
Pierre Maurice Schwang
2483eacff5
Fix memory leak by Citizen NPCs (#1693)
* fix: ignore uuid v2 for BukkitPermissionAttachmentManager

Fixes a memory leak that attaches and caches PermissionAttachments to NPCs. Citiziens uses version 2 UUIDs, which are not used for regular player uuids. Those v2 uuids are now excluded.

* fix: create Permission when required

* fix: use citizens documented way to check for NPCs
2022-04-06 16:22:53 +02:00
renovate[bot]
ed9317b4d6
build: Update dependency org.checkerframework:checker-qual to v3.21.4 (#1689)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 19:38:43 +02:00
renovate[bot]
9d56275247
[ci skip] build: Update actions/setup-java action to v3.1.0 (#1690)
* build: Update actions/setup-java action to v3.1.0

* Update build.yml

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-04-04 15:17:09 +02:00
renovate[bot]
ffea228b52
build: Update dependency gradle to v7.4.2 (#1688)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 15:14:43 +02:00
renovate[bot]
569f3dc504
build: Update com.plotsquared to v6.6.2 (#1687)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 14:53:55 +02:00
NotMyFault
d26e15b6da
build: Back to snapshot for development 2022-04-04 13:53:15 +02:00
Alexander Brandes
90e77e5074
Update bug_report.yml 2022-04-04 13:20:08 +02:00
NotMyFault
93846fabaf
build: Release 2.1.1 2022-04-04 13:15:56 +02:00
Kekschen
f477120661
Remove unused 'listeningImages' variable. (#1684) 2022-04-02 22:00:57 +02:00
Hannes Greule
a240b002de
simplify biome id logic (#1677)
Co-authored-by: Alex <mc.cache@web.de>
2022-04-01 19:25:48 +02:00
NotMyFault
4970db0405
chore: Use assets for 1.18.2 2022-03-29 12:53:19 +02:00
Pierre Maurice Schwang
2276d82d2c
//regen creates vanilla decorations without error (#1650)
* fix: Feature placement on regen should create chunk

* feat: update adapter jar

* fix: update adapter jar
2022-03-28 21:06:26 +02:00
Hannes Greule
c45b14a52d
Avoid Unsafe on paper (#1678) 2022-03-27 23:56:59 +02:00
Pierre Maurice Schwang
d1588f9207
Fix tabcomplete for random pattern / multiple pattern (#1675)
* Merge RandomPatternParser#getSuggestions with upstream

* fix: don't throw AIIBE if patterns are empty

shouldn't be the case in the first place
2022-03-27 09:46:36 +02:00
Jordan
465c81d193
Remove hardcoding of heightmap compressed long size (#1668) 2022-03-18 21:28:25 +00:00
Alex
05f80f23b9
refactor!: Don't bundle 1.15.2 adapters anymore (#1656) 2022-03-17 09:41:50 +01:00
renovate[bot]
fbb25f289b
[ci skip] build: Update actions/checkout action to v3 (#1663)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 18:52:53 +01:00
NotMyFault
07bc33b52b
[ci skip] build: Ignore kyori updates until P2 supports 4.10 2022-03-14 16:20:31 +01:00
renovate[bot]
c672d7a0b3
build: Update dependency net.kyori:adventure-nbt to v4.9.3 (#1658)
* build: Update dependency net.kyori:adventure-nbt to v4.10.1

* build: Provide proper adventure version

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2022-03-14 16:14:10 +01:00
renovate[bot]
6435fd3bea
build: Update dependency gradle to v7.4.1 (#1657)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 14:32:52 +01:00
renovate[bot]
8afde807b6
build: Drop ProtocolLib dependency (#1659)
* build: Update dependency com.comphenix.protocol:ProtocolLib to v4.8.0

* build: Drop ProtocolLib dependency

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2022-03-14 14:32:27 +01:00
renovate[bot]
ebd7c136fd
build: Update dependency org.mockito:mockito-core to v4.4.0 (#1660)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 14:23:29 +01:00
Jordan
1708584e8d
Don't call ticking_list on Spigot (#1655)
* ticking_list is paper only

* Update adapters
2022-03-14 11:08:10 +01:00
NotMyFault
d400a470a1
Update upstream
5843aa5 Change vector command converter wording. (2059)
2022-03-13 19:19:59 +01:00
Jordan
5a97b23347
Don't error when adding processors to NullExtent, simply do nothing (#1654) 2022-03-13 18:35:27 +01:00
dordsor21
d8c0f8e3b1
Make sure thread-cached arrays are reset 2022-03-13 01:44:59 +00:00
NotMyFault
7ba185c4ac
build: Back to snapshot for development 2022-03-10 23:16:30 +01:00
NotMyFault
95512a4c0b
build: Release 2.1.0 2022-03-10 22:57:23 +01:00
NotMyFault
c3cdde9d2e
build: Update paperweight 2022-03-10 22:43:33 +01:00
Jordan
e9db749e2f
Add fluid ticking and refactor post-processing a bit (#1554)
* Make postProcessSet a default method and change to void

* Throwable#getMessage is nullable

* Move (re-)ticking to a post-processor per "platform"
 - Add fluid ticking

* chore: Ignore (for us) irrelevant rules

* chore: Fix correct toml syntax?

* Re-add removed method for API-compliance and refactor it to have a use

* Switch to javax annotations

* Switch to recalcBlockCounts for ticking blocks.

* No need to set air count anymore either

* We can still "not tick" in fast mode in 1.17.2

* update adapters

* Let paper create the chunk section if biomes are null

* Adjust notes to settings

* 1.17.2 didn't exist

* Add 1.18.2

* Don't attempt to cache plains biome ID

* Use correct annotation

Co-authored-by: NotMyFault <mc.cache@web.de>
2022-03-10 15:27:25 +01:00
Alex
5d18e15128
Replace JB occurrences with JSR 305 (for now) (#1651)
* refactor: Replace JB occurrences with JSR 305 (for now)

* chore: Update adapter jar
2022-03-10 14:24:44 +01:00
Jordan
f59353006a
Update to P2 extended heights (#1581) 2022-03-09 14:21:58 +01:00
NotMyFault
3ee9797408
build: Misc dependency updates 2022-03-08 20:51:17 +01:00
Pierre Maurice Schwang
49bc675f51
Fix //regen -b on 1.18.2 (#1647)
* fix: adapt correct biome type

* fix: PaperweightPlatformAdapter#adapt should return BiomeType
2022-03-08 18:55:52 +01:00
NotMyFault
fb66ba6adf
build: Update paperweight
Closes #1649
2022-03-07 21:20:25 +01:00
renovate[bot]
5e4143c1dc
[ci skip] build: Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.7 (#1648)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-07 21:18:21 +01:00
Alex
345785a25e
feat: Support for 1.18.2 (#1641)
* feat: Preliminary work for 1.18.2

* Update SpigotNames to 1.18.2 (#1642)

* 1.18.2 / Biome-Holders, regeneration (#1645)

* 1.18.2 / Biome-Holders, regeneration

* fix: reuse old structure sets

* build: Update dev bundles

* fix: Don't log regen world generation

* fix: Run DataConverter with CBT

* fix: Override `#toNativeBinary`

* fix: Exception on regen

Co-Authored-By: Pierre Maurice Schwang <mail@pschwang.eu>

* refactor: Minor cleanup

Co-authored-by: Aurora <21148213+aurorasmiles@users.noreply.github.com>
Co-authored-by: Pierre Maurice Schwang <mail@pschwang.eu>
2022-03-07 15:20:05 +01:00
Pierre Maurice Schwang
668227ee6c
Update Upstream (#1643)
44863cf Don't access PluginClassLoader directly (#2045)
2022-03-05 18:19:58 +01:00
Alex
44078d1820
[ci skip] Update issue templates for 1.18.2 2022-03-04 13:25:42 +01:00
renovate[bot]
4ffea67514
build: Update dependency net.kyori:adventure-nbt to v4.10.0 (#1638)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-04 00:22:01 +01:00
NotMyFault
dafcd16a14
Update Upstream
eac5b51 Play dirty because bukkit classloading is bad. (2043)
2022-03-02 20:48:49 +01:00
NotMyFault
a23785632a
build: Address Gradle 7.4 deprecations 2022-02-28 15:44:05 +01:00
NotMyFault
7db06061f0
Update upstream
e2ab12c Change the class source validator to use classloaders for detection. (2039)
2022-02-28 15:42:03 +01:00
Alex
340f8dded3
tests: Remove stub server (#1629) 2022-02-28 13:53:08 +01:00
renovate[bot]
c5d70f0da1
build: Update dependency com.github.TechFortress:GriefPrevention to v16.18 (#1635)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-28 12:43:25 +01:00
renovate[bot]
be83c6ec70
build: Update com.plotsquared to v6.5.1 (#1633)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-28 10:56:22 +01:00
Jordan
dec0373081
Fix 1.17 snapshot restoration (#1632) 2022-02-27 21:20:16 +00:00
Alex
081d8ddb50
ci: Bump actions/setup-java to 3.0.0 (#1631) 2022-02-25 22:53:39 +01:00
Jordan
b8ab2a5204
Don't allow heightmap-based brushes to edit the entire world "depth" (#1617)
Fixes #1614

Co-authored-by: Alex <mc.cache@web.de>
2022-02-24 10:33:37 +01:00
Jordan
fc2662e51e
Fix //snapshot in 1.18 and re-implement biome/entity restoration (#1620)
* Re-add "//snap" and "//snapshot"

* Place code in correct method

* Use CompoundBinaryTags in AnvilChunk18 and implement biome/entity restoration

* Address comments

* Fix biome reading

* Fix retrieval of entities from zipped snapshot world

Co-authored-by: Alex <mc.cache@web.de>
2022-02-24 10:33:25 +01:00
Jordan
49d5183685
Load legacy config file before firing PlatformsRegisteredEvent (#1623)
Fixes #1622

Co-authored-by: Alex <mc.cache@web.de>
2022-02-24 10:33:06 +01:00
Jordan
28a0239437
Fix clipboards to allow proper heights by allowing extended CuboidRegion heights (#1624)
* Fix clipboards to allow proper heights by allowing extended CuboidRegion heights
Fixes #1534

* Add @since

* Fix javadoc comment

Co-authored-by: Alex <mc.cache@web.de>
2022-02-24 10:32:45 +01:00
NotMyFault
0a04b0b4cd
tests: Fix StubServer 2022-02-23 11:25:10 +01:00
NotMyFault
77b41e052a
Revert "build: Update dependency org.ajoberstar.grgit:grgit-gradle to v5 (#1611)"
This reverts commit cf0a21d

Apparently that doesn't integrate that seamless in all environments.
2022-02-23 11:15:01 +01:00
Alex
23b5f0cb4a
[ci skip] GitHub does now allow you to rebase PRs straight away 2022-02-21 00:52:22 +01:00
NotMyFault
f8e6feb1f2
Update upstream
17b9f00 Move tinyurls to ehub.to (2033)
76ec878 Allow biome commands to be used from non-player actors (2034)
2022-02-20 14:18:58 +01:00
Jordan
39081e62c9
byte cannot be used to represent height anymore (#1618)
Fixes #1593
2022-02-17 19:34:25 +01:00
Jordan
f7a0c14a1b
Correctly use getNearestSurfaceTerrainBlock in SurfaceSpline and SchemGen (#1616)
Fixes #1609
2022-02-17 19:34:07 +01:00
dordsor21
3f28a5759d
Make slope method slightly more readable in AngleMask 2022-02-16 18:18:58 +00:00
dordsor21
a40d1ccf51
Better naming for min position in HeightMap 2022-02-16 18:13:04 +00:00
dordsor21
fbe0c08c26
FAWE HeightMap constructor shouldn't be deprecated 2022-02-16 18:02:20 +00:00
dordsor21
05bd84b504
Don't crazily initialise HeightMapFilter...?? 2022-02-16 17:47:43 +00:00
dordsor21
3e85369765
Make angle pattern slope a little more readable 2022-02-16 17:42:22 +00:00
renovate[bot]
cf0a21d312
build: Update dependency org.ajoberstar.grgit:grgit-gradle to v5 (#1611)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-14 13:12:46 +01:00
renovate[bot]
b1a93766d3
build: Update com.plotsquared to v6.5.0 (#1610)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-14 12:00:32 +01:00
Pierre Maurice Schwang
f657a80dc6
fix: set size of MappedByteBuffer accordingly (#1608) 2022-02-13 13:57:19 +01:00
dordsor21
de4f73997e
Implement missing methods in tests 2022-02-12 13:38:04 +00:00
Pierre Maurice Schwang
646a683f22
fix: add coordinates to tile-entity nbt component (#1607) 2022-02-12 13:38:37 +01:00
NotMyFault
7da993d3f1
build: Update gradle 2022-02-09 23:35:13 +01:00
renovate[bot]
7e17a5cbd1
[ci skip] build: Update release-drafter/release-drafter action to v5.18.1 (#1603)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-07 10:34:27 +01:00
renovate[bot]
cf1e61c153
build: Update dependency org.checkerframework:checker-qual to v3.21.2 (#1602)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-07 10:34:13 +01:00
NotMyFault
15b9b8332c
fix: Make it build again 2022-02-04 11:24:11 +01:00
NotMyFault
d80bfc7495
docs: Update wiki link 2022-02-04 11:16:23 +01:00
NotMyFault
2bb72ebfea
[ci skip] ci: Don't run actions twice 2022-01-31 21:13:44 +01:00
renovate[bot]
faa2477305
build: Update org.bstats to v3 (#1589)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-31 13:00:09 +01:00
renovate[bot]
186386ce4a
build: Update dependency org.mockito:mockito-core to v4.3.1 (#1587)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-31 10:29:09 +01:00
renovate[bot]
d3f8a3beb3
build: Update dependency io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin to v1.3.4 (#1586)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-31 10:28:05 +01:00
NotMyFault
f0136460ba
Update upstream
ab31481 Use Chunk#getNoiseBiome instead of biome container (2025)
2022-01-30 21:18:40 +01:00
NotMyFault
38b0dcf7e4
Update upstream
e485433 Fix legacy error message output for WorldGuard commands (2023)
2022-01-30 19:54:50 +01:00
Jordan
178604bbb7
Only call org.bukkit.World height methods if they're present (1.17+) (#1551)
* Only call org.bukkit.World height methods if they're present (1.17+)

* Switch to WorldEdit get height methods in GPFeature
2022-01-29 13:12:16 +01:00
Alex
4610688fcb
fix: Debugpaste on 1.17 and lower due GSON incompatibility (#1583) 2022-01-28 22:15:24 +01:00
NotMyFault
15076f3d93
[ci skip] docs: Update documentation for Java 17 2022-01-27 21:04:22 +01:00
NotMyFault
272920fb25
build: Back to snapshot for development 2022-01-27 16:06:40 +01:00
NotMyFault
a0b61512fb
build: Release 2.0.1 2022-01-27 15:52:23 +01:00
NotMyFault
e309cf8f3c
build: Update PlotSquared 2022-01-27 15:30:18 +01:00
renovate[bot]
0f524e665b
[ci skip] build: Update dependency org.mockito:mockito-core to v4.3.0 (#1563)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-24 16:14:07 +01:00
Alex
e8f72d6521
fix: Deduplicate error messages (#1557)
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1535
2022-01-24 12:52:33 +01:00
renovate[bot]
c461674402
build: Update release-drafter/release-drafter action to v5.17.6 (#1562)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-24 11:05:47 +01:00
ahdg
806ca62485
fix: GriefDefender filter (#1546)
* Fix: GriefDefender filter

* Update libs.versions.toml

* Now it only work with 2.1.0.
2022-01-23 18:29:01 +01:00
Alex
016b4ba81d
fix: Unify superpickaxe behavior (#1553)
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1547
2022-01-21 14:41:24 +01:00
NotMyFault
d17e3a6555
chore: Add missing Fawe annotations to //regen command 2022-01-19 13:58:52 +01:00
NotMyFault
4d2a34fd21
refactor: Update upstream
0ad3ab1 Remove extra label from bukkit command usage string.
2022-01-17 13:20:16 +01:00
renovate[bot]
96805b85b5
build: Update release-drafter/release-drafter action to v5.17.5 (#1549)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-17 11:02:21 +01:00
dordsor21
d3696f91d4
Synchronise access to the PriorityQueue used for effect queuing in AbstractWorld
- Makes it thread-safe
2022-01-15 17:09:49 +00:00
NotMyFault
0ccae19ded
refactor: Update javaodc url 2022-01-14 15:34:04 +01:00
NotMyFault
f077ec9163
build: Back to snapshot for development 2022-01-14 14:54:37 +01:00
NotMyFault
2c4453b68f
build: Release 2.0.0 2022-01-14 13:53:59 +01:00
Jordan
6a972e7b99
Heightmaps used for brushes etc. should be normalised to zero. (#1522)
* Heightmaps used for brushes etc. should be normalised to zero.
Fixes #1508

* chars are unsigned

* Add scale paramer to javadoc
2022-01-14 10:49:23 +01:00
Alex
9e40b972b1
refactor: Put Fawe version information at debugpaste to (#1533) 2022-01-12 01:22:24 +01:00
Alex
6b857b0f58
ci: Cleanup maven repositories (#1526) 2022-01-12 01:21:27 +01:00
renovate[bot]
5fc0de0b82
build: Update actions/setup-java action to v2.5.0 (#1530)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-10 11:30:26 +01:00
renovate[bot]
4e2a1c393d
build: Update dependency org.checkerframework:checker-qual to v3.21.1 (#1528)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-10 11:27:07 +01:00
NotMyFault
f0f201002a
Update adapters 2022-01-09 11:22:00 +01:00
Alex
9ba90d8c83
refactor: Drop custom snakeyaml implementation (#1523)
* refactor: Drop custom snakeyaml implementation

* Merge branch 'main' into chore/main/remove-snakeyaml-wannabe-abstraction
2022-01-09 10:55:16 +01:00
dordsor21
c2f3c13a09
Fix #1510 2022-01-08 18:10:14 +00:00
dordsor21
4754f660c7
Fix #1524
Also brings in line with upstream
2022-01-08 17:46:28 +00:00
Alex
64442a8051
refactor: Tackle a few Semgrep and ErrorProne violations (#1520)
* refactor: Tackle a few Semgrep and ErrorProne violations

* Address comments
2022-01-07 12:45:53 +01:00
Alex
f27959e49a
[ci skip] Don't run build twice 2022-01-07 10:42:57 +01:00
dordsor21
59d4247ddb
Update legacy adapters 2022-01-05 23:53:02 +00:00
dordsor21
867d4c05cb
Merge branch 'main' of github.com:IntellectualSites/FastAsyncWorldEdit into main 2022-01-05 23:43:31 +00:00
dordsor21
d6695d23f0
Replace remaining instances of worldeditregentempworld 2022-01-05 23:42:57 +00:00
Alex
fe1a77a593
ci: Let release drafter listen to forks too 2022-01-05 23:49:36 +01:00
dordsor21
722c411219
Add workaround for when expressions are parsed in masks/patterns where '&&' is used
Fixes #1517
2022-01-05 17:46:18 +00:00
renovate[bot]
0408cd0575
build: Update dependency gradle.plugin.com.github.johnrengelman:shadow to v7.1.2 (#1513)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-05 17:11:06 +01:00
renovate[bot]
318b1ef690
Merge pull request #1512 from IntellectualSites/renovate/com.plotsquared
build: Update com.plotsquared to v6.2.2
2022-01-05 17:10:55 +01:00
NotMyFault
3a78abe273
ci: Change GH action branch 2022-01-05 17:00:42 +01:00
Alex
8b973da7ee
feat!: Update for 1.18 (#1482)
* ci: Switch deployment to gh actions and use semver & java 17

* build: Update core dependencies

- Drop paranamer, you can access parameter names at runtime with Java 8+ natively

* ci: Snapshot builds are the default

* ci: Cleanup and finish transition

* ci: Trigger initial sync with the OSSRH

* revert: OSSRH snapshot deployment was successful, returning to baseline

This reverts commit 3a189f65f2.

* ci: Register javadoc jar for lib artifacts

* ci: Sign artifacts

* build: Set kotlin jvm toolchain

* style: Use minimized `version` output

* feat: Setup project structure for 1.18

* Exclude 1.17

* Port initial paperweight classes to 1.18 folder structure

* Move to Paper 1.18

* Update templates, address JEP deprecations and place a few TODOs

* Drop Guava 21 enforcement

* Make 1.18 to be effectively in a usable state (#1452)

* Update swathes of easy-to-update-sort-of-code.
 - Untested
 - Should compile but NMF broken something
 - Several todos:
  - biome history//better support (move to biome sections in core)
  - regen (haha lol no thanks, someone else can do that)
  - probably actually do the palette stuff that probably won't work in PaperweightPlatformAdapter

* ci: Provide basic Jenkinsfile for ghprb pipeline

* build: Update paperweight

* upstream: Update Upstream

de6fa17 Add getBrush helper for use with instanceof pattern matching (1926)

* FAWE will now load on startup

* it....works?

* Begin to allow biome edits (and fix biomes reverting to plains upon editing blocks)

* Add new blocks/block properties

* Only create biome palette if supplies is null

* Fix biome operations

* Finally get removing BlockID done (major version change allows it)

* refactor!: Drop PlotSquared v4

Fawe 2.0.0 and newer requires Java 17, PlotSquared v4 supports 1.13 and 1.14, Fawe wont work on these versions nevertheless and refuses to load due Java version incompatiblities with older versions. Newer versions can use PlotSquared v6.

* docs: Update readme

* Added and removed some comments

* Added and removed some comments

* refactor: Rename worldedit configuration

* build: Re-add 1.17 module

This the a very nasty commit

* chore: Implement missing methods

* build: Update paperweight

* upstream: Update upstream

6df194e Remove finalize, use a Cleaner instead (1943)
9843a4f Fix snapshots in 1.18 (1959)

* ci: Escape workflows

* build: Update paperweight to 1.18.1

* build: Update Paster

* Fix compilation

* Bump to 1.18.1

* Do both 1.18 and 1.18.1

Co-authored-by: Alex <mc.cache@web.de>

* Fix single-block lookups

* Reserve ordinals 0 through 3 for air/"reserved"

* Create block palette data with values

* Fix classpath for testing for starlight

* Correctly use block rather than sky light layer [not used in paper]

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>

* Update version (checking) for semver

* build: Fix release drafter base branch

* Trigger GHPRB

* tests: Add resource pack methods

* build: Update paperweight and add 1.17 again

* chore: Lazily change build delimiter

* build: Deploy API snapshots for 2.0.0

* Update adapters jar

* More verbosely get block data and ensure biome layer isn't null

* refactor: Address a few `TODO 1.18`'s

(cherry picked from commit 0b77932b6e46c825d78b8c7ccae2a68ad890564e)

* fix: Fix `/fawe debugpaste`

* refactor! Remove deprecations marked for removal that are not present in upstream (#1483)

* Reverse a "debug" change to BukkitImplLoader

* Fix parsing of build in FaweVersion

* refactor: Do prepared statements properly

- Update TextureUtil client jar to 1.18.1
- Limit the update checker to our domain

* Add classes with the correct minor version to the start of the adapter candidates list

* refactor: Deprecate `IMP` initializors in favor of builders

* Fix WEManager (#1487)

* Fix WeManager?

* Fix WeManager?

* Also register WEManager if not available, like TaskManager.

* refactor: Also deprecated `IMP` for DBHandler

* feat: Add a bunch of new types to the flora generator

* use spigot-compatible palette constructor

* use spigot-compatible packet constructor

* implement 1.18 regen

* return air instead of reserved on get blocks

* refactor: Shift `FileAlreadyExistsException` catch to a higher level

* read the actual block from ZeroBitStorage

* Add get default version min/max world height to platform
 - Fixes #1500

* Add methods to CLIPlatform

* Fix #1490

* Fix tests

* Don't force tick limiter enable/disable

* Use Math.floor instead of int cast 757bef1f7d2b16317ab3d18427ad22183344e28d

* More precise method names in MinecraftVersion
 - Also ensure correct comparisons are made in FaweBukkit and BukkitServerInterface
 - Fixes #1504

* Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved" (#1502)

* Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved"
Also:
 - Ensure that reserved is never returned in GET block operations
 - "empty" thus doesn't exist in the GET update methods; remove the needless checks
 - Allow GET/SET chunks to determine their own default values for non-present blocks/sections

* Add comments

* Remove mentions of NMS from compilation instruction

* Update log4j version, update jd links to use "latest"

* Move to BinaryTags where appropriate in adapters

* Add comments to changed code

* Rename worldedit to fawe where appropriate

* Use new language features

* chore: Format our loggers properly

* Remove unneeded comments

* Replace CachedChange class with record

* Remove/add some more comments

* Remove remaining keywords frm CachedChanged. IJ doesn't warn?

* Compress switch statements a bit using enhanced

* More enhanced switches

* Refactor: getVersionMin/MaxY -> versionMin/MaxY

* Throw, catch, and rethrow our own exception to make sure we're finding the culprit to a possible shaded-FAWE.

* Don't wrap Exception thrown upon invalid schematic path inside a RuntimeException
Fixes #1506

* docs: Put `since` annotation on newly introduced API

* docs: Drop clarified todos

* Warn user if using small-edit history setting with extended world heights

* Refactor: add javadoc to Clipboard#create and improve variables when delegating to another paste method

* Fix issue with offset/origin when pasting a clipboard via API without wrapping into a BlockArrayClipboard

* build: Remove drop our maven repository

* docs: Fix deprecation tag

* Fix incorrect toNative method in 1.17 adapter

* refactor: Deprecate tick limiter API for public use

* ci: dordsor does love rebasing here too

* docs: Document annotations

* Update upstream

fb5ec19 Fix error for snapshot restore missing chunk

* docs: Document a few undocumented annotations

* feat: Add worldedit.schematic.list.other permission and functionality (#1507)

* Add worldedit.schematic.list.other permission and functionality

* Implement StringMan#containsUuid

* Javadocs

* chore: Add since annotation

Co-authored-by: NotMyFault <mc.cache@web.de>

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
Co-authored-by: Aurélien <43724816+Aurelien30000@users.noreply.github.com>
Co-authored-by: SirYwell <hannesgreule@outlook.de>
Co-authored-by: JOO200 <github@joo200.de>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
2022-01-05 16:58:30 +01:00
Owen1212055
c27a34ce40
feat: Add worldedit.schematic.list.other permission and functionality (#1507)
* Add worldedit.schematic.list.other permission and functionality

* Implement StringMan#containsUuid

* Javadocs

* chore: Add since annotation

Co-authored-by: NotMyFault <mc.cache@web.de>
2022-01-05 16:21:44 +01:00
NotMyFault
f4658cc668
docs: Document a few undocumented annotations 2022-01-04 21:15:45 +01:00
NotMyFault
ef686af8dd
Update upstream
fb5ec19 Fix error for snapshot restore missing chunk
2022-01-04 21:01:49 +01:00
NotMyFault
631fd3c7f5
docs: Document annotations 2022-01-04 20:57:23 +01:00
NotMyFault
30c2597aad
ci: dordsor does love rebasing here too 2022-01-04 20:33:43 +01:00
NotMyFault
b8399abfe1
refactor: Deprecate tick limiter API for public use 2022-01-04 20:33:05 +01:00
dordsor21
42dacfc7ef
Fix incorrect toNative method in 1.17 adapter 2022-01-04 13:28:29 +00:00
NotMyFault
7e96853b89
docs: Fix deprecation tag 2022-01-01 18:46:28 +01:00
NotMyFault
42d6466a4c
build: Remove drop our maven repository 2021-12-31 17:26:15 +01:00
dordsor21
0994ea1e67
Fix issue with offset/origin when pasting a clipboard via API without wrapping into a BlockArrayClipboard 2021-12-30 16:05:16 +00:00
dordsor21
f30ea96268
Refactor: add javadoc to Clipboard#create and improve variables when delegating to another paste method 2021-12-30 16:04:38 +00:00
dordsor21
9faacb38ef
Warn user if using small-edit history setting with extended world heights 2021-12-30 16:01:23 +00:00
NotMyFault
aaad86cf1d
docs: Drop clarified todos 2021-12-29 18:16:19 +01:00
NotMyFault
122cba677a
docs: Put since annotation on newly introduced API 2021-12-29 18:14:18 +01:00
dordsor21
235d0360da
Don't wrap Exception thrown upon invalid schematic path inside a RuntimeException
Fixes #1506
2021-12-29 16:55:32 +00:00
dordsor21
52fa44516e
Throw, catch, and rethrow our own exception to make sure we're finding the culprit to a possible shaded-FAWE. 2021-12-29 16:47:34 +00:00
dordsor21
9e8f0e7325
Refactor: getVersionMin/MaxY -> versionMin/MaxY 2021-12-29 16:44:41 +00:00
dordsor21
f505828af1
More enhanced switches 2021-12-29 16:44:18 +00:00
dordsor21
8d565b93f7
Compress switch statements a bit using enhanced 2021-12-29 16:39:44 +00:00
dordsor21
867b28d439
Remove remaining keywords frm CachedChanged. IJ doesn't warn? 2021-12-29 16:37:21 +00:00
dordsor21
fd3619f7b5
Merge branch 'major/2.0.0/1.18' of github.com:IntellectualSites/FastAsyncWorldEdit into major/2.0.0/1.18 2021-12-29 16:30:12 +00:00
dordsor21
3a3143065d
Remove/add some more comments 2021-12-29 16:29:55 +00:00
dordsor21
ca5640e89e
Replace CachedChange class with record 2021-12-29 16:16:23 +00:00
dordsor21
e5cbdec67e
Remove unneeded comments 2021-12-29 16:14:13 +00:00
NotMyFault
19de815ab4
chore: Format our loggers properly 2021-12-29 17:13:20 +01:00
dordsor21
e2a1721a5c
Use new language features 2021-12-29 16:12:43 +00:00
dordsor21
0d79d084a5
Rename worldedit to fawe where appropriate 2021-12-29 16:12:16 +00:00
dordsor21
3c2394afa4
Add comments to changed code 2021-12-29 16:06:49 +00:00
dordsor21
f38859237a
Move to BinaryTags where appropriate in adapters 2021-12-29 16:00:49 +00:00
dordsor21
48e2953910
Update log4j version, update jd links to use "latest" 2021-12-29 15:30:25 +00:00
dordsor21
1a281badc2
Remove mentions of NMS from compilation instruction 2021-12-29 15:30:12 +00:00
Jordan
177d731957
Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved" (#1502)
* Add back statically-set reserved IDs for air blocks only, make it clear they're "reserved"
Also:
 - Ensure that reserved is never returned in GET block operations
 - "empty" thus doesn't exist in the GET update methods; remove the needless checks
 - Allow GET/SET chunks to determine their own default values for non-present blocks/sections

* Add comments
2021-12-29 16:17:20 +01:00
dordsor21
bca3a1b04d
More precise method names in MinecraftVersion
- Also ensure correct comparisons are made in FaweBukkit and BukkitServerInterface
 - Fixes #1504
2021-12-29 14:46:30 +00:00
JOO200
5d4a2a4a0d
Use Math.floor instead of int cast 757bef1f7d2b16317ab3d18427ad22183344e28d 2021-12-29 12:42:19 +00:00
dordsor21
c28a5ee66e
Merge branch 'main' into major/2.0.0/1.18 2021-12-29 00:19:25 +00:00
dordsor21
d19369401f
Don't force tick limiter enable/disable 2021-12-29 00:18:12 +00:00
dordsor21
3ec1912046
Fix tests 2021-12-28 23:22:59 +00:00
dordsor21
36857a5064
Fix #1490 2021-12-28 23:02:48 +00:00
dordsor21
f6319d36a1
Add methods to CLIPlatform 2021-12-28 22:58:25 +00:00
dordsor21
f236934a39
Add get default version min/max world height to platform
- Fixes #1500
2021-12-28 22:46:19 +00:00
dordsor21
46fdceaea6
add missing annotation to Region 2021-12-28 22:05:40 +00:00
SirYwell
f9ecb449cf read the actual block from ZeroBitStorage 2021-12-27 06:03:01 +01:00
NotMyFault
596356a936
refactor: Shift FileAlreadyExistsException catch to a higher level 2021-12-27 00:00:49 +01:00
SirYwell
07695786ca return air instead of reserved on get blocks 2021-12-26 19:52:02 +01:00
NotMyFault
040a011ff1
Merge branch 'main' into major/2.0.0/1.18 2021-12-26 16:24:36 +01:00
SirYwell
a717df3c5f implement 1.18 regen 2021-12-26 16:20:39 +01:00
SirYwell
4ab140f6a1 use spigot-compatible packet constructor 2021-12-26 10:37:32 +01:00
SirYwell
018042769d use spigot-compatible palette constructor 2021-12-26 09:31:03 +01:00
NotMyFault
0c8db1e1fe
feat: Add a bunch of new types to the flora generator 2021-12-25 19:03:30 +01:00
NotMyFault
42035bdb87
chore: Lazily prepare update checker for future job
Future versions of Fawe use a version agnostic job. This commit will remain unmerged to any other branch but warrant a working update checker.
2021-12-25 17:24:26 +01:00
NotMyFault
3b24a8ae8a
Merge branch 'main' into major/2.0.0/1.18 2021-12-25 17:20:52 +01:00
Hannes Greule
96ca83704a
fix: Backport fixing delay closing of clipboards on quit (#1493) 2021-12-25 17:18:39 +01:00
NotMyFault
28079e8129
refactor: Also deprecated IMP for DBHandler 2021-12-23 15:59:05 +01:00
Aurélien
ca5ad58f01
Fix WEManager (#1487)
* Fix WeManager?

* Fix WeManager?

* Also register WEManager if not available, like TaskManager.
2021-12-23 12:39:11 +01:00
NotMyFault
7da921e075
refactor: Deprecate IMP initializors in favor of builders 2021-12-22 20:58:23 +01:00
dordsor21
34f971c729
Add classes with the correct minor version to the start of the adapter candidates list 2021-12-22 12:19:20 +00:00
NotMyFault
1715f35341
refactor: Do prepared statements properly
- Update TextureUtil client jar to 1.18.1
- Limit the update checker to our domain
2021-12-22 13:10:04 +01:00
dordsor21
77802758a9
Fix parsing of build in FaweVersion 2021-12-22 11:44:37 +00:00
dordsor21
d98f626ba6
Reverse a "debug" change to BukkitImplLoader 2021-12-22 11:37:01 +00:00
Jordan
6b6c94556a
refactor! Remove deprecations marked for removal that are not present in upstream (#1483) 2021-12-22 01:53:45 +01:00
NotMyFault
a4cec49e89
fix: Fix /fawe debugpaste 2021-12-22 00:53:27 +01:00
NotMyFault
94b392dd39
refactor: Address a few TODO 1.18's
(cherry picked from commit 0b77932b6e46c825d78b8c7ccae2a68ad890564e)
2021-12-21 18:02:20 +00:00
dordsor21
28f3bc61ea
More verbosely get block data and ensure biome layer isn't null 2021-12-21 18:00:09 +00:00
dordsor21
9ec829eddf
Update adapters jar 2021-12-21 17:59:55 +00:00
NotMyFault
aff3d8ba49
build: Deploy API snapshots for 2.0.0 2021-12-21 17:48:56 +01:00
NotMyFault
c9dc1ed655
Merge branch 'main' into major/2.0.0/1.18 2021-12-21 17:31:46 +01:00
Alex
8ab1d50f01
docs: Issue templates are provided by the default branch 2021-12-21 17:22:00 +01:00
NotMyFault
7453f12e66
chore: Lazily change build delimiter 2021-12-21 16:27:46 +01:00
NotMyFault
78aff4c81f
build: Update paperweight and add 1.17 again 2021-12-21 11:11:08 +01:00
NotMyFault
d6110013b8
tests: Add resource pack methods 2021-12-21 00:42:46 +01:00
NotMyFault
01ce0f94af
Trigger GHPRB 2021-12-21 00:30:36 +01:00
NotMyFault
6350fe5411
build: Fix release drafter base branch 2021-12-20 22:20:41 +01:00
dordsor21
e9d97fc7b1
Update version (checking) for semver 2021-12-20 21:18:26 +00:00
Jordan
d6e3c331d4
Make 1.18 to be effectively in a usable state (#1452)
* Update swathes of easy-to-update-sort-of-code.
 - Untested
 - Should compile but NMF broken something
 - Several todos:
  - biome history//better support (move to biome sections in core)
  - regen (haha lol no thanks, someone else can do that)
  - probably actually do the palette stuff that probably won't work in PaperweightPlatformAdapter

* ci: Provide basic Jenkinsfile for ghprb pipeline

* build: Update paperweight

* upstream: Update Upstream

de6fa17 Add getBrush helper for use with instanceof pattern matching (1926)

* FAWE will now load on startup

* it....works?

* Begin to allow biome edits (and fix biomes reverting to plains upon editing blocks)

* Add new blocks/block properties

* Only create biome palette if supplies is null

* Fix biome operations

* Finally get removing BlockID done (major version change allows it)

* refactor!: Drop PlotSquared v4

Fawe 2.0.0 and newer requires Java 17, PlotSquared v4 supports 1.13 and 1.14, Fawe wont work on these versions nevertheless and refuses to load due Java version incompatiblities with older versions. Newer versions can use PlotSquared v6.

* docs: Update readme

* Added and removed some comments

* Added and removed some comments

* refactor: Rename worldedit configuration

* build: Re-add 1.17 module

This the a very nasty commit

* chore: Implement missing methods

* build: Update paperweight

* upstream: Update upstream

6df194e Remove finalize, use a Cleaner instead (1943)
9843a4f Fix snapshots in 1.18 (1959)

* ci: Escape workflows

* build: Update paperweight to 1.18.1

* build: Update Paster

* Fix compilation

* Bump to 1.18.1

* Do both 1.18 and 1.18.1

Co-authored-by: Alex <mc.cache@web.de>

* Fix single-block lookups

* Reserve ordinals 0 through 3 for air/"reserved"

* Create block palette data with values

* Fix classpath for testing for starlight

* Correctly use block rather than sky light layer [not used in paper]

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
2021-12-20 21:12:04 +00:00
dordsor21
c697eb8d41
Merge branch 'main' into major/2.0.0/1.18 2021-12-20 20:28:15 +00:00
renovate[bot]
37cc817cbe
build: Update dependency org.checkerframework:checker-qual to v3.21.0 (#1478)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 17:10:06 +01:00
renovate[bot]
c04cc7bec5
build: Update org.apache.logging.log4j to v2.17.0 (#1480)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 17:09:57 +01:00
renovate[bot]
0e0883cfb8
build: Update dependency org.mockito:mockito-core to v4.2.0 (#1479)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 17:06:53 +01:00
renovate[bot]
fc56304af2
build: Update com.google.auto.value to v1.9 (#1475)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 12:23:15 +01:00
renovate[bot]
99da51270a
build: Update dependency gradle.plugin.com.github.johnrengelman:shadow to v7.1.1 (#1474)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 12:23:07 +01:00
renovate[bot]
511036be23
build: Update dependency gradle to v7.3.2 (#1473)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-20 11:59:39 +01:00
whitesource-bolt-for-github[bot]
4a6e2a87aa
Configure WhiteSource Bolt for GitHub (#1468)
* Add .whitesource configuration file

* chore: Update bolt

Co-authored-by: whitesource-bolt-for-github[bot] <42819689+whitesource-bolt-for-github[bot]@users.noreply.github.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2021-12-18 13:30:02 +01:00
NotMyFault
a87323616d
Merge remote-tracking branch 'origin/renovate/org.checkerframework' 2021-12-13 20:18:34 +01:00
Renovate Bot
a7b45e7f54
build: Update org.apache.logging.log4j to v2.15.0 2021-12-13 19:01:34 +00:00
Renovate Bot
a360026490
build: Update dependency org.checkerframework:checker-qual to v3.20.0 2021-12-13 17:25:07 +00:00
renovate[bot]
1f0f079193
build: Update com.plotsquared to v6.2.0 (#1462)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-13 14:22:29 +01:00
Alex
9fdff97e29
build: Update paperweight (#1454) 2021-12-10 16:20:15 +01:00
Hannes Greule
5367921496
fix: Use WE PaperweightAdapter for seed replacement (#1440)
* Use WE PaperweightAdapter for seed replacement
also, only replace when necessary

* fix comments

* ci: Provide basic Jenkinsfile for ghprb pipeline (#1451)

Co-authored-by: Alex <mc.cache@web.de>
2021-12-07 12:59:58 +01:00
Owen1212055
781bfc542f
fix: Properly delete ChangeSets on history clear (#1413)
Fixes #1347

Co-authored-by: Jordan <dordsor21@gmail.com>
Co-authored-by: Alex <mc.cache@web.de>
2021-12-06 14:31:46 +01:00
renovate[bot]
e0e3688361
build: Update dependency org.ajoberstar.grgit:grgit-gradle to v4.1.1 (#1447)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-06 10:22:44 +01:00
renovate[bot]
ec690f888b
build: Update plugin pluginyml to v0.5.1 (#1448)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-06 10:22:37 +01:00
renovate[bot]
0fe847c69a
build: Update dependency com.github.TownyAdvanced:Towny to v0.97.5.0 (#1445)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-06 10:11:08 +01:00
renovate[bot]
e371bb16e1
build: Update dependency gradle to v7.3.1 (#1446)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-06 10:08:52 +01:00
NotMyFault
6afde13a01
Drop Guava 21 enforcement 2021-11-30 22:13:13 +01:00
NotMyFault
1f975ac044
Update templates, address JEP deprecations and place a few TODOs 2021-11-30 21:30:46 +01:00
NotMyFault
d3aaf7acff
Move to Paper 1.18 2021-11-30 18:04:47 +01:00
NotMyFault
e296a329c2
Port initial paperweight classes to 1.18 folder structure 2021-11-30 12:35:34 +01:00
NotMyFault
930025afac
Exclude 1.17 2021-11-30 00:23:46 +01:00
NotMyFault
38130f701c
feat: Setup project structure for 1.18 2021-11-30 00:16:19 +01:00
NotMyFault
0b45248b8c
style: Use minimized version output 2021-11-29 22:15:41 +01:00
NotMyFault
2a1bef28d0
Merge branch 'main' into major/2.0.0/1.18 2021-11-27 12:21:55 +01:00
Alex
05c22a6802
build: Update paperlib (#1439) 2021-11-27 12:21:38 +01:00
Alex
11e25911d5
upstream: Update upstream (#1430)
* upstream: Update upstream

c407471 Re-add class shutter with tweaks. (1947)

* upstream: Update Upstream

29f1c66 If a trace hits the world limit, cancel it (1942)

* upstream: Update upstream

511daa5 Update paperweight dev bundle
2021-11-26 23:31:27 +01:00
renovate[bot]
bd9e237376
build: Update dependency org.mockito:mockito-core to v4.1.0 (#1435)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-26 10:37:06 +01:00
NotMyFault
0af0d84cf7
build: Set kotlin jvm toolchain 2021-11-25 18:23:18 +01:00
NotMyFault
22f52fc4e1
ci: Sign artifacts 2021-11-25 13:14:49 +01:00
NotMyFault
121bd58029
ci: Register javadoc jar for lib artifacts 2021-11-23 14:14:01 +01:00
NotMyFault
64f393201f
revert: OSSRH snapshot deployment was successful, returning to baseline
This reverts commit 3a189f65f2.
2021-11-22 18:11:27 +01:00
NotMyFault
3a189f65f2
ci: Trigger initial sync with the OSSRH 2021-11-22 17:18:21 +01:00
NotMyFault
52293f54e8
ci: Cleanup and finish transition 2021-11-22 16:56:20 +01:00
NotMyFault
7d5659aeac
ci: Snapshot builds are the default 2021-11-22 14:35:40 +01:00
NotMyFault
705f580290
build: Update core dependencies
- Drop paranamer, you can access parameter names at runtime with Java 8+ natively
2021-11-22 13:47:59 +01:00
NotMyFault
507b8d5e35
ci: Switch deployment to gh actions and use semver & java 17 2021-11-22 13:38:32 +01:00
NotMyFault
4b57a34f59
[ci skip] Setup release drafter for future work 2021-11-22 09:44:24 +01:00
Owen1212055
fc4517fe4c
feat: Sort plugins on debugpaste (#1429)
* Replace plugins with an array and sort them by their name.

Resolves #1428

* Use comparator

Co-authored-by: Alex <mc.cache@web.de>
2021-11-20 16:28:18 +00:00
QuickWrite
1e5e9e04b4
style: Fix spelling mistake of 'FastAsyncWorldEdit' in craftscript readme (#1431)
Change 'FastAsybcWorldEdit' to 'FastAsyncWorldEdit'.
2021-11-20 12:02:25 +01:00
Alex
4c6e707fcf
fix: Error when setting PS v4's config option (#1427)
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1372
2021-11-19 09:42:33 +00:00
dordsor21
ef61ecccaa
Fix tab completion when *not* using %.
- Also allow tab-completion of % pattern when it's the first/only pattern being used
 - Also don't error when attempting to tab complete an invalid percent value
2021-11-18 18:42:19 +00:00
NotMyFault
5604000ae2
style: Don't use spaces before colons in yaml files 2021-11-17 17:58:42 +01:00
dordsor21
9bf9885ffb
Fix tab completion of % (random) pattern removing the % part of the input 2021-11-16 14:54:43 +00:00
dordsor21
5692ec54dd
Parse with square brackets after a % modifier
- Fixes #1409
2021-11-16 14:32:25 +00:00
dordsor21
66357b8adb
Fix RichParser assuming it should be used if its prefix is short than, and contained by, the input 2021-11-16 12:49:54 +00:00
dordsor21
575b0035df
Should be equals in checking if valid prefix when not shorter and with no arguments 2021-11-16 12:48:09 +00:00
dordsor21
cf6f54bd28
Fix RichParser suggestion sometimes giving a different pattern/mask when specifying arguments 2021-11-16 12:19:08 +00:00
dordsor21
527b7141a3
RandomPatternParser is an upstream class 2021-11-15 18:02:43 +00:00
NotMyFault
7f61483609
build: Update dependencies
Closes #1415
2021-11-15 12:38:52 +01:00
Alex
ae53990136
[ci skip] Update codeowners' team scope 2021-11-14 18:40:54 +01:00
Desjardins Jérôme
a2df590fae
feat: Add worldedit.schematic.save.global permission (#1406) 2021-11-12 14:21:06 +00:00
NotMyFault
6f33c5223d
build: Update Gradle
Address regression from 3ad2f8b5fa
2021-11-11 22:30:22 +01:00
NotMyFault
3ad2f8b5fa
Update Upstream
bd87665 Update paperweight + userdev bundle. (1930)
2021-11-11 22:22:44 +01:00
Jordan
6df16cfe96
refactor: Alter handling of errors in bindings (#1395)
* Alter handling of errors in bindings
 - Fixes #1384

* Arbitrarily use TextComponent#of for InputParseException
2021-11-11 17:37:25 +00:00
dordsor21
806ea14ad2
Unfix #826 in favour of allowing toggling the wand
- #826 is a pretty niche requirement, usually permissions do not change without a world change, relog, etc. very frequently
 - Allowing //toggleeditwand and /tool none on the wand feels more important
2021-11-10 22:13:44 +00:00
dordsor21
f04e891e0c
Allow schematics with empty, but present, biome data 2021-11-10 19:45:49 +00:00
renovate[bot]
4272f96ade
chore: Update org.antlr to v4.9.3 (#1404)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-09 09:59:48 +01:00
renovate[bot]
5f055d56cb
chore: Update dependency com.github.TownyAdvanced:Towny to v0.97.2.15 (#1402)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-09 09:59:22 +01:00
dordsor21
7a9549b75a
Unmerge wall/"besides / |" masks 2021-11-08 15:49:43 +00:00
dordsor21
95ecb5609d
Check for worldguard bypass permissions 2021-11-05 19:04:15 +00:00
Lilly Tempest
971ae04020
Fix incompatibility between WorldEdit and FAWE for LocalSession#getTool (#1399) 2021-11-04 20:29:40 +00:00
dordsor21
21b6f582e1
Switch some Caption#of to TextComponent#of 2021-11-03 18:33:19 +00:00
Pierre Maurice Schwang
c4d0a4e921
Update adapters (#1394) 2021-11-02 22:05:04 +01:00
dordsor21
d91a971e85
Allow extent to be used down the pipeline in BlockReplace
- It's quite likely for this to be required given BlockReplace use in replacenear
 - Fixes #1390
2021-11-02 20:53:14 +00:00
renovate[bot]
a716dd3778
chore: Update dependency org.checkerframework:checker-qual to v3.19.0 (#1391)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-02 17:40:23 +01:00
JayemCeekay
2c56e480c3
Expand certain FAWE limits to use Long instead of Integer. (#1382) 2021-11-02 16:38:39 +00:00
dordsor21
0674f39600
Synchronise chunk filtering 2021-11-02 13:34:37 +00:00
renovate[bot]
d8735da871
chore: Update dependency commons-cli:commons-cli to v1.5.0 (#1389)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-01 13:53:29 +01:00
renovate[bot]
bd8a2a5f2a
chore: Update dependency net.kyori:adventure-nbt to v4.9.3 (#1387)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-01 13:53:20 +01:00
renovate[bot]
8a03b89434
chore: Update net.kyori to v4.9.3 (#1388)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-01 13:53:08 +01:00
renovate[bot]
67874bc9f8
chore: Update dependency com.github.TownyAdvanced:Towny to v0.97.2.12 (#1380)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-01 13:51:49 +01:00
Arcaniax
ee0d1b5a5b
fix: Add missing Gray Candle types (#1383)
* Added Gray Candle types

Added GRAY_CANDLE & GRAY_CANDLE_CAKE

* Added Gray Candle to the ItemTypes
2021-10-29 14:57:58 +00:00
Pierre Maurice Schwang
14cb97d0ad
fix: //regen with custom populators (#1376)
* Refraction + more fixes

* Remove exception debug

* Fix populator issues with //regen

* Fixed code style

* Further simplify

* Update adapters

Co-authored-by: Alex <mc.cache@web.de>
2021-10-25 14:13:02 +00:00
dordsor21
1b1f3bbcbe
Fix #1375 2021-10-25 15:04:59 +01:00
dordsor21
47f25c4f31
Slight cleanup of region parsing in EditSessionBuilder 2021-10-25 14:13:26 +01:00
dordsor21
f7e94fd450
Only add backupregions if whitelisting 2021-10-25 14:12:36 +01:00
dordsor21
4e6aee6bfb
Don't consider global region for blacklisting WG regions 2021-10-25 14:12:21 +01:00
dordsor21
75be38925f
Fix #1378 2021-10-25 14:11:17 +01:00
NotMyFault
ad640532dc
Update Upstream
d48530c Don't allow editing without a Bukkit Impl Adapter. (1920)
2021-10-24 12:21:23 +02:00
NotMyFault
c55bc8c05f
refactor: Move update checker to core
feat: Add permission for tracing
2021-10-23 19:36:59 +02:00
dordsor21
3d70d9e496
RegionIntersection requires List constructor 2021-10-23 14:09:01 +01:00
dordsor21
ae949d607b
Move paperweight to BinaryTag
- Upstream put paperweight into master branch, which doesn't have BinaryTags
 - Fixes #1374
2021-10-22 16:00:51 +01:00
MrKinau
7b775ca57d
Remove Only-vanilla-biomes restriction (#1373) 2021-10-22 15:34:37 +01:00
dordsor21
857090bdde
Add meaningful default methods to getMask for region protection 2021-10-21 18:25:36 +01:00
NotMyFault
d4eda78818
refactor: Remove redundant loggers 2021-10-21 17:26:16 +02:00
NotMyFault
c07ba4e88e
Merge branch 'feature/region-blacklist' 2021-10-21 17:13:13 +02:00
NotMyFault
7294e2346e
fix: Update adapters to latest reflection changes 2021-10-21 11:31:12 +02:00
dordsor21
8ed4736066
Add override and correct default method for fromNative
- Fixes #1370
2021-10-20 13:47:55 +01:00
NotMyFault
e7a6c3e58c
Merge branch 'chore/main/deprecate-unsafe-utils' 2021-10-19 22:09:01 +02:00
dordsor21
13be5a22ad
Fix #1370
- Actually override toNative in adapter
 - Correctly assign generic-type
 - Better default method for BinaryTag retrieval in adapter
2021-10-19 15:14:25 +01:00
dordsor21
4ee61a93c8
Fix incorrect method params 2021-10-19 14:34:35 +01:00
dordsor21
252abf862b
Add more Refraction 2021-10-19 14:30:51 +01:00
dordsor21
37eb4a1008
Regress to upstream for (Binary)Tags in data fixers 2021-10-19 14:12:02 +01:00
dordsor21
b5479e480d
Don't attempt to run null P2 tasks 2021-10-19 13:35:00 +01:00
NotMyFault
bd9476a175
refactor: Address .editorconfig violations 2021-10-18 23:09:21 +02:00
NotMyFault
9a33789e41
build: Update shadow and PlotSquared
Closes #1367
2021-10-18 22:41:31 +02:00
NotMyFault
f7c428a894
Merge branch 'main' into chore/main/deprecate-unsafe-utils 2021-10-18 22:08:27 +02:00
NotMyFault
6827f17d4d
build: Closes #1365 2021-10-18 22:08:07 +02:00
NotMyFault
f1e8a1a29a
refactor: Move Unsafe to reflection class 2021-10-18 22:01:54 +02:00
Pierre Maurice Schwang
c7a490fa03
Fix paperweight changes (#1364) 2021-10-18 20:38:43 +01:00
NotMyFault
74486fc8c9
chore: Update adapters 2021-10-17 17:33:48 +02:00
dordsor21
8fe610311d
Comments 2021-10-17 15:53:19 +01:00
dordsor21
c7c00021b2
Cleanup 2021-10-17 15:53:19 +01:00
dordsor21
7d894228d0
Implement region blacklisting 2021-10-17 15:53:04 +01:00
NotMyFault
f0880a27a0
feat: Paperweight support (#1362)
* Initial work towards paperweight

* feat: Port Fawe classes to paperweight

- Hide UnsafeUtilities in javadocs
- Fix typo in Regenerator
- Create fawe tmp directory for fawe regen

* Update adapters

* chore: Update MiniMessage

* Address todos

* Fix leftover Tuinity loggers
2021-10-17 16:32:36 +02:00
Jordan
9c1c8bfdf2
Implement restoring biomes, entities, and extended world heights (#1316) 2021-10-17 13:40:55 +00:00
NotMyFault
27865dc785
chore: Exchange debug log levels & component-ify a few messages (#1342) 2021-10-17 14:50:42 +02:00
renovate[bot]
3a952e1938
chore: Update dependency org.mockito:mockito-core to v4 (#1360)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-17 10:06:45 +02:00
NotMyFault
69a85fb068
tests: Update tests to latest Server changes 2021-10-17 10:06:21 +02:00
NotMyFault
5db9a601b1
feat: (Re-) Add update notifications (#1361)
* feat: (Re-) Add update notifications

Fixes #1348

* Move update notification to seperate class

- Add a couple of linebreaks to the chat messages
2021-10-17 09:55:25 +02:00
renovate[bot]
e5fbc4c971
chore: Update com.google.auto.value to v1.8.2 (#1353)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-11 13:06:34 +02:00
renovate[bot]
af94f9b1f9
chore: Update org.antlr to v4.9.2 (#1351)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-11 13:06:20 +02:00
NotMyFault
c58f9daf0d
build: Test with valid junit version
This is likely a typo from mockito. Junit 4 was released in 2014, not to mention prior versions...
2021-10-10 01:21:44 +02:00
renovate[bot]
4ce16a0343
chore: Update dependency org.checkerframework:checker-qual to v3.18.1 (#1343)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-10 00:25:21 +02:00
NotMyFault
99b45c13fb
fix: Invalid yaml syntax of new config values
Follow up from 6839fa5567
2021-10-09 17:22:16 +02:00
dordsor21
6839fa5567
Add configurable disallowed states for limits, global disallowed blocks (#1312) 2021-10-09 11:02:26 +00:00
NotMyFault
d641e21dfc
[ci skip] Move to org level templates 2021-10-08 19:03:41 +02:00
Pierre Maurice Schwang
2eb6451810
fix: Add dummy constructor for CraftBook5 support (Fixes #1334) (#1344)
Co-authored-by: NotMyFault <mc.cache@web.de>
2021-10-07 17:18:10 +00:00
NotMyFault
e2924f4cba
feat: Improve wording of allowed-plugins message (#1341)
Fixes #1319
2021-10-07 17:12:17 +00:00
Pierre Maurice Schwang
546ad86841
fix: Update StubServer.java to the latest spigot changes (#1345) 2021-10-07 18:05:56 +01:00
renovate[bot]
4ffddd8c93
Update dependency net.kyori:adventure-nbt to v4.9.2 (#1338)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-04 17:15:08 +02:00
renovate[bot]
fad1f5c2f0
Update net.kyori to v4.9.2 (#1339)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-04 17:14:58 +02:00
renovate[bot]
632c9845c1
Update dependency com.github.TownyAdvanced:Towny to v0.97.2.4 (#1335)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-04 17:14:38 +02:00
renovate[bot]
1166db60d1
Update dependency dev.notmyfault.serverlib:ServerLib to v2.3.1 (#1336)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-04 17:13:48 +02:00
renovate[bot]
f78730e337
Update dependency dev.notmyfault.serverlib:ServerLib to v2.3.1 (#1337)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-04 17:13:41 +02:00
dordsor21
6895234815
Don't allow edits on plots when owner is offline and player is only added (#1313) 2021-10-04 12:34:40 +00:00
dordsor21
d44f297068
Fully fix #1331 2021-10-01 13:27:05 +01:00
dordsor21
3a45a31e65
Better error message for LocalBlockVectorSet 2021-09-30 13:17:28 +01:00
dordsor21
f886320c44
SurfaceMask should be copied properly.
#1331
2021-09-30 13:17:15 +01:00
dordsor21
7a6a0f68fe
Don't allow area pickaxe outside max y
#1331
2021-09-30 13:16:15 +01:00
dordsor21
c10e48320b
Fix inverted expectFail boolean 2021-09-30 12:35:17 +01:00
NotMyFault
2e10936b3d
[ci skip] chore: Limit dependency updates to one day per week
Closes #1333
2021-09-29 22:48:42 +02:00
renovate[bot]
eafab87540
Update dependency com.github.TownyAdvanced:Towny to v0.97.2.0 (#1323)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-29 18:03:49 +02:00
dordsor21
0ed98729f8
Allow console to execute commands now that editsessions etc. accept actors
- Fixes #724
 - Fixes #1044
2021-09-28 15:59:52 +01:00
dordsor21
fa2f50dea8
Sometimes an overlay position may not be able to be found. Attempt to resolve or fail nicely. 2021-09-28 14:39:14 +01:00
dordsor21
a3365a12bc
Fix #1327 2021-09-28 14:27:36 +01:00
dordsor21
e94b85a0fc
Don't load clipboard more than once. Deprecate BukkitPlayer constructors as it's more efficient to use cached players 2021-09-28 14:11:12 +01:00
dordsor21
848eac8623
Fix schematic offset when loaded to clipboard 2021-09-28 13:16:26 +01:00
dordsor21
56999fd1e0
Drain bubble columns as well
Fixes #1326
2021-09-27 14:42:43 +01:00
dordsor21
1cf5899586
Allow deletion of DOC
Fixes #1325
2021-09-27 14:39:21 +01:00
dordsor21
b73db47e01
Add switch to schem loadall to replace existing clipboard(s) 2021-09-27 14:15:26 +01:00
dordsor21
58f231ad12
Slightly improve add clipboard hover message for schematic list 2021-09-27 14:14:24 +01:00
dordsor21
5155055446
Add deprecation message to fawe EditSessionBuilder 2021-09-26 22:10:59 +01:00
dordsor21
e6675f1656
Default per player schematics to false 2021-09-26 22:07:25 +01:00
NotMyFault
5940ebbccc
[ci skip] chore: Never suggest to update guava
Closes #1321 
Closes #1320
2021-09-26 01:36:47 +02:00
NotMyFault
ca15e93102
refactor: Remove lz4-stream
LZ4-Java contains a modern version & delegate for lz4-java-stream.
2021-09-26 00:48:50 +02:00
dordsor21
268244119f
Update adapters? 2021-09-24 17:05:26 +01:00
dordsor21
6b5f21d67b
Support old, corrupt, schematics 2021-09-24 16:41:09 +01:00
dordsor21
4e944052cd
un-transitive some dependencies 2021-09-24 15:49:30 +01:00
dordsor21
e97c945b2f
Big fix to clipboards when relogging/restarting server etc.
- Refactor the way FAWE clipboards work slightly with regards to offsets (FAWE-added) and origin (upstream-present)
 - Better error messages when exceptions are thrown attempting to load DOC
 - No longer attempt to resolve old clipboard versions. Attempt to give informative error instead
 - Don't always delete clipboards held in memory on player logout unless configured to do so
 - Go back to fully closing the DOC on logout. We now attempt to lock the file which will hopefully help with debugging shared clipboard folders
2021-09-24 12:22:01 +01:00
dordsor21
bfd9e5b347
Don't stop edits for old clipboards, attempt to load them anyway (for now) 2021-09-24 09:32:49 +01:00
dordsor21
8593c2df9f
Rearrange DOC methods 2021-09-23 12:42:51 +01:00
dordsor21
07c02b5825
Remove import static org.apache.logging.log4j.LogManager.getLogger 2021-09-23 12:34:22 +01:00
dordsor21
6c56fa29aa
Fix #1317 2021-09-22 22:22:39 +01:00
NotMyFault
a5795461f2
Improve a few dependency scopes 2021-09-22 23:00:12 +02:00
dordsor21
40b024fbba
Set legacy ID when adapter is loaded to enable reading/writing anvil 2021-09-22 16:15:18 +01:00
dordsor21
663d0139b7
default to a meaningful preload chunk count 2021-09-22 15:58:20 +01:00
dordsor21
a3d50585c2
Don't print error message if we're expecting it on biome loading 2021-09-22 15:58:11 +01:00
dordsor21
3376baa3c5
Remove needless EditSession#getWorld for setting blocks/biomes in a couple of cases
#32 IntellectualSites/FastAsyncWorldEdit-Adapters#7
2021-09-22 15:04:12 +01:00
dordsor21
d25a85e0d4
Fix expression evaluation method used for generatebiome
#32
2021-09-22 15:03:03 +01:00
dordsor21
4400b0f83e
Fix #1114
- Ensure short is correctly cast to int, as we're using it as if it were unsigned
2021-09-22 14:32:49 +01:00
dordsor21
a241e594c1
Slight adjustment to DOC 2021-09-22 13:14:10 +01:00
dordsor21
64036a38cf
Update adapters to 32c896db93 2021-09-22 12:58:09 +01:00
dordsor21
268d8cff49
Apply list of properties everywhere 2021-09-21 18:53:37 +01:00
dordsor21
cf585c48ae
Update adapters 2021-09-21 18:41:01 +01:00
dordsor21
e750e014ab
Properties can have the same string name
Make map of all properties string against list
2021-09-21 18:34:31 +01:00
dordsor21
b8ec4be95c
Revert "Slightly preferable messages on UsageException thrown by piston"
This reverts commit e9adf0f30d.
2021-09-21 17:30:32 +01:00
dordsor21
c805102819
Fix #1143 2021-09-21 17:18:49 +01:00
NotMyFault
3617a29ba8
Address javadoc violations 2021-09-21 17:40:53 +02:00
dordsor21
1de3a6b54a
Don't return "=" pattern early either 2021-09-21 15:07:58 +01:00
dordsor21
70f7f00abf
Do the same for "=" mask 2021-09-21 15:06:46 +01:00
dordsor21
c26977f578
Fix very specific issue where charmasks (< > $ etc.) are used with other masks, but only the charmask is used 2021-09-21 15:05:43 +01:00
dordsor21
57b47d2451
Use a MaskTraverser to set extent where it will be a WorldWrapper otherwise 2021-09-21 14:59:49 +01:00
dordsor21
23ca345a2e
Don't setextent twice in replace 2021-09-21 14:51:39 +01:00
dordsor21
971977a66a
Fix //sel list 2021-09-21 14:51:05 +01:00
dordsor21
84b896151f
Lazy fix for #1271 2021-09-21 14:39:14 +01:00
dordsor21
d0056870be
Fix fuzzy region 2021-09-21 14:31:03 +01:00
dordsor21
69ae4a7121
Fix ellipsoid selection 2021-09-21 14:07:10 +01:00
renovate[bot]
a23abc1bb6
Update com.plotsquared to v6.1.2 (#1307)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-21 00:57:59 +02:00
dordsor21
0fcf996c78
Fix #1314 2021-09-20 23:54:26 +01:00
dordsor21
e9adf0f30d
Slightly preferable messages on UsageException thrown by piston 2021-09-20 23:35:04 +01:00
dordsor21
9d26f030dc
Fix some command errors being hidden by a usage message 2021-09-20 23:18:38 +01:00
dordsor21
040edc8fd0
Adjust exception catch slightly 2021-09-20 23:07:58 +01:00
NotMyFault
f8ed4e0c38
Separate and uppercase libs artifacts 2021-09-20 22:30:46 +02:00
dordsor21
bb06492091
Fix -f flag 2021-09-20 18:10:37 +01:00
dordsor21
017a28b3dd
Implement getAllProperties to code and adapters 2021-09-20 16:00:50 +01:00
dordsor21
35e0a47beb
Don't have adapters as "dependency" 2021-09-20 15:09:34 +01:00
dordsor21
d5be6940c7
Add default getAllProperties method 2021-09-20 14:46:51 +01:00
dordsor21
17a97f2f19
Fix lack of handling of custom world heights in CharFilterBlock 2021-09-20 14:15:08 +01:00
dordsor21
7a9cbe5d77
Correct description of strip nbt 2021-09-20 01:54:49 +01:00
NotMyFault
9d68cd8380
Automatic deployment (#1298)
* Fixes #992

* Address asterisk imports

* Deploy sources jar & javador jar as well

* Merge branch 'main' into feature/main/automaticDeployment
2021-09-19 22:50:34 +02:00
dordsor21
aba147f787
Minor spring clean 2021-09-19 21:40:15 +01:00
dordsor21
8a4f28a7cc
StripNBT processor rather than extent 2021-09-19 21:39:00 +01:00
dordsor21
b11a67e435
Fix #1311 2021-09-19 21:20:18 +01:00
Matt
4f68fb0e26
Add tracing feature to EditSessions (Upstream 1301) (#1112)
Co-authored-by: Octavia Togami <octavia.togami@gmail.com>
Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2021-09-19 20:02:41 +00:00
dordsor21
f405994346
Improve fullycopy pattern parsing
- Don't attempt ClipboardFormats#loadAllFromInput if the user is typing #copy or #clipboard to avoid needless "File dialogs are not supported in your environment." message
2021-09-19 20:47:40 +01:00
dordsor21
abaa98d2a9
Fix #403 2021-09-19 20:47:21 +01:00
NotMyFault
5f7411114e
Fixes #1310 2021-09-19 21:42:53 +02:00
renovate[bot]
8cc93a2255
Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.6 (#1305)
* Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.6

* Make it compile

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2021-09-18 21:59:29 +02:00
dordsor21
0a48765c98
Add //blob command equivalent to //br rock 2021-09-18 17:42:58 +01:00
dordsor21
7d032ba69f
Scattercommand should use the same editsession for all commands, make it "silent" by default and allow players to see output if wanted. 2021-09-18 17:42:40 +01:00
dordsor21
34301b446a
Allow scatter command brush to use FAWE commands. Best for scatter sphere, etc. 2021-09-18 17:08:03 +01:00
dordsor21
51aa500857
move yscale earlier in br height for people that can't work it out themselves 2021-09-18 16:20:28 +01:00
dordsor21
7a0c0d5d41
Fix #990 2021-09-18 16:15:31 +01:00
dordsor21
fad1fcd8ee
Fix RichParser suggestions 2021-09-18 15:07:41 +01:00
dordsor21
54398ebe1c
Add timeout to regex masking 2021-09-18 15:01:09 +01:00
dordsor21
dbbb450172
Flush clipboards before writing schematics.
#1286
2021-09-18 03:19:49 +01:00
dordsor21
bd95d5a86d
Adjust mask managers
- Add list of "exclusive" managers to config to aid users in having some sort of prioritisation.
 - Fixes #960 if PlotSquared is added to exclusive managers, otherwise, there's no particularly sane way of adding prioritisation without requiring a treemap be added to YAML config, or for us to decide upon it ourselves
2021-09-18 03:19:27 +01:00
NotMyFault
fbbb4ed8fa
Update adapters to f840c74a30b5c5c622080cb9678db58deb7062b9 2021-09-17 19:58:54 +02:00
dordsor21
1cc6ad1481
Fix #1049 2021-09-17 17:26:41 +01:00
dordsor21
90aeb48040
Fix #1297 2021-09-17 17:12:14 +01:00
NotMyFault
07be1c6a44
Remove native libs - lz4-java links them dynamically 2021-09-17 16:22:02 +02:00
NotMyFault
ffd74e59ef
[ci skip] Closes #1306 Closes #1304 2021-09-17 16:00:25 +02:00
dordsor21
5093569ce0
Fix #1303 2021-09-17 14:54:51 +01:00
dordsor21
74697ee312
Fix ZSTD implementation and test-loading. Don't allow disabling of the test on startup 2021-09-17 14:38:28 +01:00
NotMyFault
9fb6ebe7ac
Shift ZSTD bindings check 2021-09-16 21:56:28 +02:00
dordsor21
1dd0dac462
Correct equality check for adding post processor 2021-09-16 17:49:16 +01:00
dordsor21
4182d7473c
Slightly improve regen workflow, update adapters to a9c745a600 2021-09-16 17:42:31 +01:00
dordsor21
e4cbd85197
Ensure adapters are up to date 2021-09-15 01:44:00 +01:00
dordsor21
f10dbe7387
Use an object array for synchronising on internal chunk sections rather than the sections array itself.
- Synchronising on full sections synchronises on the global FULL instance (bad)
- Synchronising on empty sections synchronises on the local empty instance (bad)
- Leads to needless thread locking, and raises the possibility of cyclic locks considerably
2021-09-14 20:20:04 -04:00
renovate[bot]
e989a4ebb0
Update com.plotsquared to v6.1.1 (#1299)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-14 17:04:21 +02:00
NotMyFault
45b745a580
[ci skip] Closes #1300, Closes #1301 2021-09-14 17:02:54 +02:00
dordsor21
635ec0e7a8
Fix #736 2021-09-14 14:44:23 +01:00
dordsor21
8120163f5e
Fix #727 2021-09-14 14:33:20 +01:00
dordsor21
dad991e7aa
synchronise filterBlocks - we shouldn't be able to execute the call method whilst a filter is ongoing and vice versa 2021-09-14 14:32:42 +01:00
dordsor21
09d2996451
Don't accept values smaller than parallel threads for target size
- Smaller than parallel threads implies any time any thread tries to do anything, another thread must cancel its work, and the chunk is submitted.
2021-09-14 14:30:32 +01:00
dordsor21
daa418a287
Fix needless complication of section position methods in CharBlocks children 2021-09-13 18:33:42 +01:00
dordsor21
ce7a97368f
Improve javadocs on BlockArrayClipboard, ensure correct clipboard is used for BlockArrayClipboard's parent clipboard 2021-09-13 15:32:33 +01:00
dordsor21
06d716248e
Flush clipboard rather than close on player disconnect
Addresses #1291
2021-09-13 15:08:03 +01:00
dordsor21
3088b1245c
Simplify flushing of clipboards in ClipboardCommands 2021-09-13 15:07:16 +01:00
dordsor21
f641fc1716
Javadoc 2021-09-13 13:27:47 +01:00
dordsor21
5207981fb2
Make clipboard flushable
#1286
2021-09-13 13:25:11 +01:00
dordsor21
fcbbc72a19
Refactor the try-catch for copy/cut commands, switch to saveDiskClipboard instead of closing the clipboard on error
Address #1291
2021-09-13 13:19:57 +01:00
dordsor21
adf83bdd0a
Use default blockstate internal id for creating blockstates from their serialised form
Fixes #1294
2021-09-13 13:14:49 +01:00
dordsor21
40a4010041
Add loadIfPresent method for use where the section should definitely exist and be FULL 2021-09-13 12:47:00 +01:00
dordsor21
af890cf21d
Fix build
(cherry picked from commit dc2e1bec1e)
2021-09-13 12:31:06 +01:00
dordsor21
b6b6ba7265
Improve CachedMask a bit - no need to unwrap/wrap blockvectors, allow extents to be parsed
(cherry picked from commit 41c0ea98f1)
2021-09-13 12:30:58 +01:00
dordsor21
f5d6d4079a
*Actually rename section index everywhere
(cherry picked from commit 3ea3bd2a78)
2021-09-13 12:30:49 +01:00
dordsor21
7876ab825e
Make blocking executor a fair policy
Safer if we're submitting lots of chunks for recursive operations. These chunks should be handled in the order they're submitted so we don't handle a chunk that's been submitted twice (possible) in the wrong order

(cherry picked from commit ce915fe04d)
2021-09-13 12:30:44 +01:00
dordsor21
66b79b4ea2
Remove unneeded IQueueWrapper, clean up some queue classes slightly
(cherry picked from commit 66e22df3f4)
2021-09-13 12:30:39 +01:00
dordsor21
d60d178513
Rename section index to position as it's a more suitable name
(cherry picked from commit 74f1d21f6e)
2021-09-13 12:30:22 +01:00
dordsor21
d9a8c047a2
don't create chunk set if it doesn't already exist when checking for biomes
It shouldn't ever create the set at this point though

(cherry picked from commit 3ea725a863)
2021-09-13 12:30:12 +01:00
dordsor21
fc47fd586c
Update adapters
(cherry picked from commit 6f180421e1)
2021-09-13 12:30:05 +01:00
dordsor21
da2a846d3d
Don't return null when adding processors to NullExtent
(cherry picked from commit 1a8ad8133e)
2021-09-13 12:29:49 +01:00
NotMyFault
cdbbedb662
Update Upstream
6008fe7 Remove class shutter
2021-09-13 10:51:58 +02:00
dordsor21
5d31b7034d
Deprecate sponge schematic reader/writer and tell users why (#1287) 2021-09-13 10:51:58 +02:00
dordsor21
8e214b1232
Javadocs to LocalBlockVectorSet 2021-09-11 16:59:00 +01:00
dordsor21
8c8419a1c5
LocalBlockVectorSet shouldn't actually be used from multiple threads. SparseBitSet is not thread safe 2021-09-11 16:41:42 +01:00
dordsor21
6e586da83e
Some code cleanup
- Simplify MaskFilter slightly
- Improve thread safety of LocalBlockVectorSet
- Simplify if statement in SingleThreadQueueExtent
- Better error in MathMan#tripleSearchCoords for handling of the error in some cases
2021-09-11 16:38:01 +01:00
dordsor21
e85586db80
Only set ParserContext extent to world if null when setting world 2021-09-11 16:25:45 +01:00
dordsor21
a923c112ee
Actually do what I said for min/max Y in HeightmapProcessor 2021-09-11 14:25:47 +01:00
dordsor21
2c0c57ec4f
Update adapters 2021-09-11 13:49:06 +01:00
dordsor21
82220ef87e
Move HeightMapType and HeightmapProcessor into own package 2021-09-11 13:37:31 +01:00
dordsor21
333b9c184e
Go into more detail about tree types not being there because version 2021-09-11 12:54:09 +01:00
dordsor21
f84c98e721
Use given min/max y values in HeightmapProcessor 2021-09-11 12:41:06 +01:00
dordsor21
6cbd9631a0
Improve notes on getting the stored section range/refactor method name 2021-09-11 12:40:39 +01:00
dordsor21
37998ec598
Refactor heightmap classes to math where it makes more sense
(not required by heightmap processor, nor are they processors, used for heightmap brushes etc.)
2021-09-11 12:23:03 +01:00
SirYwell
5fb4434afe Fix indexing and custom world heights in HeightmapProcessor 2021-09-11 10:26:02 +02:00
NotMyFault
f29d68b16e
Update Upstream
fbf61ef Fix raise and lower deform brushes (1889)
2021-09-11 10:15:44 +02:00
dordsor21
db24b429c1
only close clipboard on error during copy
apply to //cut as well
2021-09-11 00:27:26 +01:00
dordsor21
470ba64fe4
Fix #1260 2021-09-10 17:46:21 +01:00
dordsor21
829ddc393f
Fix #1268 2021-09-10 17:14:55 +01:00
dordsor21
c16212e456
Update adapters 2021-09-10 16:54:30 +01:00
dordsor21
88ae6d9e1d
Optimise HeightmapProcessor (around 16x faster) 2021-09-10 16:53:25 +01:00
dordsor21
f0a6fa13da
Fix serverlib shading 2021-09-10 16:25:31 +01:00
dordsor21
0e72fa5058
Specify requirement for delay-chunk-unloads-by to be set for preloading 2021-09-10 15:52:46 +01:00
NotMyFault
91919d31b0
Update PlotSquared 2021-09-10 16:10:05 +02:00
dordsor21
3f182c63bc
Fix #1285 2021-09-10 14:53:07 +01:00
dordsor21
effb94623a
Fix exceptions being squashed RegionVisitor preloading 2021-09-10 14:41:15 +01:00
dordsor21
ef62f1e0d9
Fix adapters cos it's just plain wrong..? 2021-09-10 14:13:59 +01:00
dordsor21
195a13a23c
some codestyle application 2021-09-08 16:39:43 +01:00
NotMyFault
dc11b74020
Closes #1283 Closes #1284 2021-09-07 10:41:42 +02:00
NotMyFault
8c328abdd2
Update Upstream
6c08b68 Set Multi-Release in CLI manifest
2021-09-07 10:19:04 +02:00
NotMyFault
91ad0a20ef
Identify CLI as Fawe version 2021-09-07 01:06:22 +02:00
NotMyFault
17a1c7e0bf
Fix CLI 2021-09-06 20:17:43 +02:00
NotMyFault
7c3c165fd6
Merge branch 'main' of https://github.com/IntellectualSites/FastAsyncWorldEdit into main 2021-09-06 15:31:27 +02:00
NotMyFault
8aadeb9291
Identify as Fawe when throwing unknown exceptions
Closes #1281
Closes #1279
Closes #1282
2021-09-06 15:28:54 +02:00
renovate[bot]
e3ab25b3c9
Update dependency org.checkerframework:checker-qual to v3.18.0 (#1280)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-06 14:59:17 +02:00
NotMyFault
e08a14b3a7
Renovate
Closes #1267
Closes #1269
Closes #1276
Closes #1270
Closes #1253
2021-09-06 13:38:22 +02:00
NotMyFault
3b4bd5384c
Closes #1275 2021-09-06 13:13:01 +02:00
renovate[bot]
c342de28f2
Update dependency com.github.TownyAdvanced:Towny to v0.97.1.7 (#1274)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-06 13:11:50 +02:00
renovate[bot]
489b0d050c
Update dependency com.github.MilkBowl:VaultAPI to v1.7.1 (#1273)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-06 13:11:19 +02:00
NotMyFault
d236470df8
Update Upstream
b1c230d Add conditional checking in help command (1888)
b4fbbc9 Move clearable checks for Bukkit to adapters (1887)
2021-09-04 10:31:31 +02:00
dordsor21
cdc3abbc43
bump p2 version 2021-09-03 14:48:58 +01:00
dordsor21
4bf2781cd0
Update adapters to ae35e53276 2021-09-02 18:07:08 +01:00
dordsor21
79f4be3941
Adjust some synchronisation 2021-09-02 18:06:36 +01:00
NotMyFault
09c4655be7
Setup allowed-plugins with an example plugin 2021-09-02 18:53:14 +02:00
dordsor21
f8aaf0cae3
Don't set extent to self when cancelling in AbstractDelegateExtent
#749
2021-09-02 17:13:38 +01:00
dordsor21
93dff36ee2
Fix #1265 2021-09-02 14:08:49 +01:00
dordsor21
15d888a40c
Updated adapters to 5016d6d295
#1266
2021-09-02 13:47:27 +01:00
dordsor21
b9e4b31c68
Clean up ChunkHolder slightly, only trim chunk get if not already present 2021-09-02 12:31:27 +01:00
dordsor21
fb7e95c440
Improve exceptions (#1256)
- Kick more exceptions further up the pipeline to be more likely to be shown to player
- Try to avoid lots of console spamming when it's the same error multiple times
- Allow parsing of FaweExceptions during commands to better give information to players
2021-09-01 16:36:03 +02:00
NotMyFault
0c9270dbc1
8f8288a96b 2021-08-29 20:25:09 +02:00
dordsor21
0e62760abf
Update adapters to 9c5798ea7d 2021-08-29 10:28:23 +01:00
dordsor21
ebc38a62ad
Should fix #1237 and should fix #1236 2021-08-26 16:44:49 +01:00
dordsor21
cacfcb8c5c
LimitExtent isn't a processor 2021-08-26 16:44:08 +01:00
NotMyFault
81534b3476
Ignore datapacks on 1.15 2021-08-26 10:47:00 +02:00
NotMyFault
ee14f7ebb1
Closes #1254 2021-08-25 17:34:42 +02:00
dordsor21
da8289f8ba
Fix #826 2021-08-25 16:19:51 +01:00
dordsor21
4050cf238f
Fix #1217 2021-08-25 15:48:39 +01:00
dordsor21
29bebcd034
Fully fix #949 2021-08-25 15:32:25 +01:00
dordsor21
4e463af1df
Remove log output from DefaultBlockParser 2021-08-25 14:12:40 +01:00
dordsor21
a66080d803
Fix build, add note 2021-08-25 14:06:12 +01:00
dordsor21
46fb0c9418
Add binary tag methods to IDelegateBukkitImplyAdapter 2021-08-25 12:53:37 +01:00
dordsor21
ea6b29f145
Fix up annotations in block classes and slight cleanup 2021-08-25 12:25:33 +01:00
dordsor21
80d99073ec
Remove PluginPreloader 2021-08-25 11:19:31 +01:00
dordsor21
df18fcef92
Fix #1250 2021-08-25 11:16:06 +01:00
dordsor21
46c96b45fc
Fix build 2021-08-25 11:16:01 +01:00
dordsor21
012e55e780
Fix links 2021-08-25 11:08:14 +01:00
dordsor21
7d9abc9273
Skip corrupt tile entities in legacy schematics 2021-08-23 21:46:50 +01:00
dordsor21
6301a7adb9
Deprecate and add the warnings for BlockType#getState as it is broken 2021-08-23 21:28:06 +01:00
dordsor21
c0893a404d
Set default number of iterations for snow smooth brush to 1. 2021-08-23 21:27:35 +01:00
dordsor21
0aadef97d0
Quick fix for SnowHeightMap 2021-08-23 21:26:59 +01:00
dordsor21
ddc59809d8
Update adapters to ff01bfd70d 2021-08-23 20:59:29 +01:00
NotMyFault
869a8058cc
Skip checking for custom biomes on 1.15.2 2021-08-23 21:15:41 +02:00
dordsor21
1a0f7df3f4
Fix #1243 2021-08-23 13:08:10 +01:00
dordsor21
2e0de7b197
Fix nullability issue with SnowHeightMap mask, apply some cleanup and reduce needless object creation 2021-08-23 11:57:00 +01:00
NotMyFault
cf671ad7ff
Update Upstream
ed28089 Don't crash if fields are null in ChunkDeleter (1874)
f049d56 Revert "Use a Guava Cache instead of a ThreadLocal (1859)"
c5a4450 Internally use a negated mask class to prevent russian doll wrapping (1877)
1397ec7 Add Snow Smooth Tools (1580)

Fixes #955
Fixes #858
2021-08-22 11:56:39 +02:00
SirYwell
df8b2802b2 Support custom world min heights when processing heightmaps 2021-08-21 10:52:45 +02:00
dordsor21
cd576a2a87
Fix #1241 2021-08-20 16:33:58 +01:00
dordsor21
8e899b8524
Skip registering "custom" biome.
Update adapters to 332c1f6bb17d2ded53fe5b09f3f2a4578f3f9bfc
2021-08-20 16:30:51 +01:00
dordsor21
3dd943f961
Avoid paper-only method 2021-08-20 15:53:12 +01:00
dordsor21
cf68caff99
Correct default biome loading method 2021-08-19 14:12:55 +01:00
dordsor21
f412796f28
Load default biomes into registry at earliest convenience, then load custom biomes later. 2021-08-19 13:48:24 +01:00
dordsor21
563ad7761a
Fix LocalBlockVectorSet
- Fixes #1238
2021-08-19 13:10:09 +01:00
NotMyFault
188e4b6215
Fix unknown direction exception missing key 2021-08-18 14:57:14 +02:00
NotMyFault
f258a3d52c
Add javadoc linking for bukkit module 2021-08-18 12:08:52 +02:00
NotMyFault
cc97510523
[ci skip] Update Javadocs' links 2021-08-18 11:42:57 +02:00
NotMyFault
613b973309
Add javadoc linking 2021-08-18 11:26:14 +02:00
dordsor21
6a932f2eda
Preloading is paper only. 2021-08-17 22:34:51 +01:00
NotMyFault
73a237d75e
Update adapters 2021-08-17 23:22:03 +02:00
dordsor21
1d9b1a3d5e
Remove hardcoding of world limits (#1199)
* Remove hardcoding of world limits
 - seems to be working fine without the datapack for world height changing
 - particular attention should be given to LocalBlockVectorSet and MathMan changes

* update adapters

* Override getMinY in various classes and ensure selections have a world attached to them

* no message

* Address comments
 - Fix for lighting mode 1

* A few more changes

* Fix LocalBlockVectorSet

* Fix range statement

* Various fixes/comment-addressing
- There's not much point in having a different file name now for history. We've broken it before...
- Fix history read/write
- Fix range on for loops in CharBlocks

* undo bad CharBlocks change

* Fix history y level

* Fix biome history

* Fix lighting

* Fix /up

* Make regen fail not because of these changes

* Fixes for y < 0

* Fix isEmpty where only the uppermost chunksection is edited

* Fix javadocs/FAWE annotations

* Better explain why BiomeMath is removed

* If history task throws an error, it should only be caught and printed if not completing now.

* Min|max world heights for new patterns

* Load biomes from NMS instead of bukkit (#1200)

* Update adapters

* Update adapters

* Don't initialise BlockTypes when biomes aren't set up yet so all BiomeTypes.BIOME are no longer null thanks.

* Address some comments.

* rename layer -> sectionIndex to imply inclusivity

* Javadoctored.

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2021-08-17 22:13:51 +01:00
NotMyFault
5b2bd45d86
091200e1f80576175cfdf147928583b28275f437 2021-08-17 22:10:37 +02:00
dordsor21
f7161ea890
Update adapters 2021-08-17 18:45:08 +01:00
dordsor21
664cd4e33d
Preloader is null for spigot users 2021-08-17 18:06:57 +01:00
dordsor21
51eee01eef
Update adapters 2021-08-17 17:52:28 +01:00
dordsor21
347bd04065
Fix initialisation 2021-08-17 17:09:52 +01:00
dordsor21
4cae37fbbf
Add back extra angle mask prefixes 2021-08-17 17:07:37 +01:00
dordsor21
569fdc3861
Reimplement radius mask, fix wall mask 2021-08-17 17:03:25 +01:00
dordsor21
46f6395279
Improve mask parsing
- Fixes #1230
2021-08-17 17:02:11 +01:00
NotMyFault
f6676cf6a3
Follow up to 1ee4de0edf 2021-08-17 16:57:35 +02:00
dordsor21
0ffab8ee69
Add null check to preloader 2021-08-17 15:38:47 +01:00
renovate[bot]
1ee4de0edf
Update dependency gradle to v7.2 (#1229)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-17 16:21:09 +02:00
dordsor21
8c11ba7fea
Preload chunks up to the configured limit, cancel preloading on EditSession complete 2021-08-17 12:07:48 +01:00
dordsor21
da7aca8ef8
Add basic preloading (#1221) 2021-08-16 20:47:09 -04:00
dordsor21
d4d98708f9
Re-implement richer mask and transform parsing (#1223)
Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2021-08-16 09:03:06 +00:00
dordsor21
50137b31c4
Update adapters 2021-08-15 15:59:30 +01:00
dordsor21
c287739be7
Minecraft uses the global block palette if there are more than 8 bits per entry in a chunk section
- Fixes #1228
2021-08-14 14:29:57 +01:00
dordsor21
98673b5743
Update adapters 2021-08-13 11:59:24 +01:00
dordsor21
3c75ed7d46
javadoc 2021-08-13 11:51:05 +01:00
dordsor21
c65c72b249
Allow adapters to override World#getEntities to avoid AsyncCatcher
- Even if we access (cache) the entities synchronously, we'd then be doing stuff asynchronously so adapters can override this and either use the world#getEntities normally (pre 1.17) or get entities async anyway.
2021-08-13 11:44:18 +01:00
dordsor21
3e4f1d5cd8
Better Mathman#isInteger 2021-08-11 20:38:52 +01:00
dordsor21
00a6a2d917
Fix stash failure 2021-08-11 15:03:59 +01:00
dordsor21
3ba42df321
Use more MutableBlockVector3s 2021-08-11 14:56:10 +01:00
dordsor21
6f5430a940
Some cleanup of mutables 2021-08-11 14:00:12 +01:00
dordsor21
8928556c1d
Minor improvement to MathMan#isInteger 2021-08-11 12:32:46 +01:00
Pierre Maurice Schwang
7d3a9ff36d
Fixed Unit Tests (BlockVector3.isLongPackable) (#1168)
* Fixed Unit Tests (BlockVector3.isLongPackable)

* Re-enable tests for ci

* Address gh action dependency complaints

* Fix "invalid usage of tag &" for MinecraftVersion.java

* Simple StubServer for BukkitWorldTest.java

* Add parallelgzip to test runtime, fixed javadoc encoding, make gradlew executable and patch StubServer for latest spigot / paper release

* Move Javadoc UTF-8 to PlatformConfig.kt

* Revert "make gradlew executable"
Was required for act to run, but not required for GH actions - Weird behavior

* Mark upstream changes, move class + apply editorconfig

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
2021-08-10 09:31:37 +01:00
dordsor21
31b41235ac
Update adapters 2021-08-09 14:34:39 +01:00
NotMyFault
9ea5a94941
Use temurin for gh actions 2021-08-09 15:09:55 +02:00
NotMyFault
a1e6839cae
Improve jd of MinecraftVersion#getPackageVersion 2021-08-09 11:36:50 +02:00
Maddy Miller
e2b2feb7c5
Use MethodHandle for faster event bus (#1865)
* Use MethodHandle for faster event bus

* Implement hashCode/equals

* Apply review comments

* Bind to the object directly
2021-08-09 10:21:42 +01:00
dordsor21
57f7c93033
Fix history rollback
- Fixes #959
2021-08-08 19:35:57 +01:00
Maddy Miller
f06ba41f91
Fix Cycler tool not using full block data (#1868)
(cherry picked from commit 8ee45137aa5d7a3b80b661601ab14e48f13756ec)
2021-08-08 17:33:45 +01:00
dordsor21
6562f8adbd
Update adapters 2021-08-08 12:09:05 +01:00
dordsor21
08ebef2905
Break file to make git notice it 2021-08-08 12:08:55 +01:00
dordsor21
c58b143552
Update adapters to 3f6df1adee 2021-08-08 12:03:52 +01:00
Joseph Thomas
d10b038e84
Create SurfaceAngleMask (#1215) 2021-08-08 09:59:42 +00:00
dordsor21
2376ce8d9d
Add thickness to //hcyl and //br cylinder -h
- Closes #753
2021-08-08 10:02:58 +01:00
NotMyFault
75b888a9f0
Add missing translation keys 2021-08-08 01:52:28 +02:00
dordsor21
9af77c06b8
Fix ParallelQueueExtent#setBlocks(Region, <B extends BlockStateHolder>)#
- Fixes removeabove/removebelow
2021-08-07 17:38:09 +01:00
dordsor21
346223977d
Add javadoc comments to generateTree 2021-08-07 16:28:41 +01:00
dordsor21
e90b261196
Trees should be generated on the main thread
- Also remove warning when using tree tool
2021-08-07 16:19:41 +01:00
dordsor21
0d84967853
Fixes #1219 2021-08-07 16:12:03 +01:00
Aurélien
abaa347ad4
Fix major security bugs (3 brushes + superpickaxe)! (#1213)
* Fix major security bugs (3 brushes + superpickaxe)!
- Due to some recent changes, FAWE could edit everything in the world, no matter other plugin protections such as PS or WG.
- Fix superpickaxe allow to bypass protections => Fix SurvivalModeExtent not taking into account protections plugins due to breaking blocks naturally to get drops.

* Adress requests
- Revert some unsuitabe changes
- Add FAWE diff comments

* Clean imports

* Adress requests

Co-authored-by: NotMyFault <mc.cache@web.de>
2021-08-07 11:09:33 +02:00
Matt
14b3fd2085 Fixed parameter name 2021-08-05 17:38:44 -04:00
NotMyFault
14fc2dbf9b
Fix fawe-deprecation javadoc linking 2021-08-05 18:33:19 +02:00
NotMyFault
c468d22120
Fixes #1208 2021-08-05 15:55:20 +02:00
NotMyFault
3ccb5e0aed
Use translation message for brush assignment 2021-08-04 22:44:24 +02:00
NotMyFault
2bcf3eedf1
Add //br snow
Apparently an upstream addition we forgot to pull.
2021-08-04 22:29:43 +02:00
NotMyFault
45a8030aeb
Update Upstream
b9f0416 Use a Guava Cache instead of a ThreadLocal (1862)
2021-08-02 22:10:21 +02:00
NotMyFault
a5e84dcfea
Switch to version catalogs
- Closes #1204
- Switch to security advisory
- Move fawe-tests to fawe packages
2021-08-01 19:28:51 +02:00
NotMyFault
9f3a451ef6
Fixes #756 2021-07-31 14:18:04 +02:00
NotMyFault
678fb0a8b3
Fixes #1201 2021-07-30 01:31:25 +02:00
dordsor21
d62a1b5ad3
Always trim chunk GET in ChunkHolder
- Possibly something to do with #1169
2021-07-29 20:37:10 +01:00
NotMyFault
84b9dce6be
Move debug notes to logger factory 2021-07-29 21:11:23 +02:00
NotMyFault
17019ac723
Archive workflow artifacts 2021-07-28 15:04:49 +02:00
NotMyFault
69067fe8c8
Leave a note about (temporary) not undoable tree tools 2021-07-27 19:45:31 +02:00
NotMyFault
77e44c80c2
[ci skip] Update Javadocs URL 2021-07-27 01:13:26 +02:00
NotMyFault
e1d18dc896
(Temporarily) Include datapacks in debugpaste 2021-07-26 20:40:18 +02:00
NotMyFault
b4f9ade5bd
Fixes #1071 2021-07-26 17:05:54 +02:00
NotMyFault
39f6a2e17f
Update adapters 2021-07-26 01:14:01 +02:00
NotMyFault
92b4524dd6
Update Upstream
f414af5 Fix the offset mask forcing negation of itself (1656)
2021-07-26 00:48:38 +02:00
NotMyFault
aae5d037db
Reduce gh actions time by ~75% (~6 minutes) 2021-07-25 17:46:33 +02:00
NotMyFault
844691fa2c
Remove checkstyle files 2021-07-24 22:48:58 +02:00
NotMyFault
f479e32b5f
Update contributing url 2021-07-24 19:28:28 +02:00
dordsor21
8ba2eb3330
[CI-SKIP] update bug report template to reflect 1.17 FAWE 2021-07-24 17:17:43 +01:00
dordsor21
8c0195970b
Add and apply .editorconfig from P2 (#1195)
* Consistenty use javax annotations.
 - Unfortunately jetbrains annotations seem to be exposed transitively via core somewhere, but with the correct IDE settings, annotations can be defaulted to javax
 - Cleaning up of import order in #1195
 - Must be merged before #1195

* Add and apply .editorconfig from P2
 - Does not rearrange entries

* Address some comments

* add back some javadoc comments

* Address final comments

Co-authored-by: NotMyFault <mc.cache@web.de>
2021-07-24 16:34:05 +01:00
dordsor21
3b4beba7d6
Improve performance of various commands/actions
- Add chunk preloading to RegionVisitor if supplied with a suitable Extent
 - Where extents are used in masks, set EditSession as the extent as they are otherwise initialised with WorldWrapper that is very slow
 - Fixes #1073
2021-07-24 15:47:22 +01:00
dordsor21
f2ee2248e0
Consistenty use javax annotations. (#1197)
- Unfortunately jetbrains annotations seem to be exposed transitively via core somewhere, but with the correct IDE settings, annotations can be defaulted to javax
 - Cleaning up of import order in #1195
 - Must be merged before #1195

Co-authored-by: NotMyFault <mc.cache@web.de>
2021-07-24 15:52:08 +02:00
dordsor21
5e9535db41
Re-add shading/relocation of fastutils and add a dumb class because minimise doesn't scan worldedit-adapters 2021-07-24 14:12:59 +01:00
NotMyFault
46f2a202e6
Remove unneeded maven repos 2021-07-24 14:28:35 +02:00
dordsor21
b599d86a1c
Assume it's safe not to shade or relocate fastutils 2021-07-24 13:14:58 +01:00
dordsor21
8f55d3f9a4
update adapters 2021-07-24 13:14:19 +01:00
dordsor21
41f4aadf40
Update to 1.17.1 texture jar 2021-07-24 12:19:44 +01:00
dordsor21
d46af0136b
Fix nullable world in regions 2021-07-24 10:04:04 +01:00
dordsor21
39defaea5e
and reupdate adapters without a borked jar file because the hash wasn't different the first time round 2021-07-23 21:57:06 +01:00
dordsor21
c37ce767d7
update adapters 2021-07-23 21:54:49 +01:00
dordsor21
4341001a1c
Update adapters 2021-07-23 21:03:02 +01:00
dordsor21
0be8746c11
Add more directionals
- Fixes #1122
 - Levers and buttons can be flipped/rotated vertically
2021-07-23 20:15:22 +01:00
renovate[bot]
0d26dad397
Update dependency com.github.luben:zstd-jni to v1.5.0-4 (#1189)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-23 20:17:43 +02:00
NotMyFault
ae9c5f8490
Update adapters 2021-07-23 18:31:18 +02:00
NotMyFault
50ab8ad5c7
Feature/propagate diff and object cleanup (#1190)
* Feature/main/propagate diff annotations (#1187)

* 25% done

* More work

* More work

* 50%

* More work

* 75%

* 100% & cleanup

* Update adapters

* Squish squash, applesauce

commit 275ba9bd84
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:10:20 2021 +0200

    Update dependency com.comphenix.protocol:ProtocolLib to v4.7.0 (#1173)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 9fd8984804
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:09:29 2021 +0200

    Update dependency org.checkerframework:checker-qual to v3.16.0 (#1184)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 861fb45e5c
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 19:07:02 2021 +0100

    Fix #1075

commit 420c45a29a
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 18:48:21 2021 +0100

    Entity removal should be on the main thread as we're just passing through rather than doing chunk operations
     - Fixes #1164
     - Not working: butcher/remove history

commit 4d4db7dcd0
Author: SirYwell <hannesgreule@outlook.de>
Date:   Fri Jul 16 17:52:44 2021 +0200

    Make sure leaves category is loaded for heightmaps (fixes #1176)

commit c98f6e4f37
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:44:52 2021 +0100

    Do not allow generation commands to generate outside selection

commit 2485f5eccc
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:43:15 2021 +0100

    EditSession needs to override some Extent methods to ensure block changes are correctly set through the various extents
    Fixes #1152

commit d9418ec8ae
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 09:52:44 2021 +0100

    Undo part of 41073bb1a0
    Fixes #1178

* Update Upstream

fb1fb84 Fixed typo and grammar

* We don't support custom heights yet

* Casing inconsistency

* Address a few comments

* Address comments

* Don't refactor to AP classpath

* Document annotation style

* Refactoring & shade cleanup

* Address a few comments

* More work

* Resolve comments not being resolved yet

* Feature/main/propagate diff annotations (#1187) (#1194)

* Remove beta package, fix history packages, move classes out of object package

* Resolve comments not being resolved yet

* Remove beta package, fix history packages, move classes out of object package

Co-authored-by: NotMyFault <mc.cache@web.de>

* brushes should be under brush

* More refactoring
 - Filters/processors should be in the same place and are related to extents
 - Transforms are in `extent.transform` in upstream

* Move history classes under history

* Update adapters

Co-authored-by: dordsor21 <dordsor21@gmail.com>
2021-07-23 17:48:51 +02:00
dordsor21
ad102ab7a9
clipboard brush is supposed to be -o not -p 2021-07-23 11:27:14 +01:00
dordsor21
8e16acde1d
Fix error in clipboard brush switches 2021-07-23 09:54:30 +01:00
NotMyFault
39a3c83801
The CLI is not a plugin... but now it technically is? 2021-07-22 22:11:43 +02:00
dordsor21
6acd8498b2
Update adapters 2021-07-22 17:59:48 +01:00
dordsor21
1e49f59001
Much better hinge handling 2021-07-21 20:00:39 +01:00
dordsor21
1ec927f30c
Add check when obtaining BlockState from id to prevent edits losing large amounts of data 2021-07-20 20:49:47 +01:00
dordsor21
5f8addbb5b
Fix #1185
TODO: fix door hinge placement on rotate/flip sometimes
2021-07-20 20:49:13 +01:00
dordsor21
ca1744aa97
Likely fix for rotation issue
fixes #996
2021-07-19 20:33:50 +01:00
dordsor21
6ab927fa4d
Fix #1167 2021-07-19 20:28:36 +01:00
dordsor21
e6b18cf230
Run residence permission playerHas check on main thread 2021-07-18 13:18:55 +01:00
renovate[bot]
275ba9bd84
Update dependency com.comphenix.protocol:ProtocolLib to v4.7.0 (#1173)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-17 01:10:20 +02:00
renovate[bot]
9fd8984804
Update dependency org.checkerframework:checker-qual to v3.16.0 (#1184)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-17 01:09:29 +02:00
dordsor21
861fb45e5c
Fix #1075 2021-07-16 19:07:02 +01:00
dordsor21
420c45a29a
Entity removal should be on the main thread as we're just passing through rather than doing chunk operations
- Fixes #1164
 - Not working: butcher/remove history
2021-07-16 18:48:21 +01:00
SirYwell
4d4db7dcd0 Make sure leaves category is loaded for heightmaps (fixes #1176) 2021-07-16 17:54:18 +02:00
dordsor21
c98f6e4f37
Do not allow generation commands to generate outside selection 2021-07-16 10:44:52 +01:00
dordsor21
2485f5eccc
EditSession needs to override some Extent methods to ensure block changes are correctly set through the various extents
Fixes #1152
2021-07-16 10:43:15 +01:00
dordsor21
d9418ec8ae
Undo part of 41073bb1a0
Fixes #1178
2021-07-16 09:52:44 +01:00
NotMyFault
bcceadee6b
Propagate FAWE diff annotations down the bukkit module
- Minor upstream merge
2021-07-14 14:40:20 +02:00
NotMyFault
d7763c8542
Fixes #1181 2021-07-13 17:20:37 +02:00
NotMyFault
3cf283a65b
Update Upstream
954210d Fix //outline for non-cuboid regions (1827)
2021-07-13 10:59:04 +02:00
NotMyFault
6d360db753
Update adapters 2021-07-12 15:48:19 +02:00
dordsor21
41073bb1a0
More exact testing for scaling/flipping in AffineTransform and only combine transforms when not equal in ForwardExtentCopy
- Fixes #1162
 - Also fixes rotation in x/z axes
2021-07-10 19:47:39 +01:00
dordsor21
338be0ff31
Undo/redo should not be allowed outside allowed regions by default.
Fixes #949
2021-07-10 14:14:34 +01:00
NotMyFault
0434b86d8e
Feature/1.17.1 (#1172)
* Update adapters for 1.17.1

* Fixes #1074

* fd10efa56b51d915302d616302145c74c3f079ee

* Fix `//chunkinfo` message

* 9fc85704e9570304f1b336612039afc85bb17064

* 03b4437023

* JitPack decided to work again
2021-07-09 16:07:48 +02:00
NotMyFault
dd082d4f39
Fix loading on Java versions prior to 16
- Lazy workaround continuously JitPack outages
2021-07-09 11:34:07 +02:00
NotMyFault
457861b879
Update Upstream
1f21162 Ensure the SLF4J ban is being applied
2021-07-09 11:08:17 +02:00
NotMyFault
a183425642
Update Upstream
40ded93 Fix loading legacy invalid blocks
2021-07-06 13:13:54 +02:00
NotMyFault
22f11abce8
Remove unneeded maven repos 2021-07-05 22:26:14 +02:00
NotMyFault
35b1202951
Mitigate logger spam introduced in 256d7c4e5d
Touches #1122, #1166
2021-07-04 00:43:57 +02:00
renovate[bot]
4f4f3ea0aa
Update dependency gradle to v7.1.1 (#1165)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-03 11:34:30 +02:00
NotMyFault
c19b13adb4
[ci skip] We only need one 1.17 on issue templates 2021-07-02 14:24:49 +02:00
renovate[bot]
af1a3c3ddb
Update dependency net.kyori:adventure-nbt to v4.8.1 (#1161)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-01 22:57:52 +02:00
NotMyFault
876d84aec0
Fix typo 2021-07-01 22:49:10 +02:00
dordsor21
aa3ae63682
Feature/1.17 (#1120)
* start v6

* Update classes to v6 method signatures

* change rootVersion to signify p2v6 compat

* Use 16 as toolchain version but target 11 for build output

* add minimessage as api

* Require v6 and don't attempt to "setup" hook from FAWE

* Address comments

* *address /all/ comments

* FAWE classes should only act as a delegate

* Uppercase logger

* Settings for v6-hook have moved to P2-v6, remove unneeded if statements

* Rename classes to Delegate

* add whenDone task to setCuboids

* Remove bad spaces

* Fix plot swap

* Initial work on 1.17 support

* Remove data versions from the Bukkit adapters (#1507)

* Remove data versions from the Bukkit adapters

* Don't allow saving schematics without an adapter in place on Bukkit.

* Removed confusing line

(cherry picked from commit 2056218b4a8644836b1d127105dfa289e9cdbc1c)

* More progress

* Fix chunk sending

* Repackage from com.boydti to com.fastasyncworldedit.<module> (#1119)

* Preliminary work on repackaging

* Rename build artifacts matching our pattern

* Finish up repackaging

* Fix a few field accesses and old imports

* Dirty fix for chunks container ChunkSections outside of 0-15

* Correctly read from NibbleArrays for lighting

* Fix getSections and BlockMaterial for 1.17

* Fix writing blocks to the world.
 - The issue isn't the presence of a "-1" chunk, it's the constructor for ChunkSection requiring the layer (0 to 15) rather than the y chord

* Fix more field accesses

* More work towards 1.17

* Update Upstream

a57f66f Fix watchdog, add negative y support. (1782)

* Add azalea tree to `/tool tree`

* Don't define toolchain twice

* Repackage GriefDefender

* Relocate under new namespace

* Bye bye ecma left overs

* Add 1.17 to issue templates and instructions

* Move to adventure-nbt (#918)

* Initial work for adventure-nbt

* Some more FAWE specific stuff

* Fix erroneous deprecation check

* Workflow change

* Continued merging all adventure NBT related changes

* Continued merging all adventure NBT related changes

* Made a constructor public again

This needs to be public for BlockTransformExtent.java

* Finished converting all NBT data to adventure.

* Make this compile

* Fix conflicts

Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>

* Update adapters to 1.17

* Change build prefix to 1.17

* Move more nms classes to adapters

* Move left over nms classes

* Move Spigot 1.17 class

* Remove unneeded adapter loader code
The loader will find the appropriate class now itself

* Update adapters

* Update adapters

* Lazy fix tests

* Update adapters

* Update Upstream

43da91a Remove method reflection for getMinHeight in BukkitWorld. (1796)

* Relocate adventure-nbt under proper namespace

* Add LazyCompoundTag as a non-version-specific class to be used by adapters

* Better integration between old NBT and Adventure NBT - begin fixing the issues seen recently

* Correctly NBT conversion method

* LazyCompoundTags should actually be overriding and correctly returning a CompoundBinaryTag.

* Update worldedit-adapters
Fixes #1141

* Remove unnecessary massive lag machine

* Refactor apply to applyBlock in subclasses

* applyBlock should be overriden by all subclasses.
Default apply to applyBlock

* Closes #1130 Closes #1132

* Squashed commit of the following:

commit a9bfa1a07c77083c844a0c3ba62f4bd94bed107c
Author: NotMyFault <mc.cache@web.de>
Date:   Sun Jun 27 21:53:21 2021 +0200

    [ci skip] Update gradle wrapper validation

commit aa7471f95317d28a16f62e4b200de8d0fea2fa95
Author: Matthew Miller <mnmiller1@me.com>
Date:   Sat Oct 10 15:49:13 2020 +1000

    Add ^x,y,z relative offset support to the offset parser (#1545)

    * Add ^x,y,z relative offset support to the offset parser

    * Wrap in a try-catch

    (cherry picked from commit 28bdf7ff9254bbc85bb4f5f792b303943a3930a8)

* Add `fawe.error.schematic.not.found` translation key

* Update Upstream

728a152 Skip notify if chunk section doesn't exist (1794)

* Fixed #1157

* Add a null check to prevent NPE in nbt code

* Update adapters

* Update Upstream

fbb047a Optimize legacy schematic loading (1808)

* Hurr durr I don't want to update Java

* Update Upstream

0790e6e Fix CLI Mess (1811)

* Fixes #1160

* Expose minimessage transitively thru PlotSquared

Touches #32

* [ci skip] Remove unneeded maven repository

* Steal tab completion from PlotSquared for P2 related commands

* Don't error on startup when building locally

Co-Authored-By: goldfishapp <8278196+goldfishapp@users.noreply.github.com>

* [ci skip] Update gh actions to Java 16

* Update textures to grab 1.17 jar

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: SirYwell <hannesgreule@outlook.de>
Co-authored-by: Matthew Miller <mnmiller1@me.com>
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
Co-authored-by: goldfishapp <8278196+goldfishapp@users.noreply.github.com>
2021-07-01 22:16:25 +02:00
Matt
b0c0689887
Added 1.17 to the bug template. 2021-06-26 01:00:25 -04:00
NotMyFault
78acb857da
Closes #1129 Closes #1128 2021-06-19 10:17:43 +02:00
dordsor21
a0e84d7a44
Fix superpickaxe item dropping
Fixes #1079
2021-06-18 23:48:23 +01:00
NotMyFault
7af06a533b
Split up worldedit.anyblock and worldedit.anyblock.nbt for specific nbt operations 2021-06-18 20:58:10 +02:00
dordsor21
391869cf3a
Fix up LimitExtent
- Correctly handle block state limit checks.
- Don't quash exceptions thrown in a region operation by having a "max-fails" check that can only be hit once....
Fixes #1127
2021-06-18 18:00:42 +01:00
NotMyFault
96ed367420
Closes #1121 2021-06-18 01:01:30 +02:00
renovate[bot]
17c19766f7
Update dependency gradle to v7.1 (#1124)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-17 13:00:24 -04:00
NotMyFault
79e8755d93
Update Upstream
eb7b79c Use require instead of strictly to reduce problems with mojang/bukkit updates (1787)
2021-06-17 10:44:19 +02:00
NotMyFault
0af60e5680
Added support for GriefDefender (#1123) 2021-06-17 10:37:53 +02:00
dordsor21
256d7c4e5d
Temporary fix for #1122 2021-06-14 06:34:05 +01:00
dordsor21
d015e6b270
Also synchronise when loading sections forcefully 2021-06-12 15:09:02 +01:00
renovate[bot]
8836d1d75c
Update dependency org.mockito:mockito-core to v3.11.1 (#1118)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
2021-06-11 17:20:24 +02:00
dordsor21
b796106dd7
Add directionals for chests and slabs "type" block state
Fixes #987
2021-06-11 15:25:52 +01:00
dordsor21
da264b52e1
Fix #1116 2021-06-11 15:05:52 +01:00
dordsor21
f6c87b6726
Add null check to creating default NBT data 2021-06-10 19:59:17 +01:00
dordsor21
717a1b5db4
Replace ImmutableBaseBlock with BlanketBaseBlock
- ImmutableBaseBlock is no longer needed as NBT was made immutable previously
 - BlanketBaseBlock represents to masks that the block has NBT, but does not need to match a specific state
 - Allow FuzzyBlockState to create BaseBlocks without NBT data (fixed tab completion issues)
2021-06-10 19:47:34 +01:00
renovate[bot]
e11a2d7f6d
Update dependency com.github.luben:zstd-jni to v1.5.0-2 (#1113)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-10 17:37:15 +02:00
dordsor21
1fa5f4d725
Begin fixing layer brush
- Required new argument parser, which should ultimately be made into a singe blockstate parser for best results, and proper tab-completion
 - The layer brush itself is broken because of the changes to internal block retrieval from legacy
2021-06-10 16:19:23 +01:00
dordsor21
7ef8b2f95e
Create default TileEntity data where required.
Fixes #1093
Fixes #1042
2021-06-10 13:39:36 +01:00
dordsor21
71130025e8
Allow ^ mask to be used between blocks that may have different properties, only keeping the shared properties
Fixes #1092
2021-06-10 12:46:19 +01:00
dordsor21
dd217fcb70
Don't bother trying to use a clipboard when clearing plots.
Fixes #1088
2021-06-09 17:45:57 +01:00
NotMyFault
09b2cfef56
Closes #1107 2021-06-08 23:53:19 +02:00
renovate[bot]
bae592bf91
Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.5 (#1108)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-08 23:50:45 +02:00
renovate[bot]
75935f91e9
Update dependency com.github.luben:zstd-jni to v1.5.0-1 (#1106)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-08 23:46:46 +02:00
dordsor21
f6af9925e8
Char block null check (#1030)
**Add a null-check to CharBlocks FULL section layer-retrieval.**
 - It is possible to trim CharBlocks whilst it is attempting to read data due to the batching of chunks to help reduce memory
 - This is done when the number of chunks sitting loaded in memory with having been "submitted" to the queue for writing to disk becomes high
 - Seconday operations such as heightmap processing and lighting will quickly load chunks, meaning many chunks are submitted early
 - This leads to much higher chances of the chunk being submitted and subsequently trimmed given heightmap and light processing is done layer-by-layer over many chunks, rather than chunk-by-chunk - thus leading to NPEs.
 - By adding synchronisation to and around only the specific sections when loading/updating, and not blocking the whole chunk, many access can still be thread-safe without causing deadlocks
 - This allows removal of lots of the needless and very-slowing synchronisation on get**Block** methods

**Remove much of the synchronisation from ChunkHolder**
 - We shouldn't be synchronising with call() and safety should be added elsewhere. (plus it's making edits very very slow when queue target size is hit)
 - Also remove much of synchronisation because we've added the null-check and section-specific synchronisation to CharBlocks
 
**Some QOL/thread-safe data access changes**
- Replaces the Array#clone seen in the get blocks classes with System#arraycopy as deep cloning is not required, and is also slower than arraycopy
- Add System#arraycopy when accessing chunk section data via history to ensure it is not altered whilst being written
- Renaming EMPTY to empty means it is not implied to be a static variable

Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1028
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1025
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1089
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1091
Fixes https://github.com/IntellectualSites/FastAsyncWorldEdit/issues/1097
2021-06-08 14:28:16 +00:00
dordsor21
1cd2d8d121
Send before history is acttually safer at the moment
- avoids deadlocks
2021-06-08 14:15:43 +01:00
NotMyFault
ef5211d5b5
Update Wiki link 2021-06-06 21:17:24 +02:00
SirYwell
e40a657faf Remove unused imports 2021-06-05 20:38:53 +02:00
SirYwell
798e18ecc2 Look up BlockBase.Info field in actual class instead of subclass 2021-06-05 20:32:09 +02:00
NotMyFault
2bdf6ae18a
Leave a proper warning if you install WE alongside FAWE 2021-06-05 20:01:06 +02:00
NotMyFault
75fbe654ee
Update Upstream
0036e06 Alter the CUI lifecycle to be more consistent and reliable (1633)
2021-06-05 11:27:27 +02:00
NotMyFault
d1af6c38e7
Update Upstream
9516002 Register platforms and commands in a more proper way (1766)
2021-06-05 10:27:38 +02:00
renovate[bot]
f139088b6e
Update dependency org.mockito:mockito-core to v3.11.0 (#1103)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-04 09:07:50 +02:00
MattBDev
6bfc3ceb95 Removed cast to ResettableExtent in for loop.
I have no idea why we were casting it when all objects in the loop were ResettableExtents in the first place.
2021-06-03 17:59:51 -04:00
renovate[bot]
c87a19da5a
Update dependency org.checkerframework:checker-qual to v3.14.0 (#1102)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-03 00:31:30 +02:00
MattBDev
7f51d8374b Merge remote-tracking branch 'origin/main' 2021-06-02 17:27:46 -04:00
MattBDev
930b9b07d5 Fixed raw class usage in DistrFilter 2021-06-02 17:27:37 -04:00
NotMyFault
46ed9a2d67
Include classloader in extend debug message 2021-06-02 17:27:18 +02:00
NotMyFault
b599769f8c
Fixes #1098 2021-05-30 23:49:46 +02:00
Hannes Greule
53681ccc59
Feature/unsafe over reflections (#1082)
* Use Unsafe to replace Lock

* Start cleaning up everything that has to do with CleanableThreadLocal

* Make cancellation work

Co-authored-by: NotMyFault <mc.cache@web.de>
2021-05-28 18:47:46 -04:00
renovate[bot]
04610822a2
Update dependency org.jetbrains:annotations to v21 (#1084)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-24 12:01:29 +02:00
NotMyFault
cbe5cd4eb3
Move Fawe commands to Captions 2021-05-24 11:36:37 +02:00
NotMyFault
d2dee87ab9
Update Upstream
5a7cbfd Fix selecting at 0,0,0 or radius 0 cyl/ellipse (1734)
2021-05-24 10:52:58 +02:00
NotMyFault
b7f595cc50
Remove redundant tab from translation file 2021-05-23 23:39:00 +02:00
NotMyFault
8d35963171
Address dead Component imports 2021-05-23 23:35:08 +02:00
NotMyFault
106f9aed79
Address requested changes
- 4534154894 (r50694638)
- 4c1d0bc9a6 (r50694886)
2021-05-23 23:24:18 +02:00
NotMyFault
d48808f111
Fixes #1072 2021-05-22 17:33:42 +02:00
NotMyFault
a7cbf1dd0a
Elaborate where config changes can be applied to 2021-05-19 23:51:42 +02:00
SirYwell
71f7103edd Always use Unsafe to clean ByteBuffer 2021-05-15 15:27:28 +02:00
NotMyFault
706ac35063
Update GitHub actions matching latest Java requirements 2021-05-14 23:46:49 +02:00
Matt
aa0ad16a1b
Update to Gradle 7 (#1078) 2021-05-14 23:42:37 +02:00
1689 geänderte Dateien mit 234196 neuen und 78563 gelöschten Zeilen

1013
.editorconfig Normale Datei

Datei-Diff unterdrückt, da er zu groß ist Diff laden

2
.github/CODEOWNERS vendored
Datei anzeigen

@ -1 +1 @@
* @IntellectualSites/fawe-team
* @IntellectualSites/fastasyncworldedit-team

12
.github/FUNDING.yml vendored
Datei anzeigen

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: [NotMyFault, dordsor21, SirYwell]
patreon: IntellectualSites # Replace with a single Patreon username
open_collective: IntellectualSites
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://www.paypal.me/AlexanderBrandes # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

Datei anzeigen

@ -7,7 +7,8 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this bug report for FastAsyncWorldEdit! Fill out the following form to your best ability to help us fix the problem.
Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit/wiki).
Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/fastasyncworldedit-documentation/).
Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://github.com/IntellectualSites/FastAsyncWorldEdit/security/policy) GitHub form!
- type: dropdown
attributes:
@ -17,8 +18,6 @@ body:
options:
- Paper
- Spigot
- Tuinity
- Purpur
validations:
required: true
@ -28,8 +27,11 @@ body:
description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first.
multiple: false
options:
- '1.16.5'
- '1.15.2'
- '1.20.1'
- '1.20'
- '1.19.4'
- '1.18.2'
- '1.17.1'
validations:
required: true
@ -80,7 +82,7 @@ body:
attributes:
label: Fawe Version
description: What version of Fawe are you running? (`/version FastAsyncWorldEdit`)
placeholder: "For example: FastAsyncWorldEdit version 1.16-606;4a6af71"
placeholder: "For example: FastAsyncWorldEdit version 2.0.0-SNAPSHOT-1"
validations:
required: true
@ -91,7 +93,7 @@ body:
options:
- label: I have included a Fawe debugpaste.
required: true
- label: I am using the newest build from https://ci.athion.net/job/FastAsyncWorldEdit-1.16/ and the issue still persists.
- label: I am using the newest build from https://ci.athion.net/job/FastAsyncWorldEdit/ and the issue still persists.
required: true
- type: textarea

Datei anzeigen

@ -4,5 +4,5 @@ contact_links:
url: https://discord.gg/intellectualsites
about: Our support Discord, please ask questions and seek support here.
- name: FastAsyncWorldEdit Wiki
url: https://github.com/IntellectualSites/FastAsyncWorldEdit/wiki
url: https://intellectualsites.github.io/fastasyncworldedit-documentation/
about: Look at the wiki page for answers for setup instructions command syntax and more.

Datei anzeigen

@ -7,7 +7,7 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this feature request for FastAsyncWorldEdit! Fill out the following form to your best ability to help us understand your feature request and greately improve the change of it getting added.
For anything else than a feature request, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit/wiki).
For anything else than a feature request, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/fastasyncworldedit-documentation/).
- type: textarea
attributes:

Datei anzeigen

@ -1,19 +0,0 @@
## Overview
<!-- Please describe which issue this Pull Request targets
If there is no issue, please create one so we can look into it before approving your PR.
You can do so here: https://github.com/IntellectualSites/FastAsyncWorldEdit/issues
-->
<!-- Remove the brackets around the issue to connect your pull request with the issue it resolves -->
**Fixes #{issue number}**
## Description
<!-- Please describe what you have changed -->
## Checklist
<!-- Make sure you have completed the following steps (put an "X" between of brackets): -->
- [] I included all information required in the sections above
- [] I tested my changes and approved their functionality
- [] I ensured my changes do not break other parts of the code
- [] I read and followed the [contribution guidelines](https://github.com/IntellectualSites/FastAsyncWorldEdit/blob/1.16/CONTRIBUTING.md)

1
.github/release-drafter.yml vendored Normale Datei
Datei anzeigen

@ -0,0 +1 @@
_extends: .github

35
.github/renovate.json vendored Normale Datei
Datei anzeigen

@ -0,0 +1,35 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
":semanticCommitsDisabled"
],
"automerge": true,
"ignoreDeps": [
"guava",
"com.google.guava:guava",
"rhino-runtime",
"org.antlr",
"antlr4-runtime",
"fastutil",
"it.unimi.dsi:fastutil",
"auto-value-annotations",
"auto-value",
"com.google.code.gson:gson",
"net.fabricmc:fabric-loader",
"net.fabricmc.fabric-api:fabric-api",
"com.github.luben:zstd-jni",
"org.jetbrains.kotlin.jvm",
"log4j",
"org.apache.logging.log4j:log4j-api",
"org.apache.logging.log4j:log4j-bom",
"org.apache.logging.log4j:log4j-slf4j-impl",
"org.apache.logging.log4j:log4j-core",
"org.bstats:bstats-sponge",
"org.spongepowered:spongeapi",
"org.yaml:snakeyaml"
],
"labels": ["Renovate"],
"rebaseWhen": "conflicted",
"schedule": ["on the first day of the month"]
}

2
.github/stale.yml vendored
Datei anzeigen

@ -1,4 +1,4 @@
daysUntilStale: 60
daysUntilStale: 30
daysUntilClose: 7
only: issues
exemptLabels:

Datei anzeigen

@ -0,0 +1,28 @@
name: Announce release on discord
#on:
# workflow_run:
# workflows: ["Upload release assets"]
# types:
# - completed
jobs:
send_announcement:
runs-on: ubuntu-latest
steps:
- name: send custom message with args
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
DISCORD_USERNAME: FastAsyncWorldEdit Release
DISCORD_AVATAR: https://raw.githubusercontent.com/IntellectualSites/Assets/main/plugins/FastAsyncWorldEdit/FastAsyncWorldEdit.png
uses: Ilshidur/action-discord@0.3.2
with:
args: |
"<@&525015715300900875> <@&706463154804097105> <@&671372968462516240>"
""
"<:fawe:730750370984493106> **FastAsyncWorldEdit ${{ github.event.release.tag_name }} has been released!**"
""
"Click here to view changelog: https://github.com/IntellectualSites/FastAsyncWorldEdit/releases/tag/${{ github.event.release.tag_name }}"
""
"The download is available at:"
"- Spigot: <https://www.spigotmc.org/resources/13932/>"
"- Modrinth: <https://modrinth.com/plugin/fastasyncworldedit/version/${{ github.event.release.tag_name }}>"
"- CurseForge: <https://www.curseforge.com/minecraft/bukkit-plugins/fawe>"

27
.github/workflows/build-pr.yml vendored Normale Datei
Datei anzeigen

@ -0,0 +1,27 @@
name: Build PR
on: [pull_request]
jobs:
build_pr:
if: github.repository_owner == 'IntellectualSites'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
cache: gradle
java-version: 17
- name: Build on ${{ matrix.os }}
run: ./gradlew build -s
- name: Archive artifacts
uses: actions/upload-artifact@v3
with:
name: FastAsyncWorldEdit-SNAPSHOT
path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar

Datei anzeigen

@ -1,58 +1,78 @@
name: "build"
on: ["pull_request", "push"]
name: Build
on:
push:
branches:
- main
jobs:
build:
strategy:
matrix:
java: ["8", "11"]
os: ["ubuntu-latest"]
runs-on: "${{ matrix.os }}"
if: github.repository_owner == 'IntellectualSites'
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: "actions/checkout@v2.3.4"
- name: "Setup JDK ${{ matrix.java }}"
uses: "actions/setup-java@v2"
with:
distribution: "adopt"
java-version: "${{ matrix.java }}"
- name: "Cache Gradle"
uses: "actions/cache@v2.1.4"
with:
path: |
"~/.gradle/caches"
"~/.gradle/wrapper"
key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}"
restore-keys: |
"${{ runner.os }}-gradle-"
- name: "Cache Local Maven Repository"
uses: "actions/cache@v2.1.4"
with:
path: "~/.m2/repository"
key: "${{ runner.os }}-${{ matrix.java }}-maven-${{ hashFiles('**/pom.xml') }}"
restore-keys: |
"${{ runner.os }}-${{ matrix.java }}-maven-"
- name: "Cache BuildTools Decompiled Code"
uses: "actions/cache@v2.1.4"
with:
path: "$GITHUB_WORKSPACE/work"
key: "${{ runner.os }}-buildtools"
restore-keys: |
"${{ runner.os }}-buildtools"
- name: "Test Enviornment"
run: "echo $GITHUB_WORKSPACE"
- name: "Download BuildTools"
run: "wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
- name: "Run BuildTools"
run: "java -jar BuildTools.jar --rev 1.16.5"
- name: "Clean Build"
run: "./gradlew clean build sourcesJar javadocJar"
- name: Cleanup Gradle Cache
# Remove some files from the Gradle cache, so they aren't cached by GitHub Actions.
# Restoring these files from a GitHub Actions cache might cause problems for future builds.
run: |
rm -f ~/.gradle/caches/modules-2/modules-2.lock
rm -f ~/.gradle/caches/modules-2/gc.properties
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
cache: gradle
java-version: 17
- name: Clean Build
run: ./gradlew clean build --no-daemon
- name: Determine release status
if: ${{ runner.os == 'Linux' }}
run: |
if [ "$(./gradlew properties | awk '/^version:/ { print $2; }' | grep '\-SNAPSHOT')" ]; then
echo "STATUS=snapshot" >> $GITHUB_ENV
else
echo "STATUS=release" >> $GITHUB_ENV
fi
- name: Publish Release
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
- name: Publish Snapshot
if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run: ./gradlew publishToSonatype
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
- name: Publish core javadoc
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
uses: cpina/github-action-push-to-another-repository@main
env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with:
source-directory: 'worldedit-core/build/docs/javadoc'
destination-github-username: 'IntellectualSites'
destination-repository-name: 'fastasyncworldedit-javadocs'
user-email: ${{ secrets.USER_EMAIL }}
target-branch: main
target-directory: worldedit-core
- name: Publish bukkit javadoc
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
uses: cpina/github-action-push-to-another-repository@main
env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with:
source-directory: 'worldedit-bukkit/build/docs/javadoc'
destination-github-username: 'IntellectualSites'
destination-repository-name: 'fastasyncworldedit-javadocs'
user-email: ${{ secrets.USER_EMAIL }}
target-branch: main
target-directory: worldedit-bukkit
- name: Archive Artifacts
uses: actions/upload-artifact@v3
with:
name: FastAsyncWorldEdit-Bukkit-SNAPSHOT
path: worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar
- name: Publish to Modrinth
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
run: ./gradlew modrinth
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}

36
.github/workflows/codeql.yml vendored Normale Datei
Datei anzeigen

@ -0,0 +1,36 @@
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['java']
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
cache: gradle
java-version: 17
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

17
.github/workflows/release-drafter.yml vendored Normale Datei
Datei anzeigen

@ -0,0 +1,17 @@
name: draft release
on:
push:
branches:
- main
pull_request:
types: [opened, reopened, synchronize]
pull_request_target:
types: [opened, reopened, synchronize]
jobs:
update_release_draft:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Datei anzeigen

@ -0,0 +1,26 @@
name: Upload release assets
on:
release:
types: [published]
jobs:
upload_asset:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
cache: gradle
java-version: 17
- name: Clean Build
run: ./gradlew clean build --no-daemon
- name: Upload Release Assets
uses: AButler/upload-release-assets@v2.0
with:
files: 'worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-*.jar'
repo-token: ${{ secrets.GITHUB_TOKEN }}
release-tag: ${{ github.event.release.tag_name }}

Datei anzeigen

@ -1,12 +0,0 @@
name: "validate gradle wrapper"
on: ["pull_request", "push"]
jobs:
build:
runs-on: "ubuntu-18.04"
steps:
- name: "Checkout Repository"
uses: "actions/checkout@v2.3.4"
- name: "Validate Gradle Wrapper"
uses: "gradle/wrapper-validation-action@v1.0.3"

8
.gitignore vendored
Datei anzeigen

@ -2,7 +2,8 @@
.project
.settings
eclipse
.idea
/.idea/*
!/.idea/icon.svg
*.iml
*.ipr
*.iws
@ -23,7 +24,6 @@ logs/
worldedit-bukkit/src/main/java/ignore/*
todo.txt
mvn/*
docs/
*.sh
# i18n
worldedit-core/src/main/resources/lang/*
@ -31,3 +31,7 @@ worldedit-core/src/main/resources/lang/*
**/*.eml
/worldedit-core/FastAsyncWorldEdit.worldedit-core.eml
/worldedit-core/.factorypath
.DS_Store
### Run server ignore
run-*

112
.idea/icon.svg Normale Datei
Datei anzeigen

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
id="svg2"
xml:space="preserve"
width="512"
height="512"
viewBox="0 0 512 512.00001"
sodipodi:docname="icon.svg"
inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18">
<path
d="M 0,2500 H 3000 V 0 H 0 Z"
id="path16" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18-2"><path
d="M 0,2500 H 3000 V 0 H 0 Z"
id="path16-1" /></clipPath></defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1440"
inkscape:window-height="872"
id="namedview4"
inkscape:pagecheckerboard="0"
showgrid="false"
width="512px"
inkscape:snap-others="false"
inkscape:zoom="0.2263301"
inkscape:cx="797.50773"
inkscape:cy="547.87234"
inkscape:window-x="0"
inkscape:window-y="28"
inkscape:window-maximized="0"
inkscape:current-layer="g10" />
<g
id="g10"
inkscape:groupmode="layer"
inkscape:label="FastAsyncWorldEdit"
transform="matrix(1.3333333,0,0,-1.3333333,0,3333.3333)">
<g
id="g12"
transform="matrix(0.17875858,0,0,0.17875858,-78.817913,2093.6589)"><g
id="g14"
clip-path="url(#clipPath18-2)"><g
id="g20"
transform="translate(1643.0798,2025.9724)"><path
d="m 0,0 c 34.839,11.026 70.869,18.313 107.28,21.408 18.861,-48.96 46.604,-93.992 77.514,-136.19 49.794,-66.487 110.495,-124.616 178.34,-172.506 78.156,-55.366 165.481,-97.254 256.496,-126.783 83.229,-27.124 169.601,-44.008 256.592,-53.295 -1.047,-153.146 -64.344,-303.076 -167.124,-415.762 -47.77,-52.914 -103.208,-99.136 -164.838,-135.047 -91.873,-53.843 -197.557,-83.896 -304.076,-85.705 -10.764,101.16 -31.91,201.534 -67.273,297.051 -28.243,76.537 -65.678,149.835 -112.853,216.465 -47.865,67.583 -105.685,128.332 -172.125,177.888 -42.102,31.22 -87.348,58.939 -136.404,77.823 3.834,48.628 15.479,96.636 33.625,141.906 19.169,46.769 46.96,90.968 85.752,123.926 C -91.706,-36.816 -46.722,-14.717 0,0"
style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path22" /></g><g
id="g24"
transform="translate(1887.3362,1969.7008)"><path
d="m 0,0 c 20.837,19.313 56.319,19.718 77.228,0.333 32.243,-32.053 64.272,-64.296 96.492,-96.373 17.313,-17.384 20.766,-46.27 8.93,-67.631 -9.073,-15.431 -23.813,-26.314 -35.744,-39.388 -37.339,25.29 -72.917,53.105 -106.637,83.015 -17.122,17.074 -36.316,32.076 -51.771,50.794 -8.525,10.74 -20.432,18.813 -26.457,31.458 C -25.242,-25.242 -12.788,-12.431 0,0"
style="fill:#062f4c;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path26" /></g><g
id="g28"
transform="translate(1463.3822,1497.8577)"><path
d="m 0,0 c -4.644,-0.786 -9.097,-2.786 -12.383,-6.168 -292.384,-292.645 -585.053,-585.029 -877.484,-877.627 -6.74,-6.382 -14.741,-13.145 -14.717,-23.337 -1.262,-12.383 8.668,-21.242 17.384,-28.291 9.882,-6.882 24.552,-4.215 32.481,4.525 293.718,293.693 587.411,587.387 881.104,881.104 10.74,9.049 12.241,27.219 1.929,37.101 C 21.48,-4.406 11.264,2.715 0,0 M -994.266,-946.234 C -647.088,-599.055 -299.885,-251.901 47.27,95.326 84.134,65.44 116.592,30.505 147.502,-5.382 c 23.266,-26.814 43.579,-55.986 64.749,-84.419 -346.679,-346.584 -693.215,-693.286 -1039.941,-1039.822 -20.623,-21.98 -58.439,-23.599 -80.514,-2.953 -32.172,32.149 -64.321,64.345 -96.493,96.493 -16.503,16.741 -19.932,44.007 -9.882,64.963 4.572,9.907 12.692,17.384 20.313,24.886"
style="fill:#062f4c;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path30" /></g><g
id="g32"
transform="translate(1827.8735,1911.1907)"><path
d="M 0,0 C 7.859,6.168 14.288,13.883 21.504,20.718 27.529,8.073 39.435,0 47.961,-10.74 c 15.455,-18.717 34.648,-33.72 51.77,-50.794 33.721,-29.91 69.298,-57.725 106.638,-83.015 -9.383,-9.263 -18.67,-18.67 -28.029,-27.957 C 110.495,-124.617 49.794,-66.488 0,0"
style="fill:#081d2d;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path34" /></g><g
id="g36"
transform="translate(1531.0129,1613.4966)"><path
d="m 0,0 c 66.44,-49.556 124.26,-110.305 172.125,-177.888 -9.145,-9.192 -18.36,-18.336 -27.505,-27.552 -21.17,28.433 -41.483,57.605 -64.749,84.419 C 48.961,-85.134 16.503,-50.199 -20.361,-20.313 -13.574,-13.55 -6.811,-6.763 0,0"
style="fill:#081d2d;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path38" /></g><g
id="g40"
transform="translate(2519.302,1558.6062)"><path
d="M 0,0 C 21.408,-2.334 42.865,-3.763 64.321,-5.596 73.179,-84.086 63.178,-164.123 40.126,-239.47 3.072,-360.657 -72.393,-468.319 -168.696,-549.976 c -101.446,-87.038 -230.349,-142.429 -363.943,-152.121 -32.72,-2.548 -65.726,-2.453 -98.279,1.786 -0.857,21.313 -3.072,42.555 -5.12,63.797 106.518,1.81 212.203,31.862 304.076,85.705 61.63,35.911 117.068,82.133 164.838,135.047 C -64.344,-303.076 -1.048,-153.145 0,0"
style="fill:#6fc4ee;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path42" /></g><g
id="g44"
transform="translate(1463.3822,1497.8577)"><path
d="m 0,0 c 11.264,2.715 21.48,-4.406 28.314,-12.693 10.312,-9.882 8.811,-28.052 -1.929,-37.101 -293.693,-293.717 -587.386,-587.411 -881.104,-881.104 -7.929,-8.74 -22.599,-11.407 -32.481,-4.525 -8.716,7.049 -18.646,15.908 -17.384,28.291 -0.024,10.192 7.977,16.955 14.717,23.337 292.431,292.598 585.1,584.982 877.484,877.627 C -9.097,-2.786 -4.644,-0.786 0,0"
style="fill:#105677;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path46" /></g></g></g></g>
</svg>

Nachher

Breite:  |  Höhe:  |  Größe: 6.3 KiB

54
Annotation-Explanation.adoc Normale Datei
Datei anzeigen

@ -0,0 +1,54 @@
:toc:
:toclevels: 2
= Fawe annotations explained
If we have modified parts of the WorldEdit codebase, we considered annotating it with different styles of comments, which
are explained in this document.
== In-line annotations
[source,java]
-----------------
public static Player adapt(com.sk89q.worldedit.entity.Player player) {
//FAWE start - Get player from PlayerProxy instead of BukkitPlayer if null
player = PlayerProxy.unwrap(player);
return player == null ? null : ((BukkitPlayer) player).getPlayer();
//FAWE end
}
-----------------
The `-sources` jar retains comments, if you add the FAWE API to your maven or gradle project, you can view differences between the projects with ease.
Behind the `//FAWE start - ` you can find a comment what has been changed and why it has been changed.
== Block annotations
[source,java]
-----------------
//FAWE start
@Override
public void setPermission(String permission, boolean value) {
}
//FAWE end
-----------------
Annotations can cover whole methods or go beyond the method and wrap around several added methods.
== Package annotations
Class additions are added under the `com.fastasyncworldedit` namespace, but sometimes classes need to be added in package private.
If that is done, you can find a `package-info.java` file within the package affected that outlines FAWE added classes:
[source,java]
-----------------
/**
* The following classes are FAWE additions:
*
* @see com.sk89q.worldedit.world.block.BlockTypesCache
*/
package com.sk89q.worldedit.world.block;
-----------------
== Undocumented annotations
Specific changes are not annotated:
* `com.fastasyncworldedit.core.configuration.Caption` in `com.sk89q.worldedit` packages have been changed from
`com.sk89q.worldedit.util.formatting.text.Text` to allow the usage of color codes for messages.
* Certain Log4J loggers have been adjusted to use the proper format of placeholders.

Datei anzeigen

@ -1,12 +1,14 @@
Compiling
=========
:toc:
:toclevels: 2
You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 8 installed. Gradle will download JDK 8 specifically if needed,
= Compiling
You can compile FastAsyncWorldEdit as long as you have some version of Java greater than or equal to 17 installed. Gradle will download JDK 17 specifically if needed,
but it needs some version of Java to bootstrap from.
Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 8.
Note that if you have JRE 8 installed, Gradle will currently attempt to use that to compile, which will not work. It is easiest to uninstall JRE 8 and replace it with JDK 17.
You can get the JDK 8 [here](https://adoptopenjdk.net/?variant=openjdk8&jvmVariant=hotspot).
You can get the JDK 17 link:https://adoptium.net/[here] from Adoptium.
The build process uses Gradle, which you do *not* need to download. FastAsyncWorldEdit is a multi-module project with three active modules:
@ -14,23 +16,19 @@ The build process uses Gradle, which you do *not* need to download. FastAsyncWor
* `worldedit-bukkit` is the Bukkit plugin
* `worldedit-cli` is the command line interface
## To compile...
== To compile...
### NMS
FastAsyncWorldEdit uses NMS (net.minecraft.server) code in a variety of spots. NMS is not distributed via maven and therefore FastAsyncWorldEdit may not build without errors if you didn't install it into your local repository beforehand.
You can do that by either running Spigot's [BuildTools](https://www.spigotmc.org/wiki/buildtools/) targeting the versions needed or using Paper's paperclip with `java -Dpaperclip.install=true -jar paperclip.jar`.
### On Windows
=== On Windows
1. Shift + right-click the folder with FastAsyncWorldEdit's files and click "Open command prompt".
2. `gradlew clean build`
### On Linux, BSD, or Mac OS X
=== On Linux, BSD, or Mac OS X
1. In your terminal, navigate to the folder with FastAsyncWorldEdit's files (`cd /folder/of/fawe/files`)
2. `./gradlew clean build`
## Then you will find...
== Then you will find...
You will find:
@ -38,14 +36,14 @@ You will find:
* FastAsyncWorldEdit for Bukkit in **worldedit-bukkit/build/libs**
* the CLI version in **worldedit-cli/build/libs**
If you want to use FastAsyncWorldEdit, use the `FastAsyncWorldEdit-1.16-<commitHash>` version obtained in **worldedit-bukkit/build/libs**.
If you want to use FastAsyncWorldEdit, use the `FastAsyncWorldEdit-<identifier>` version obtained in **worldedit-bukkit/build/libs**.
(The `-#` version includes FastAsyncWorldEdit + necessary libraries.)
## Other commands
== Other commands
* `gradlew idea` will generate an [IntelliJ IDEA](http://www.jetbrains.com/idea/) module for each folder.
* `gradlew idea` will generate an link:https://www.jetbrains.com/idea/[IntelliJ IDEA] module for each folder.
_Possibly broken_:
* `gradlew eclipse` will generate an [Eclipse](https://www.eclipse.org/downloads/) project for each folder.
* `gradlew eclipse` will generate an link:https://www.eclipse.org/downloads/[Eclipse] project for each folder.

Datei anzeigen

@ -1,74 +0,0 @@
Contributing
============
Thank you for your interest in contributing to FastAsyncWorldEdit! We appreciate your
effort, but to make sure that the inclusion of your patch is a smooth process, we
ask that you make note of the following guidelines.
* **Follow the [Oracle coding conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html).**
We can't stress this enough; if your code has notable issues, it may delay
the process significantly.
* **Target Java 8 for source and compilation.** Make sure to mark methods with
` @Override` that override methods of parent classes, or that implement
methods of interfaces.
* **Use only spaces for indentation.** Our indents are 4-spaces long, and tabs
are unacceptable.
* **Wrap code to a 120 column limit.** We do this to make side by side diffs
and other such tasks easier. Ignore this guideline if it makes the code
too unreadable.
* **Write complete Javadocs.** Do so only for public methods, and make sure
that your `@param` and `@return` fields are not just blank.
* **Don't tag classes with @author.** Some legacy classes may have this tag,
but we are phasing it out.
* **Make sure the code is efficient.** One way you can achieve this is to spend
around ten minutes to think about what the code is doing and whether it
seems awfully roundabout. If you had to copy the same large piece of
code in several places, that's bad.
* **Keep commit summaries under 70 characters.** For more details, place two
new lines after the summary line and write away!
* **Test your code.** We're not interested in broken code, for the obvious reasons.
* **Write unit tests.** While this is strictly optional, we recommend it for
complicated algorithms.
Additional Notes
----------------
If you're submitting a feature, base your code on `main` and PR against the
`main` branch.
Checklist
---------
Ready to submit? Perform the checklist below:
1. Have all tabs been replaced into four spaces? Are indentations 4-space wide?
2. Have I written proper Javadocs for my public methods? Are the @param and
@return fields actually filled out?
3. Have I `git rebase`d my pull request to the latest commit of the target
branch?
4. Have I combined my commits into a reasonably small number (if not one)
commit using `git rebase`?
5. Have I made my pull request too large? Pull requests should introduce
small sets of changes at a time. Major changes should be discussed with
the team prior to starting work.
6. Are my commit messages descriptive?
You should be aware of [`git rebase`](http://learn.github.com/p/rebasing.html).
It allows you to modify existing commit messages, and combine, break apart, or
adjust past changes.
Example
-------
This is **GOOD:**
if (var.func(param1, param2)) {
// do things
}
This is **VERY BAD:**
if(var.func( param1, param2 ))
{
// do things
}

36
Jenkinsfile vendored Normale Datei
Datei anzeigen

@ -0,0 +1,36 @@
pipeline {
agent any
options {
disableConcurrentBuilds()
}
stages {
stage('Build') {
steps {
withEnv([
"PATH+JAVA=${tool 'Temurin-17.0.7_7'}/bin"
]) {
sh './gradlew clean build'
}
}
}
stage('Archive artifacts') {
steps {
sh 'rm -rf artifacts'
sh 'mkdir artifacts'
sh 'cp worldedit-bukkit/build/libs/FastAsyncWorldEdit*.jar artifacts/'
sh 'cp worldedit-cli/build/libs/FastAsyncWorldEdit*.jar artifacts/'
archiveArtifacts artifacts: 'artifacts/*.jar', followSymlinks: false
}
}
stage('Fingerprint artifacts') {
steps {
fingerprint 'worldedit-bukkit/build/libs/FastAsyncWorldEdit*.jar'
}
}
stage('Publish JUnit test results') {
steps {
junit 'worldedit-core/build/test-results/test/*.xml,worldedit-bukkit/build/test-results/test/*.xml'
}
}
}
}

108
README.md
Datei anzeigen

@ -1,47 +1,95 @@
<p align="center">
<img src="fawe-logo.png" width="150">
</p>
# FastAsyncWorldEdit
[![Join us on Discord](https://img.shields.io/discord/268444645527126017.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/intellectualsites)
[![bStats Servers](https://img.shields.io/bstats/servers/1403)](https://bstats.org/plugin/bukkit/FastAsyncWorldEdit/1403)
[![Crowdin](https://badges.crowdin.net/e/4a5819fae3fd88234a8ea13bfbb072bb/localized.svg)](https://intellectualsites.crowdin.com/fastasyncworldedit)
---
## What is FAWE and why should I use it?
FastAsyncWorldEdit is a fork of WorldEdit that has huge speed and memory improvements and considerably more features
FAWE is designed for efficient world editing.
* Simple to set up and use
* Extremely configurable
* Uses minimal CPU/Memory
* Safe for many players to use
* Insanely fast, when using the slowest mode
**A Minecraft Map Editor... that runs in-game!**
FastAsyncWorldEdit is a fork of WorldEdit that has huge speed and memory improvements and considerably more features.
If you use other plugins which depend on WorldEdit, simply having FAWE installed will boost their performance.
* With selections, schematics, copy and paste, brushes, and scripting!
* Use it in creative, survival in single player or on your server.
* Use it on your Minecraft server to fix grieving and mistakes.
## Downloads
Java Edition required. FastAsyncWorldEdit is compatible with Bukkit, Spigot, Paper, and Tuinity.
Downloads are available either on SpigotMC, Modrinth or on CurseForge.
- [SpigotMC](https://www.spigotmc.org/resources/13932/)
- [Modrinth](https://modrinth.com/plugin/fastasyncworldedit/)
- [CurseForge](https://dev.bukkit.org/projects/fawe)
## Download FastAsyncWorldEdit
* Spigot: https://www.spigotmc.org/resources/fast-async-worldedit.13932/
* Older, unsupported, versions: https://intellectualsites.github.io/download/fawe.html
Snapshots are available on [Jenkins](https://ci.athion.net/job/FastAsyncWorldEdit/).
## Links
## Features
* [Discord](https://discord.gg/intellectualsites)
* [Wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit/wiki)
* [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit/issues)
* [Crowdin (Translations)](https://intellectualsites.crowdin.com/fastasyncworldedit)
* [JavaDocs](https://ci.athion.net/job/FastAsyncWorldEdit-1.16/javadoc/)
* Over 200 Commands
* Style and translate messages and commands
* (No setup required) Clipboard web integration (Clipboard)
* Unlimited //undo, per world history, instant lookups/rollback and cross server clipboards
* Advanced per player limits (entity, tiles, memory, changes, iterations, regions, inventory)
* Visualization, targeting modes/masks and scroll actions
* Adds lots of powerful new //brushes and //tools.
* Adds a lot more mask functionality. (new mask syntax, patterns, expressions, source masks)
* Adds a lot more pattern functionality. (a lot of new pattern syntax and patterns)
* Adds edit transforms (apply transforms to a source, e.g. on //paste)
* Adds support for new formats (e.g. Structure Blocks)
* Instant copying of arbitrary size with `//lazycopy`
* Auto repair partially corrupt schematic files
* Biome mixing, in-game world painting, dynamic view distance, vanilla cui, off axis rotation, image importing, cave generation,
multi-clipboards, interactive messages, schematic visualization, lag prevention, persistent brushes + A LOT MORE
## Edit The Code
### Performance
There are several placement modes, each supporting higher throughput than the previous. All editing is processed
asynchronously, with
certain tasks being broken up on the main thread. The default mode is chunk placement.
* Blocks (Bukkit-API) - Only used if chunk placement isn't supported. Still faster than any other plugin on spigot.
* Chunks (NMS) - Places entire chunk sections
* World (CFI) - Used to generate new worlds / regions
### Protection Plugins
The following plugins are supported with Bukkit:
* [WorldGuard](https://dev.bukkit.org/projects/worldguard)
* [PlotSquared](https://www.spigotmc.org/resources/77506/)
### Logging and Rollback
By default you can use `//inspect` and `//history rollback` to search and restore changes. To reduce disk usage, increase the
compression level and buffer size. To bypass logging use `//fast`.
### Developer API
FAWE maintains API compatibility with WorldEdit, so you can use the normal WorldEdit API asynchronously.
FAWE also has some asynchronously wrappers for the Bukkit API.
The wiki has examples for various things like reading NBT, modifying world files, pasting schematics, splitting up tasks, lighting etc.
If you need help with anything, hop on discord (link on the left bar).
## Documentation
* [Wiki](https://intellectualsites.github.io/fastasyncworldedit-documentation/)
* [Javadocs](https://intellectualsites.github.io/fastasyncworldedit-javadocs/)
## Contributing
Want to add new features to FastAsyncWorldEdit or fix bugs yourself? You can get the game running, with FastAsyncWorldEdit, from the code here:
For additional information about compiling FastAsyncWorldEdit, see [COMPILING.md](COMPILING.md).
For additional information about compiling FastAsyncWorldEdit, read the [compiling documentation](https://github.com/IntellectualSites/FastAsyncWorldEdit/blob/main/COMPILING.adoc).
## Submitting Your Changes
FastAsyncWorldEdit is open source (specifically licensed under GPL v3), so note that your contributions will also be open source. The best way to submit a change is to create a fork on GitHub, put your changes there, and then create a "pull request" on our FastAsyncWorldEdit repository.
## Special thanks
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for important guidelines to follow.
## YourKit
<a href="https://www.yourkit.com">
<img src="https://www.yourkit.com/images/yklogo.png">
<a href="https://jb.gg/OpenSourceSupport"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg" width="150">
</a>
</br>
[JetBrains](https://jb.gg/OpenSourceSupport), creators of the IntelliJ IDEA, supports us with their Open Source Licenses.
<a href="https://yourkit.com/"><img src="https://www.yourkit.com/images/yklogo.png" width="200">
</a>
Thank you to YourKit for supporting our product by providing us with their innovative and intelligent tools
for monitoring and profiling Java and .NET applications.
YourKit is the creator of <a href="https://www.yourkit.com/java/profiler/">YourKit Java Profiler</a>, <a href="https://www.yourkit.com/.net/profiler/">YourKit .NET Profiler</a>, and <a href="https://www.yourkit.com/youmonitor/">YourKit YouMonitor</a>
YourKit is the creator of [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/), and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/).

Datei anzeigen

@ -1,14 +1,31 @@
import org.ajoberstar.grgit.Grgit
import java.time.format.DateTimeFormatter
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED
import java.net.URI
import java.time.format.DateTimeFormatter
import xyz.jpenilla.runpaper.task.RunServer
plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
id("xyz.jpenilla.run-paper") version "2.1.0"
}
if (!File("$rootDir/.git").exists()) {
logger.lifecycle("""
**************************************************************************************
You need to fork and clone this repository! Don't download a .zip file.
If you need assistance, consult the GitHub docs: https://docs.github.com/get-started/quickstart/fork-a-repo
**************************************************************************************
""".trimIndent()
).also { kotlin.system.exitProcess(1) }
}
logger.lifecycle("""
*******************************************
You are building FastAsyncWorldEdit!
If you encounter trouble:
1) Read COMPILING.md if you haven't yet
1) Read COMPILING.adoc if you haven't yet
2) Try running 'build' in a separate Gradle run
3) Use gradlew and not gradle
4) If you still need help, ask on Discord! https://discord.gg/intellectualsites
@ -17,7 +34,8 @@ logger.lifecycle("""
*******************************************
""")
var rootVersion by extra("1.16")
var rootVersion by extra("2.7.1")
var snapshot by extra("SNAPSHOT")
var revision: String by extra("")
var buildNumber by extra("")
var date: String by extra("")
@ -27,11 +45,10 @@ ext {
}
date = git.head().dateTime.format(DateTimeFormatter.ofPattern("yy.MM.dd"))
revision = "-${git.head().abbreviatedId}"
val commit: String? = git.head().abbreviatedId
buildNumber = if (project.hasProperty("buildnumber")) {
project.properties["buildnumber"] as String
snapshot + "-" + project.properties["buildnumber"] as String
} else {
commit.toString()
project.properties["snapshot"] as String
}
}
@ -66,3 +83,32 @@ allprojects {
}
applyCommonConfiguration()
val supportedVersions = listOf("1.16.5", "1.17", "1.17.1", "1.18.2", "1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1")
tasks {
supportedVersions.forEach {
register<RunServer>("runServer-$it") {
minecraftVersion(it)
pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
.toTypedArray())
jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true")
group = "run paper"
runDirectory.set(file("run-$it"))
}
}
runServer {
minecraftVersion("1.20.1")
pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
.toTypedArray())
}
}
nexusPublishing {
this.repositories {
sonatype {
nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}

Datei anzeigen

@ -6,7 +6,7 @@ plugins {
}
repositories {
jcenter()
mavenCentral()
gradlePluginPortal()
maven {
name = "EngineHub"
@ -22,6 +22,13 @@ val properties = Properties().also { props ->
dependencies {
implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:4.1.0")
implementation("com.github.jengelman.gradle.plugins:shadow:6.1.0")
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.0")
implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.5")
}
kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
}
}

Datei anzeigen

@ -0,0 +1,23 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.dependencies
// For specific version pinning, see
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
fun Project.applyPaperweightAdapterConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-library")
applyCommonJavaConfiguration(
sourcesJar = true,
banSlf4j = false,
)
apply(plugin = "io.papermc.paperweight.userdev")
dependencies {
"implementation"(project(":worldedit-bukkit"))
}
tasks.named("assemble") {
dependsOn("reobfJar")
}
}

Datei anzeigen

@ -2,7 +2,6 @@ import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.repositories
import org.gradle.kotlin.dsl.the
@ -11,11 +10,7 @@ fun Project.applyCommonConfiguration() {
version = rootProject.version
repositories {
mavenLocal()
maven {
name = "IntellectualSites"
url = uri("https://mvn.intellectualsites.com/content/groups/public/")
}
mavenCentral()
maven {
name = "EngineHub"
url = uri("https://maven.enginehub.org/repo/")
@ -24,10 +19,6 @@ fun Project.applyCommonConfiguration() {
name = "OSS Sonatype Snapshots"
url = uri("https://oss.sonatype.org/content/repositories/snapshots/")
}
maven {
name = "OSS Sonatype Releases"
url = uri("https://oss.sonatype.org/content/repositories/releases/")
}
maven {
name = "Athion"
url = uri("https://ci.athion.net/plugin/repository/tools/")
@ -40,17 +31,9 @@ fun Project.applyCommonConfiguration() {
}
}
configurations.findByName("compileClasspath")?.apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
plugins.withId("java") {
the<JavaPluginExtension>().toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
languageVersion.set(JavaLanguageVersion.of(17))
}
}
@ -62,15 +45,15 @@ fun Project.applyCommonConfiguration() {
continue
}
add(conf.name, "com.google.guava:guava") {
version { strictly(Versions.GUAVA) }
version { require("31.1-jre") }
because("Mojang provides Guava")
}
add(conf.name, "com.google.code.gson:gson") {
version { strictly(Versions.GSON) }
version { require("2.10") }
because("Mojang provides Gson")
}
add(conf.name, "it.unimi.dsi:fastutil") {
version { strictly(Versions.FAST_UTIL) }
version { require("8.5.9") }
because("Mojang provides FastUtil")
}
}

Datei anzeigen

@ -0,0 +1,90 @@
import org.gradle.api.Project
import org.gradle.api.attributes.java.TargetJvmVersion
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean = true) {
applyCommonConfiguration()
apply(plugin = "eclipse")
apply(plugin = "idea")
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial"
)
options.release.set(17)
options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = true
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}
configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
dependencies {
"compileOnly"("com.google.code.findbugs:jsr305:3.0.2")
"testImplementation"("org.junit.jupiter:junit-jupiter-api:5.10.0")
"testImplementation"("org.junit.jupiter:junit-jupiter-params:5.10.0")
"testImplementation"("org.mockito:mockito-core:5.4.0")
"testImplementation"("org.mockito:mockito-junit-jupiter:5.4.0")
"testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.10.0")
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
options.encoding = "UTF-8"
links(
"https://jd.advntr.dev/api/latest/",
"https://logging.apache.org/log4j/2.x/log4j-api/apidocs/",
"https://www.antlr.org/api/Java/",
"https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/",
"https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/",
"https://jd.papermc.io/paper/1.20/",
"https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/"
)
docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}"
}
}
configure<JavaPluginExtension> {
disableAutoTargetJvm()
withJavadocJar()
if (sourcesJar) {
withSourcesJar()
}
}
if (banSlf4j) {
configurations["compileClasspath"].apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
}
}

Datei anzeigen

@ -1,6 +1,6 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
@ -9,4 +9,4 @@ val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.sourceSets: SourceSetContainer
get() = the<JavaPluginConvention>().sourceSets
get() = the<JavaPluginExtension>().sourceSets

Datei anzeigen

@ -1,33 +1,48 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.internal.HasConvention
import org.gradle.api.plugins.MavenRepositoryHandlerConvention
import org.gradle.api.tasks.Upload
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.attributes.Usage
import org.gradle.api.attributes.java.TargetJvmVersion
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getPlugin
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.the
import org.gradle.plugins.signing.SigningExtension
import javax.inject.Inject
fun Project.applyLibrariesConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-base")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "signing")
configurations {
create("shade")
getByName("archives").extendsFrom(getByName("default"))
}
group = "${rootProject.group}.worldedit-libs"
val relocations = mapOf(
"net.kyori.text" to "com.sk89q.worldedit.util.formatting.text",
"net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori"
"net.kyori.text" to "com.sk89q.worldedit.util.formatting.text",
"net.kyori.minecraft" to "com.sk89q.worldedit.util.kyori",
"net.kyori.adventure.nbt" to "com.sk89q.worldedit.util.nbt"
)
tasks.register<ShadowJar>("jar") {
@ -37,8 +52,10 @@ fun Project.applyLibrariesConfiguration() {
dependencies {
exclude(dependency("com.google.guava:guava"))
exclude(dependency("com.google.code.gson:gson"))
exclude(dependency("com.google.errorprone:error_prone_annotations"))
exclude(dependency("org.checkerframework:checker-qual"))
exclude(dependency("org.apache.logging.log4j:log4j-api"))
exclude(dependency("com.google.code.findbugs:jsr305"))
}
relocations.forEach { (from, to) ->
@ -47,22 +64,22 @@ fun Project.applyLibrariesConfiguration() {
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
@ -81,31 +98,175 @@ fun Project.applyLibrariesConfiguration() {
archiveClassifier.set("sources")
}
// This a dummy jar to comply with the requirements of the OSSRH,
// libs are not API and therefore no "proper" javadoc jar is necessary
tasks.register<Jar>("javadocJar") {
archiveClassifier.set("javadoc")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
dependsOn("jar", "sourcesJar", "javadocJar")
}
artifacts {
val jar = tasks.named("jar")
add("default", jar) {
builtBy(jar)
project.apply<LibsConfigPluginHack>()
val libsComponent = project.components["libs"] as AdhocComponentWithVariants
val apiElements = project.configurations.register("apiElements") {
isVisible = false
description = "API elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
val sourcesJar = tasks.named("sourcesJar")
add("archives", sourcesJar) {
builtBy(sourcesJar)
outgoing.artifact(tasks.named("jar"))
}
val runtimeElements = project.configurations.register("runtimeElements") {
isVisible = false
description = "Runtime elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
outgoing.artifact(tasks.named("jar"))
}
val sourcesElements = project.configurations.register("sourcesElements") {
isVisible = false
description = "Source elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.SOURCES))
}
outgoing.artifact(tasks.named("sourcesJar"))
}
val javadocElements = project.configurations.register("javadocElements") {
isVisible = false
description = "Javadoc elements for libs"
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.SHADOWED))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType.JAVADOC))
}
outgoing.artifact(tasks.named("javadocJar"))
}
libsComponent.addVariantsFromConfiguration(apiElements.get()) {
mapToMavenScope("compile")
}
libsComponent.addVariantsFromConfiguration(runtimeElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(sourcesElements.get()) {
mapToMavenScope("runtime")
}
libsComponent.addVariantsFromConfiguration(javadocElements.get()) {
mapToMavenScope("runtime")
}
val publishingExtension = the<PublishingExtension>()
configure<SigningExtension> {
if (!version.toString().endsWith("-SNAPSHOT")) {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
isRequired
sign(publishingExtension.publications)
}
}
tasks.register<Upload>("install") {
configuration = configurations["archives"]
(repositories as HasConvention).convention.getPlugin<MavenRepositoryHandlerConvention>().mavenInstaller {
pom.version = project.version.toString()
pom.artifactId = project.name
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(libsComponent)
group = "com.fastasyncworldedit"
artifactId = "FastAsyncWorldEdit-Libs-${project.name.replaceFirstChar(Char::titlecase)}"
version = version
pom {
name.set("${rootProject.name}-Libs" + " " + project.version)
description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.")
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit")
licenses {
license {
name.set("GNU General Public License, Version 3.0")
url.set("https://www.gnu.org/licenses/gpl-3.0.html")
distribution.set("repo")
}
}
developers {
developer {
id.set("NotMyFault")
name.set("Alexander Brandes")
email.set("contact(at)notmyfault.dev")
organization.set("IntellectualSites")
}
developer {
id.set("SirYwell")
name.set("Hannes Greule")
organization.set("IntellectualSites")
}
developer {
id.set("dordsor21")
name.set("dordsor21")
organization.set("IntellectualSites")
}
}
scm {
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit")
connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git")
developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git")
}
issueManagement {
system.set("GitHub")
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues")
}
}
}
}
}
}
// A horrible hack because `softwareComponentFactory` has to be gotten via plugin
// gradle why
internal open class LibsConfigPluginHack @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory
) : Plugin<Project> {
override fun apply(project: Project) {
val libsComponents = softwareComponentFactory.adhoc("libs")
project.components.add(libsComponents)
}
}
fun Project.constrainDependenciesToLibsCore() {
evaluationDependsOn(":worldedit-libs:core")
val coreDeps = project(":worldedit-libs:core").configurations["shade"].dependencies

Datei anzeigen

@ -1,20 +1,18 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.StandardJavadocDocletOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getByName
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
import org.gradle.kotlin.dsl.the
import org.gradle.plugins.signing.SigningExtension
fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration()
@ -22,92 +20,110 @@ fun Project.applyPlatformAndCoreConfiguration() {
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "maven-publish")
// apply(plugin = "checkstyle")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "signing")
applyCommonJavaConfiguration(
sourcesJar = name in setOf("worldedit-core", "worldedit-bukkit"),
)
if (project.hasProperty("buildnumber")) {
ext["internalVersion"] = "$version;${rootProject.ext["gitCommitHash"]}"
} else {
ext["internalVersion"] = "$version"
}
tasks
.withType<JavaCompile>()
.matching { it.name == "compileJava" || it.name == "compileTestJava" }
.configureEach {
val disabledLint = listOf(
"processing", "path", "fallthrough", "serial"
)
//options.compilerArgs.addAll(listOf("-Xlint:all") + disabledLint.map { "-Xlint:-$it" })
options.isDeprecation = false
options.encoding = "UTF-8"
options.compilerArgs.add("-parameters")
}
// configure<CheckstyleExtension> {
// configFile = rootProject.file("config/checkstyle/checkstyle.xml")
// toolVersion = "8.34"
// }
tasks.withType<Test>().configureEach {
useJUnitPlatform()
configure<JavaPluginExtension> {
disableAutoTargetJvm()
withJavadocJar()
}
dependencies {
"compileOnly"("org.jetbrains:annotations:20.1.0")
"testImplementation"("org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}")
"testImplementation"("org.junit.jupiter:junit-jupiter-params:${Versions.JUNIT}")
"testImplementation"("org.mockito:mockito-core:${Versions.MOCKITO}")
"testImplementation"("org.mockito:mockito-junit-jupiter:${Versions.MOCKITO}")
"testImplementation"("net.bytebuddy:byte-buddy:1.11.0")
"testRuntime"("org.junit.jupiter:junit-jupiter-engine:${Versions.JUNIT}")
if (name in setOf("worldedit-core", "worldedit-bukkit", "worldedit-cli")) {
the<JavaPluginExtension>().withSourcesJar()
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
(options as StandardJavadocDocletOptions).apply {
addStringOption("Xdoclint:none", "-quiet")
tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
val javaComponent = components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
}
val publishingExtension = the<PublishingExtension>()
configure<SigningExtension> {
if (!version.toString().endsWith("-SNAPSHOT")) {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
isRequired
sign(publishingExtension.publications)
}
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
configure<PublishingExtension> {
publications {
register<MavenPublication>("maven") {
from(javaComponent)
tasks.named("assemble").configure {
dependsOn("javadocJar")
}
group = "com.fastasyncworldedit"
artifactId = "${rootProject.name}-${project.description}"
version = version
artifacts {
add("archives", tasks.named("jar"))
add("archives", tasks.named("javadocJar"))
}
pom {
name.set("${rootProject.name}-${project.description}" + " " + project.version)
description.set("Blazingly fast Minecraft world manipulation for artists, builders and everyone else.")
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit")
if (name == "worldedit-core" || name == "worldedit-bukkit") {
tasks.register<Jar>("sourcesJar") {
dependsOn("classes")
archiveClassifier.set("sources")
from(sourceSets["main"].allSource)
}
licenses {
license {
name.set("GNU General Public License, Version 3.0")
url.set("https://www.gnu.org/licenses/gpl-3.0.html")
distribution.set("repo")
}
}
artifacts {
add("archives", tasks.named("sourcesJar"))
}
tasks.named("assemble").configure {
dependsOn("sourcesJar")
developers {
developer {
id.set("NotMyFault")
name.set("Alexander Brandes")
email.set("contact(at)notmyfault.dev")
organization.set("IntellectualSites")
}
developer {
id.set("SirYwell")
name.set("Hannes Greule")
organization.set("IntellectualSites")
}
developer {
id.set("dordsor21")
name.set("dordsor21")
organization.set("IntellectualSites")
}
}
scm {
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit")
connection.set("scm:https://IntellectualSites@github.com/IntellectualSites/FastAsyncWorldEdit.git")
developerConnection.set("scm:git://github.com/IntellectualSites/FastAsyncWorldEdit.git")
}
issueManagement{
system.set("GitHub")
url.set("https://github.com/IntellectualSites/FastAsyncWorldEdit/issues")
}
}
}
}
}
// tasks.named("check").configure {
// dependsOn("checkstyleMain", "checkstyleTest")
// }
if (name != "worldedit-fabric") {
configurations["compileClasspath"].apply {
resolutionStrategy.componentSelection {
withModule("org.slf4j:slf4j-api") {
reject("No SLF4J allowed on compile classpath")
}
}
}
}
}
@ -133,27 +149,28 @@ val CLASSPATH = listOf("truezip", "truevfs", "js")
.joinToString(separator = " ")
sealed class WorldEditKind(
val name: String,
val mainClass: String = "com.sk89q.worldedit.internal.util.InfoEntryPoint"
val name: String,
val mainClass: String = "com.sk89q.worldedit.internal.util.InfoEntryPoint"
) {
class Standalone(mainClass: String) : WorldEditKind("STANDALONE", mainClass)
object Mod : WorldEditKind("MOD")
object Plugin : WorldEditKind("PLUGIN")
}
fun Project.addJarManifest(kind: WorldEditKind, includeClasspath: Boolean = false) {
fun Project.addJarManifest(kind: WorldEditKind, includeClasspath: Boolean = false, extraAttributes: Map<String, String> = mapOf()) {
tasks.named<Jar>("jar") {
val version = project(":worldedit-core").version
inputs.property("version", version)
val attributes = mutableMapOf(
"Implementation-Version" to version,
"WorldEdit-Version" to version,
"WorldEdit-Kind" to kind.name,
"Main-Class" to kind.mainClass
"Implementation-Version" to version,
"WorldEdit-Version" to version,
"WorldEdit-Kind" to kind.name,
"Main-Class" to kind.mainClass
)
if (includeClasspath) {
attributes["Class-Path"] = CLASSPATH
}
attributes.putAll(extraAttributes)
manifest.attributes(attributes)
}
}

Datei anzeigen

@ -1,22 +0,0 @@
import org.gradle.api.Project
object Versions {
const val TEXT = "3.0.4"
const val TEXT_EXTRAS = "3.0.6"
const val PISTON = "0.5.7"
const val AUTO_VALUE = "1.7.4"
const val JUNIT = "5.7.0"
const val MOCKITO = "3.9.0"
const val FAST_UTIL = "8.2.1"
const val GUAVA = "21.0"
const val GSON = "2.8.0"
}
// Properties that need a project reference to resolve:
class ProjectVersions(project: Project) {
val loom = project.rootProject.property("loom.version")
val mixin = project.rootProject.property("mixin.version")
}
val Project.versions
get() = ProjectVersions(this)

Datei anzeigen

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files=".*DataFixer\.java" checks="MethodName|FallThrough"/>
<suppress files=".*[\\/]MathUtils.java" checks="MethodName"/>
<suppress files=".*[\\/]bPermissionsResolver.java" checks="TypeName"/>
<!-- This thing only works via the use of a finalizer. -->
<suppress files=".*[\\/]TracedEditSession.java" checks="NoFinalizer"/>
<!-- None of the old command stuff really matters -->
<suppress files=".*[\\/]minecraft[\\/]util[\\/]commands[\\/].*\.java" checks=".*"/>
<!-- FAWE ADDITIONS -->
<suppress files=".*[\\/]MathMan.java" checks="MethodName"/>
<suppress files=".*[\\/]net[\\/]jpountz[\\/]lz4[\\/].*\.java" checks=".*"/>
<suppress files=".*[\\/]BufferedRandomAccessFile.java" checks=".*"/>
<suppress files=".*[\\/]ByteBufferUtils.java" checks="NoWhitespaceBefore"/>
<suppress files=".*[\\/]Settings.java" checks="MemberName"/>
<suppress files=".*[\\/]FaweLimit.java" checks="MemberName"/>
<suppress files=".*[\\/]SimplexNoise.java" checks="MemberName"/>
<suppress files=".*[\\/]SparseBitSet.java" checks=".*"/>
</suppressions>

Datei anzeigen

@ -1,214 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checks based on Google Checks, modified for EngineHub.
-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="RightCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT, INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="WhitespaceAfter">
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. (4.1.3)"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens" value="COMMA, POST_INC, POST_DEC, ELLIPSIS, LABELED_STAT"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens" value="SEMI"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough">
<property name="reliefPattern" value="FALL-THROUGH|falls?[ -]?thr(u|ough)"/>
</module>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^([a-z][_a-zA-Z0-9]+|[xyz])$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="severity" value="warning"/>
<property name="format" value="^([a-z][a-z0-9][_a-zA-Z0-9]*|[a-z])$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|(^[A-Z][a-zA-Z0-9]*$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="severity" value="warning"/>
<property name="format" value="(^[A-Z][0-9]?)$|(^[A-Z][a-zA-Z0-9]*$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Regexp">
<property name="format" value="[ \t]+$"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Trailing whitespace"/>
</module>
<module name="Indentation">
<property name="basicOffset" value="4"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="4"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="4"/>
</module>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="customImportOrderRules" value="THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE###STATIC"/>
</module>
<module name="MethodParamPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadocCheck">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<!-- No javadoc for now -->
<!--<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>-->
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected|ignored"/>
</module>
<module name="CommentsIndentation"/>
<!-- Validate String.to(Lower|Upper)Case() calls include Locale argument -->
<module name="Regexp">
<property name="severity" value="warning"/>
<property name="message" value="Case-conversion calls must include an explicit Locale"/>
<property name="format" value="(?!Character)\.to(Lower|Upper)Case\(\)"/>
<property name="illegalPattern" value="true"/>
</module>
</module>
<!-- Validate that command annotations are formatted correctly -->
<module name="RegexpMultiline">
<property name="format" value="^( +)@(Arg|Switch|Command)\(.*?\r?\n\1 {5,}"/>
</module>
<module name="RegexpMultiline">
<property name="format" value="(?s:(\r\n|\r).*)"/>
<property name="message" value="CRLF and CR line endings are prohibited, but this file uses them."/>
</module>
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/checkstyle-suppression.xml"/>
</module>
</module>

Datei anzeigen

@ -1,5 +1,5 @@
Write a cool script? You can submit a pull request to [our GitHub Repository](https://github.com/IntellectualSites/FastAsyncWorldEdit).
We will consider your script for inclusion in the FastAsyncWorldEdit repository. CraftScripts in the FastAsyncWorldEdit repository are
licensed under GPLv3, like the rest of FastAsybcWorldEdit.
licensed under GPLv3, like the rest of FastAsyncWorldEdit.
You can also post your scripts on [our Discord](https://discord.gg/intellectualsites) in the `#sharing-is-caring` channel.

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 17 KiB

Datei anzeigen

@ -1,10 +1,9 @@
group=com.sk89q.worldedit
group=com.fastasyncworldedit
org.gradle.jvmargs=-Xmx1512M
org.gradle.daemon=true
org.gradle.configureondemand=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.vfs.watch=true
loom.version=0.5.43

125
gradle/libs.versions.toml Normale Datei
Datei anzeigen

@ -0,0 +1,125 @@
[versions]
# Minecraft expectations
paper = "1.20.1-R0.1-SNAPSHOT"
fastutil = "8.5.9"
guava = "31.1-jre"
log4j = "2.19.0"
gson = "2.10"
snakeyaml = "2.0"
# Plugins
dummypermscompat = "1.10"
worldguard-bukkit = "7.0.9"
mapmanager = "1.8.0-SNAPSHOT"
griefprevention = "16.18.1"
griefdefender = "2.1.0-SNAPSHOT"
residence = "4.5._13.1"
towny = "0.99.5.10"
plotsquared = "7.0.0-rc.4"
# Third party
bstats = "3.0.2"
sparsebitset = "1.2"
parallelgzip = "1.0.5"
adventure = "4.14.0"
adventure-bukkit = "4.3.0"
checkerqual = "3.37.0"
truezip = "6.8.4"
auto-value = "1.10.2"
findbugs = "3.0.2"
rhino-runtime = "1.7.14"
zstd-jni = "1.4.8-1" # Not latest as it can be difficult to obtain latest ZSTD libs
antlr4 = "4.13.0"
json-simple = "1.1.1"
jlibnoise = "1.0.0"
jchronic = "0.2.4a"
lz4-java = "1.8.0"
lz4-stream = "1.0.0"
commons-cli = "1.5.0"
paperlib = "1.0.8"
paster = "1.1.5"
vault = "1.7.1"
serverlib = "2.3.1"
## Internal
text-adapter = "3.0.6"
text = "3.0.4"
piston = "0.5.7"
# Tests
mockito = "5.4.0"
# Gradle plugins
pluginyml = "0.6.0"
minotaur = "2.8.3"
[libraries]
# Minecraft expectations
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
fastutil = { group = "it.unimi.dsi", name = "fastutil", version.ref = "fastutil" }
log4jBom = { group = "org.apache.logging.log4j", name = "log4j-bom", version.ref = "log4j" }
log4jApi = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" }
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" }
# Plugins
dummypermscompat = { group = "com.sk89q", name = "dummypermscompat", version.ref = "dummypermscompat" }
worldguard = { group = "com.sk89q.worldguard", name = "worldguard-bukkit", version.ref = "worldguard-bukkit" }
mapmanager = { group = "com.github.InventivetalentDev", name = "MapManager", version.ref = "mapmanager" }
griefprevention = { group = "com.github.TechFortress", name = "GriefPrevention", version.ref = "griefprevention" }
griefdefender = { group = "com.griefdefender", name = "api", version.ref = "griefdefender" }
residence = { group = "com.bekvon.bukkit.residence", name = "Residence", version.ref = "residence" }
towny = { group = "com.palmergames.bukkit.towny", name = "towny", version.ref = "towny" }
plotSquaredCore = { group = "com.intellectualsites.plotsquared", name = "plotsquared-core", version.ref = "plotsquared" }
plotSquaredBukkit = { group = "com.intellectualsites.plotsquared", name = "plotsquared-bukkit", version.ref = "plotsquared" }
# Third Party
bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" }
bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
sparsebitset = { group = "com.zaxxer", name = "SparseBitSet", version.ref = "sparsebitset" }
parallelgzip = { group = "org.anarres", name = "parallelgzip", version.ref = "parallelgzip" }
adventureNbt = { group = "net.kyori", name = "adventure-nbt", version.ref = "adventure" }
truezip = { group = "de.schlichtherle", name = "truezip", version.ref = "truezip" }
autoValueAnnotations = { group = "com.google.auto.value", name = "auto-value-annotations", version.ref = "auto-value" }
autoValue = { group = "com.google.auto.value", name = "auto-value", version.ref = "auto-value" }
findbugs = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "findbugs" }
rhino = { group = "org.mozilla", name = "rhino-runtime", version.ref = "rhino-runtime" }
zstd = { group = "com.github.luben", name = "zstd-jni", version.ref = "zstd-jni" }
antlr4 = { group = "org.antlr", name = "antlr4", version.ref = "antlr4" }
antlr4Runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "antlr4" }
jsonSimple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" }
jlibnoise = { group = "com.sk89q.lib", name = "jlibnoise", version.ref = "jlibnoise" }
jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" }
lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" }
lz4JavaStream = { group = "net.jpountz", name = "lz4-java-stream", version.ref = "lz4-stream" }
commonsCli = { group = "commons-cli", name = "commons-cli", version.ref = "commons-cli" }
paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" }
adventureApi = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
adventureMiniMessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
adventureBukkit = { group = "net.kyori", name = "adventure-platform-bukkit", version.ref = "adventure-bukkit" }
paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref = "paster" }
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" }
checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" }
# Internal
## Text
adventureTextAdapterBukkit = { group = "net.kyori", name = "text-adapter-bukkit", version.ref = "text-adapter" }
adventureTextApi = { group = "net.kyori", name = "text-api", version.ref = "text" }
adventureTextSerializerGson = { group = "net.kyori", name = "text-serializer-gson", version.ref = "text" }
adventureTextSerializerLegacy = { group = "net.kyori", name = "text-serializer-legacy", version.ref = "text" }
adventureTextSerializerPlain = { group = "net.kyori", name = "text-serializer-plain", version.ref = "text" }
## Piston
piston = { group = "org.enginehub.piston", name = "core", version.ref = "piston" }
pistonImpl = { group = "org.enginehub.piston", name = "default-impl", version.ref = "piston" }
pistonAnnotations = { group = "org.enginehub.piston.core-ap", name = "annotations", version.ref = "piston" }
pistonProcessor = { group = "org.enginehub.piston.core-ap", name = "processor", version.ref = "piston" }
pistonRuntime = { group = "org.enginehub.piston.core-ap", name = "runtime", version.ref = "piston" }
# Tests
mockito = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" }
log4jCore = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" }
[plugins]
pluginyml = { id = "net.minecrell.plugin-yml.bukkit", version.ref = "pluginyml" }
minotaur = { id = "com.modrinth.minotaur", version.ref = "minotaur" }

Binäre Datei nicht angezeigt.

Datei anzeigen

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

293
gradlew vendored
Datei anzeigen

@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,67 +17,98 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -87,9 +118,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -98,88 +129,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

15
gradlew.bat vendored
Datei anzeigen

@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

Datei anzeigen

@ -1,6 +0,0 @@
{
"extends": [
"config:base"
],
"ignoreDeps": ["guava", "rhino-runtime", "mockito-core", "antlr4", "antlr4-runtime", "paranamer", "fastutil", "auto-value-annotations", "auto-value"]
}

Datei anzeigen

@ -2,11 +2,14 @@ rootProject.name = "FastAsyncWorldEdit"
include("worldedit-libs")
listOf("legacy", "1_17_1", "1_18_2", "1_19", "1_19_3","1_19_4", "1_20").forEach {
include("worldedit-bukkit:adapters:adapter-$it")
}
listOf("bukkit", "core", "cli").forEach {
include("worldedit-libs:$it")
include("worldedit-$it")
}
// include("worldedit-mod")
include("worldedit-libs:core:ap")
dependencyResolutionManagement {
@ -18,3 +21,5 @@ dependencyResolutionManagement {
}
}
}
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

9
steamwarci.yml Normale Datei
Datei anzeigen

@ -0,0 +1,9 @@
build:
- "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew build"
- "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew --stop"
artifacts:
"/binarys/FastAsyncWorldEdit-1.18.jar": "worldedit-bukkit/build/libs/FastAsyncWorldEdit-Bukkit-2.7.1-SNAPSHOT.jar"
release:
- "mvn deploy:deploy-file -DgroupId=de.steamwar -DartifactId=fastasyncworldedit -Dversion=1.18 -Dpackaging=jar -Dfile=/binarys/FastAsyncWorldEdit-1.18.jar -Durl=file:///var/www/html/maven/"

Datei anzeigen

@ -0,0 +1,26 @@
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
applyPaperweightAdapterConfiguration()
plugins {
java
}
repositories {
mavenCentral()
gradlePluginPortal()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
configurations.all {
attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17)
}
dependencies {
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.17.1-R0.1-20220414.034903-210")
compileOnly(libs.paperlib)
}

Datei anzeigen

@ -0,0 +1,103 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stat;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.OptionalInt;
import java.util.UUID;
class PaperweightFakePlayer extends ServerPlayer {
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
UUID.nameUUIDFromBytes("worldedit".getBytes()),
"[WorldEdit]"
);
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
PaperweightFakePlayer(ServerLevel world) {
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
}
@Override
public Vec3 position() {
return ORIGIN;
}
@Override
public void tick() {
}
@Override
public void die(DamageSource damagesource) {
}
@Override
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
return this;
}
@Override
public OptionalInt openMenu(MenuProvider factory) {
return OptionalInt.empty();
}
@Override
public void updateOptions(ServerboundClientInformationPacket packet) {
}
@Override
public void displayClientMessage(Component message, boolean actionBar) {
}
@Override
public void sendMessage(Component message, ChatType type, UUID sender) {
}
@Override
public void awardStat(Stat<?> stat, int amount) {
}
@Override
public void awardStat(Stat<?> stat) {
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return true;
}
@Override
public void openTextEdit(SignBlockEntity sign) {
}
}

Datei anzeigen

@ -0,0 +1,209 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Objects;
public class PaperweightWorldNativeAccess implements
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private final PaperweightAdapter adapter;
private final WeakReference<ServerLevel> world;
private SideEffectSet sideEffectSet;
public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference<ServerLevel> world) {
this.adapter = adapter;
this.world = world;
}
private ServerLevel getWorld() {
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getWorld().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state);
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) {
return chunk.getBlockState(position);
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState state
) {
return chunk.setType(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState block,
BlockPos position
) {
return Block.updateFromNeighbourShapes(block, getWorld(), position);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos position) {
getWorld().getChunkSource().getLightEngine().checkBlock(position);
}
@Override
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
return false;
}
@Override
public void notifyBlockUpdate(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk chunk) {
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk chunk, BlockPos position) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().getChunkSource().blockChanged(position);
}
}
@Override
public void notifyNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
ServerLevel world = getWorld();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
world.updateNeighborsAt(pos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
Block block = oldState.getBlock();
fireNeighborChanged(pos, world, block, pos.west());
fireNeighborChanged(pos, world, block, pos.east());
fireNeighborChanged(pos, world, block, pos.below());
fireNeighborChanged(pos, world, block, pos.above());
fireNeighborChanged(pos, world, block, pos.north());
fireNeighborChanged(pos, world, block, pos.south());
}
if (newState.hasAnalogOutputSignal()) {
world.updateNeighbourForOutputSignal(pos, newState.getBlock());
}
}
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
}
@Override
public void updateNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
ServerLevel world = getWorld();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = world.getWorld();
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
CraftBlockData.fromData(newState)
);
world.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getWorld().onBlockStateChange(pos, oldState, newState);
}
@Override
public void flush() {
}
}

Datei anzeigen

@ -0,0 +1,189 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block;
private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial;
private final int opacity;
private final CompoundTag tile;
public PaperweightBlockMaterial(Block block) {
this(block, block.defaultBlockState());
}
public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block;
this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aP"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO,
blockState
);
tile = tileEntity == null
? null
: new PaperweightLazyCompoundTag(Suppliers.memoize(() -> tileEntity.save(new net.minecraft.nbt.CompoundTag())));
}
public Block getBlock() {
return block;
}
public BlockState getState() {
return blockState;
}
public CraftBlockData getCraftBlockData() {
return craftBlockData;
}
public Material getMaterial() {
return material;
}
@Override
public boolean isAir() {
return blockState.isAir();
}
@Override
public boolean isFullCube() {
return craftMaterial.isOccluding();
}
@Override
public boolean isOpaque() {
return material.isSolidBlocking();
}
@Override
public boolean isPowerSource() {
return blockState.isSignalSource();
}
@Override
public boolean isLiquid() {
return material.isLiquid();
}
@Override
public boolean isSolid() {
return material.isSolid();
}
@Override
public float getHardness() {
return craftBlockData.getState().destroySpeed;
}
@Override
public float getResistance() {
return block.getExplosionResistance();
}
@Override
public float getSlipperiness() {
return block.getFriction();
}
@Override
public int getLightValue() {
return blockState.getLightEmission();
}
@Override
public int getLightOpacity() {
return opacity;
}
@Override
public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY;
}
@Override
public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK;
}
@Override
public boolean isTicksRandomly() {
return block.isRandomlyTicking(blockState);
}
@Override
public boolean isMovementBlocker() {
return material.isSolid();
}
@Override
public boolean isBurnable() {
return material.isFlammable();
}
@Override
public boolean isToolRequired() {
// Removed in 1.16.1, this is not present in higher versions
return false;
}
@Override
public boolean isReplacedDuringPlacement() {
return material.isReplaceable();
}
@Override
public boolean isTranslucent() {
return isTranslucent;
}
@Override
public boolean hasContainer() {
return block instanceof EntityBlock;
}
@Override
public boolean isTile() {
return block instanceof EntityBlock;
}
@Override
public CompoundTag getDefaultTile() {
return tile;
}
@Override
public int getMapColor() {
// rgb field
return material.getColor().col;
}
}

Datei anzeigen

@ -0,0 +1,709 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen.PaperweightRegen;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.WritableRegistry;
import net.minecraft.nbt.IntTag;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final PaperweightAdapter parent;
// ------------------------------------------------------------------------
// Code that may break between versions of Minecraft
// ------------------------------------------------------------------------
private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil();
private char[] ibdToStateOrdinal = null;
private int[] ordinalToIbdID = null;
private boolean initialised = false;
private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter();
}
@Nullable
private static String getEntityId(Entity entity) {
ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType());
return resourceLocation == null ? null : resourceLocation.toString();
}
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent;
}
@SuppressWarnings("unchecked")
private synchronized boolean init() {
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false;
}
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState blockState = BlockTypesCache.states[i];
PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial();
int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState());
char ordinal = blockState.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
}
Map<String, List<Property<?>>> properties = new HashMap<>();
try {
for (Field field : BlockStateProperties.class.getDeclaredFields()) {
Object obj = field.get(null);
if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property<?> state)) {
continue;
}
Property<?> property;
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
property = new BooleanProperty(
state.getName(),
(List<Boolean>) ImmutableList.copyOf(state.getPossibleValues())
);
} else if (state instanceof DirectionProperty) {
property = new DirectionalProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase()))
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
property = new EnumProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> ((StringRepresentable) e).getSerializedName())
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
property = new IntegerProperty(
state.getName(),
(List<Integer>) ImmutableList.copyOf(state.getPossibleValues())
);
} else {
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state
.getClass()
.getSimpleName());
}
properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> {
if (v == null) {
v = new ArrayList<>(Collections.singletonList(property));
} else {
v.add(property);
}
return v;
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
allBlockProperties = ImmutableMap.copyOf(properties);
}
initialised = true;
return true;
}
@Override
public BlockMaterial getMaterial(BlockType blockType) {
Block block = getBlock(blockType);
return new PaperweightBlockMaterial(block);
}
@Override
public synchronized BlockMaterial getMaterial(BlockState state) {
net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
return new PaperweightBlockMaterial(blockState.getBlock(), blockState);
}
public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
}
@Deprecated
@Override
public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
if (state.getBlockType().getMaterial().hasContainer()) {
// Read the NBT data
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.save(new net.minecraft.nbt.CompoundTag());
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
}
}
return state.toBaseBlock();
}
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
}
@SuppressWarnings("rawtypes")
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
if (section == null) {
if (blockState.isAir()) {
return true;
}
levelChunkSections[y4] = section = new LevelChunkSection(y4 << 4);
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess(
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
}
@Override
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
Preconditions.checkNotNull(entity);
CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle();
String id = getEntityId(mcEntity);
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
tags.put("Id", StringBinaryTag.of(id));
return CompoundBinaryTag.from(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
return null;
}
}
@Override
public Component getRichBlockName(BlockType blockType) {
return parent.getRichBlockName(blockType);
}
@Override
public Component getRichItemName(ItemType itemType) {
return parent.getRichItemName(itemType);
}
@Override
public Component getRichItemName(BaseItemStack itemStack) {
return parent.getRichItemName(itemStack);
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState();
return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState));
}
@Override
public BlockState adapt(BlockData blockData) {
CraftBlockData cbd = ((CraftBlockData) blockData);
net.minecraft.world.level.block.state.BlockState ibd = cbd.getState();
return adapt(ibd);
}
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
return BlockTypesCache.states[adaptToChar(blockState)];
}
public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) {
int id = Block.BLOCK_STATE_REGISTRY.getId(blockState);
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
try {
init();
return ibdToStateOrdinal[id];
} catch (ArrayIndexOutOfBoundsException e1) {
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
);
return BlockTypesCache.ReservedIDs.AIR;
}
}
}
public char ibdIDToOrdinal(int id) {
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
init();
return ibdToStateOrdinal[id];
}
}
@Override
public char[] getIbdToStateOrdinal() {
if (initialised) {
return ibdToStateOrdinal;
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal;
}
init();
return ibdToStateOrdinal;
}
}
public int ordinalToIbdID(char ordinal) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
init();
return ordinalToIbdID[ordinal];
}
}
@Override
public int[] getOrdinalToIbdID() {
if (initialised) {
return ordinalToIbdID;
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID;
}
init();
return ordinalToIbdID;
}
}
@Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
return material.getCraftBlockData();
}
@Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle();
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) {
boolean flag = false;
// PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
*/ Stream.empty();
ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle();
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
.forEach(entityPlayer -> {
synchronized (chunkPacket) {
ClientboundLevelChunkPacket nmsPacket = (ClientboundLevelChunkPacket) chunkPacket.getNativePacket();
if (nmsPacket == null) {
nmsPacket = mapUtil.create(this, chunkPacket);
chunkPacket.setNativePacket(nmsPacket);
}
try {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
entityPlayer.connection.send(nmsPacket);
} finally {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
}
}
});
}
}
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
return getParent().getProperties(blockType);
}
@Override
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
);
}
@Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount()
);
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNativeBinary(baseItemStack.getNbt())));
return CraftItemStack.asCraftMirror(stack);
}
@Override
public boolean generateTree(
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
org.bukkit.World bukkitWorld
) {
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) {
blockVector3 = blockVector3.add(
0,
1,
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back
}
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle();
final BlockVector3 finalBlockVector = blockVector3;
// Sync to main thread to ensure no clashes occur
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> {
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true;
try {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
}
@Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
// Quickly add each entity to a list copy.
List<Entity> mcEntities = new ArrayList<>();
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>();
mcEntities.forEach((mcEnt) -> {
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity();
if (bukkitEntity.isValid()) {
list.add(bukkitEntity);
}
});
return list;
}
@Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack;
}
@Override
public Tag toNative(net.minecraft.nbt.Tag foreign) {
return parent.toNative(foreign);
}
@Override
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
if (foreign instanceof PaperweightLazyCompoundTag) {
return ((PaperweightLazyCompoundTag) foreign).get();
}
return parent.fromNative(foreign);
}
@Override
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
}
@Override
public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) {
return new PaperweightGetBlocks(world, chunkX, chunkZ);
}
@Override
public int getInternalBiomeId(BiomeType biomeType) {
final Registry<Biome> registry = MinecraftServer
.getServer()
.registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
Biome biome = registry.get(resourceLocation);
return registry.getId(biome);
}
@Override
public Iterable<NamespacedKey> getRegisteredBiomes() {
WritableRegistry<Biome> biomeRegistry = ((CraftServer) Bukkit.getServer())
.getServer()
.registryAccess()
.ownedRegistryOrThrow(
Registry.BIOME_REGISTRY);
List<ResourceLocation> keys = biomeRegistry.stream()
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
List<NamespacedKey> namespacedKeys = new ArrayList<>();
for (ResourceLocation key : keys) {
try {
namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key));
} catch (IllegalArgumentException e) {
LOGGER.error("Error converting biome key {}", key.toString(), e);
}
}
return namespacedKeys;
}
@Override
public RelighterFactory getRelighterFactory() {
try {
Class.forName("ca.spottedleaf.starlight.light.StarLightEngine");
if (PaperweightStarlightRelighter.isUsable()) {
return new PaperweightStarlightRelighterFactory();
}
} catch (ThreadDeath td) {
throw td;
} catch (Throwable ignored) {
}
return new NMSRelighterFactory();
}
@Override
public Map<String, List<Property<?>>> getAllProperties() {
if (initialised) {
return allBlockProperties;
}
synchronized (this) {
if (initialised) {
return allBlockProperties;
}
init();
return allBlockProperties;
}
}
@Override
public IBatchProcessor getTickingPostProcessor() {
return new PaperweightPostProcessor();
}
}

Datei anzeigen

@ -0,0 +1,286 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.task.RunnableVal;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private static final Direction[] NEIGHBOUR_ORDER = {
Direction.EAST,
Direction.WEST,
Direction.DOWN,
Direction.UP,
Direction.NORTH,
Direction.SOUTH
};
private final PaperweightFaweAdapter paperweightFaweAdapter;
private final WeakReference<Level> level;
private final AtomicInteger lastTick;
private final Set<CachedChange> cachedChanges = new HashSet<>();
private final Set<IntPair> cachedChunksToSend = new HashSet<>();
private SideEffectSet sideEffectSet;
public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference<Level> level) {
this.paperweightFaweAdapter = paperweightFaweAdapter;
this.level = level;
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
}
private Level getLevel() {
return Objects.requireNonNull(level.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getLevel().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) {
int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) {
return levelChunk.getBlockState(blockPos);
}
@Nullable
@Override
public synchronized net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
}
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) {
lastTick.set(currentTick);
}
flushAsync(nextTick);
}
return blockState;
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState blockState,
BlockPos blockPos
) {
return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos blockPos) {
getLevel().getChunkSource().getLightEngine().checkBlock(blockPos);
}
@Override
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
// We will assume that the tile entity was created for us,
// though we do not do this on the other versions
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
if (blockEntity == null) {
return false;
}
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
blockEntity.load((CompoundTag) nativeTag);
return true;
}
@Override
public void notifyBlockUpdate(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos);
}
}
@Override
public void notifyNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
Level level = getLevel();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
level.blockUpdated(blockPos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
// Un-nest neighbour updating
for (Direction direction : NEIGHBOUR_ORDER) {
BlockPos shifted = blockPos.relative(direction);
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
}
}
if (newState.hasAnalogOutputSignal()) {
level.updateNeighbourForOutputSignal(blockPos, newState.getBlock());
}
}
@Override
public void updateNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
Level level = getLevel();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = level.getWorld();
if (craftWorld != null) {
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
CraftBlockData.fromData(newState)
);
level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
}
newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getLevel().onBlockStateChange(blockPos, oldState, newState);
}
private synchronized void flushAsync(final boolean sendChunks) {
final Set<CachedChange> changes = Set.copyOf(cachedChanges);
cachedChanges.clear();
final Set<IntPair> toSend;
if (sendChunks) {
toSend = Set.copyOf(cachedChunksToSend);
cachedChunksToSend.clear();
} else {
toSend = Collections.emptySet();
}
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
if (!sendChunks) {
return;
}
for (IntPair chunk : toSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
}
@Override
public synchronized void flush() {
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
for (IntPair chunk : cachedChunksToSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
if (Fawe.isMainThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
}
cachedChanges.clear();
cachedChunksToSend.clear();
}
private record CachedChange(
LevelChunk levelChunk,
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
}
}

Datei anzeigen

@ -0,0 +1,245 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.LevelChunk;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet {
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks;
private final int minHeight;
private final int maxHeight;
final ServerLevel serverLevel;
final LevelChunk levelChunk;
private ChunkBiomeContainer chunkBiomeContainer;
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
this.levelChunk = levelChunk;
this.serverLevel = levelChunk.level;
this.minHeight = serverLevel.getMinBuildHeight();
this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive.
this.blocks = new char[getSectionCount()][];
}
protected void storeTile(BlockEntity blockEntity) {
tiles.put(
BlockVector3.at(
blockEntity.getBlockPos().getX(),
blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ()
),
new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.save(new net.minecraft.nbt.CompoundTag())))
);
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return tiles;
}
@Override
@Nullable
public CompoundTag getTile(int x, int y, int z) {
return tiles.get(BlockVector3.at(x, y, z));
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
entity.save(compoundTag);
entities.add((CompoundTag) adapter.toNative(compoundTag));
}
@Override
public Set<CompoundTag> getEntities() {
return this.entities;
}
@Override
public CompoundTag getEntity(UUID uuid) {
for (CompoundTag tag : entities) {
if (uuid.equals(tag.getUUID())) {
return tag;
}
}
return null;
}
@Override
public boolean isCreateCopy() {
return false;
}
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setHeightmapToGet(HeightMapType type, int[] data) {
}
@Override
public int getMaxY() {
return maxHeight;
}
@Override
public int getMinY() {
return minHeight;
}
@Override
public int getMaxSectionPosition() {
return maxHeight >> 4;
}
@Override
public int getMinSectionPosition() {
return minHeight >> 4;
}
protected void storeBiomes(ChunkBiomeContainer chunkBiomeContainer) {
// The to do one line below is pre-paperweight and needs to be revised
// TODO revisit last parameter, BiomeStorage[] *would* be more efficient
this.chunkBiomeContainer = new ChunkBiomeContainer(chunkBiomeContainer.biomeRegistry, serverLevel,
chunkBiomeContainer.writeBiomes()
);
}
@Override
public BiomeType getBiomeType(int x, int y, int z) {
Biome biome = null;
if (y == -1) {
for (y = serverLevel.getMinBuildHeight(); y <= serverLevel.getMaxBuildHeight(); y += 4) {
biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2);
if (biome != null) {
break;
}
}
} else {
biome = this.chunkBiomeContainer.getNoiseBiome(x >> 2, y >> 2, z >> 2);
}
return biome != null ? PaperweightPlatformAdapter.adapt(biome, serverLevel) : null;
}
@Override
public void removeSectionLighting(int layer, boolean sky) {
}
@Override
public boolean trim(boolean aggressive, int layer) {
return false;
}
@Override
public IBlocks reset() {
return null;
}
@Override
public int getSectionCount() {
return serverLevel.getSectionsCount();
}
protected void storeSection(int layer, char[] data) {
blocks[layer] = data;
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)];
return state.toBaseBlock(this, x, y, z);
}
@Override
public boolean hasSection(int layer) {
layer -= getMinSectionPosition();
return blocks[layer] != null;
}
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public char[] loadIfPresent(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)];
}
@Override
public int getSkyLight(int x, int y, int z) {
return 0;
}
@Override
public int getEmittedLight(int x, int y, int z) {
return 0;
}
@Override
public int[] getHeightMap(HeightMapType type) {
return new int[0];
}
@Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
return null;
}
public char get(int x, int y, int z) {
final int layer = (y >> 4) - getMinSectionPosition();
final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index];
}
@Override
public boolean trim(boolean aggressive) {
return false;
}
}

Datei anzeigen

@ -0,0 +1,32 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkPacket> {
public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("x", "b"));
fieldBitMask = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("z", "c"));
fieldHeightMap = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("availableSections", "d"));
fieldChunkData = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("biomes", "f"));
fieldBlockEntities = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("buffer", "g"));
fieldFull = ClientboundLevelChunkPacket.class.getDeclaredField(Refraction.pickName("blockEntitiesTags", "h"));
fieldX.setAccessible(true);
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
}
@Override
public ClientboundLevelChunkPacket createPacket() {
// TODO ??? return new ClientboundLevelChunkPacket();
throw new UnsupportedOperationException();
}
}

Datei anzeigen

@ -0,0 +1,511 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.mojang.datafixers.util.Either;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket;
import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.BitStorage;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.gameevent.GameEventDispatcher;
import net.minecraft.world.level.gameevent.GameEventListener;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
import sun.misc.Unsafe;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.stream.Stream;
public final class PaperweightPlatformAdapter extends NMSAdapter {
public static final Field fieldStorage;
public static final Field fieldPalette;
public static final Field fieldBits;
public static final Field fieldBitsPerEntry;
private static final Field fieldTickingFluidContent;
private static final Field fieldTickingBlockCount;
private static final Field fieldNonEmptyBlockCount;
private static final Field fieldBiomes;
private static final MethodHandle methodGetVisibleChunk;
private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;
private static final Field fieldLock;
private static final long fieldLockOffset;
private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveBlockEntityTicker;
private static final Field fieldRemove;
private static final Logger LOGGER = LogManagerCompat.getLogger();
static {
try {
fieldBits = PalettedContainer.class.getDeclaredField(Refraction.pickName("bits", "l"));
fieldBits.setAccessible(true);
fieldStorage = PalettedContainer.class.getDeclaredField(Refraction.pickName("storage", "c"));
fieldStorage.setAccessible(true);
fieldPalette = PalettedContainer.class.getDeclaredField(Refraction.pickName("palette", "k"));
fieldPalette.setAccessible(true);
fieldBitsPerEntry = BitStorage.class.getDeclaredField(Refraction.pickName("bits", "c"));
fieldBitsPerEntry.setAccessible(true);
fieldTickingFluidContent = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
fieldTickingFluidContent.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
fieldNonEmptyBlockCount.setAccessible(true);
fieldBiomes = ChunkBiomeContainer.class.getDeclaredField(Refraction.pickName("biomes", "f"));
fieldBiomes.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
"getVisibleChunkIfPresent",
"getVisibleChunk"
), long.class);
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
} else {
// in paper, the used methods are synchronized properly
fieldLock = null;
fieldLockOffset = -1;
}
fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
"gameEventDispatcherSections", "x"));
fieldGameEventDispatcherSections.setAccessible(true);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName(
"removeBlockEntityTicker",
"l"
), BlockPos.class
);
removeBlockEntityTicker.setAccessible(true);
methodremoveBlockEntityTicker = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
rethrow.printStackTrace();
throw new RuntimeException(rethrow);
}
}
static boolean setSectionAtomic(
LevelChunkSection[] sections,
LevelChunkSection expected,
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
}
return false;
}
// There is no point in having a functional semaphore for paper servers.
private static final ThreadLocal<DelegateSemaphore> SEMAPHORE_THREAD_LOCAL =
ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null));
static DelegateSemaphore applyLock(LevelChunkSection section) {
if (PaperLib.isPaper()) {
return SEMAPHORE_THREAD_LOCAL.get();
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
Semaphore currentLock = (Semaphore) unsafe.getObject(blocks, fieldLockOffset);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(blocks, fieldLockOffset, newLock);
return newLock;
}
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) {
if (!PaperLib.isPaper()) {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false);
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
try {
CraftChunk chunk;
try {
chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
String world = serverLevel.getWorld().getName();
// We've already taken 10 seconds we can afford to wait a little here.
boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null);
if (loaded) {
LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world);
// Retry chunk load
chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get();
} else {
throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!");
}
}
return chunk.getHandle();
} catch (Throwable e) {
e.printStackTrace();
}
}
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
}
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
// Ensure chunk is definitely loaded before applying a ticket
net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
.getChunkSource()
.addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
}
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap;
try {
return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ));
} catch (Throwable thr) {
throw new RuntimeException(thr);
}
}
@SuppressWarnings("unchecked")
public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) {
ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ);
if (chunkHolder == null) {
return;
}
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
// UNLOADED_CHUNK
Optional<LevelChunk> optional = ((Either) chunkHolder
.getTickingChunkFuture()
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only
optional = optional.or(() -> Optional.ofNullable(nmsWorld
.getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ)));
}
if (optional.isEmpty()) {
return;
}
LevelChunk levelChunk = optional.get();
TaskManager.taskManager().task(() -> {
ClientboundLevelChunkPacket chunkPacket = new ClientboundLevelChunkPacket(levelChunk);
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(chunkPacket));
if (lighting) {
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
boolean trustEdges = true;
ClientboundLightUpdatePacket packet =
new ClientboundLightUpdatePacket(coordIntPair, nmsWorld.getChunkSource().getLightEngine(), null, null,
trustEdges
);
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
}
});
}
private static Stream<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
}
/*
NMS conversion
*/
public static LevelChunkSection newChunkSection(
final int layer,
final char[] blocks,
boolean fastMode,
CachedBukkitAdapter adapter
) {
return newChunkSection(layer, null, blocks, fastMode, adapter);
}
public static LevelChunkSection newChunkSection(
final int layer,
final Function<Integer, char[]> get,
char[] set,
boolean fastMode,
CachedBukkitAdapter adapter
) {
if (set == null) {
return newChunkSection(layer);
}
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get();
final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get();
try {
int num_palette;
final short[] nonEmptyBlockCount = fastMode ? new short[1] : null;
if (get == null) {
num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, nonEmptyBlockCount);
} else {
num_palette = createPalette(
layer,
blockToPalette,
paletteToBlock,
blocksCopy,
get,
set,
adapter,
nonEmptyBlockCount
);
}
// BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.settings().PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
}
if (bitsPerEntry > 8) {
bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1);
}
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntry);
final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong);
if (num_palette == 1) {
for (int i = 0; i < blockBitArrayEnd; i++) {
blockStates[i] = 0;
}
} else {
final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntry, 4096, blockStates);
bitArray.fromRaw(blocksCopy);
}
LevelChunkSection levelChunkSection = newChunkSection(layer);
// set palette & data bits
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks =
levelChunkSection.getStates();
// private DataPalette<T> h;
// protected DataBits a;
final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd);
final BitStorage nmsBits = new BitStorage(bitsPerEntry, 4096, bits);
final Palette<net.minecraft.world.level.block.state.BlockState> blockStatePalettedContainer;
if (bitsPerEntry <= 4) {
blockStatePalettedContainer = new LinearPalette<>(Block.BLOCK_STATE_REGISTRY, bitsPerEntry, dataPaletteBlocks,
NbtUtils::readBlockState
);
} else if (bitsPerEntry < 9) {
blockStatePalettedContainer = new HashMapPalette<>(
Block.BLOCK_STATE_REGISTRY,
bitsPerEntry,
dataPaletteBlocks,
NbtUtils::readBlockState,
NbtUtils::writeBlockState
);
} else {
blockStatePalettedContainer = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE;
}
// set palette if required
if (bitsPerEntry < 9) {
for (int i = 0; i < num_palette; i++) {
final int ordinal = paletteToBlock[i];
blockToPalette[ordinal] = Integer.MAX_VALUE;
final BlockState state = BlockTypesCache.states[ordinal];
final net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
blockStatePalettedContainer.idFor(blockState);
}
}
try {
fieldStorage.set(dataPaletteBlocks, nmsBits);
fieldPalette.set(dataPaletteBlocks, blockStatePalettedContainer);
fieldBits.set(dataPaletteBlocks, bitsPerEntry);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
if (!fastMode) {
levelChunkSection.recalcBlockCounts();
} else {
try {
fieldNonEmptyBlockCount.set(levelChunkSection, nonEmptyBlockCount[0]);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return levelChunkSection;
} catch (final Throwable e) {
throw e;
} finally {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
Arrays.fill(paletteToBlock, Integer.MAX_VALUE);
Arrays.fill(blockStates, 0);
Arrays.fill(blocksCopy, 0);
}
}
private static LevelChunkSection newChunkSection(int layer) {
return new LevelChunkSection(layer);
}
public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException {
fieldTickingFluidContent.setShort(section, (short) 0);
fieldTickingBlockCount.setShort(section, (short) 0);
}
public static Biome[] getBiomeArray(ChunkBiomeContainer chunkBiomeContainer) {
try {
return (Biome[]) fieldBiomes.get(chunkBiomeContainer);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static BiomeType adapt(Biome biome, LevelAccessor levelAccessor) {
ResourceLocation resourceLocation = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getKey(
biome);
if (resourceLocation == null) {
return levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY).getId(biome) == -1
? BiomeTypes.OCEAN
: null;
}
return BiomeTypes.get(resourceLocation.toString().toLowerCase(Locale.ROOT));
}
@SuppressWarnings("unchecked")
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try {
// Do the method ourselves to avoid trying to reflect generic method parameters
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) {
if (!levelChunk.level.isClientSide) {
Block block = beacon.getBlockState().getBlock();
if (block instanceof EntityBlock) {
GameEventListener gameEventListener = ((EntityBlock) block).getListener(levelChunk.level, beacon);
if (gameEventListener != null) {
int i = SectionPos.blockToSectionCoord(beacon.getBlockPos().getY());
GameEventDispatcher gameEventDispatcher = levelChunk.getEventDispatcher(i);
gameEventDispatcher.unregister(gameEventListener);
if (gameEventDispatcher.isEmpty()) {
try {
((Int2ObjectMap<GameEventDispatcher>) fieldGameEventDispatcherSections.get(levelChunk))
.remove(i);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
fieldRemove.set(beacon, true);
}
}
methodremoveBlockEntityTicker.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(chunk.getPos());
}
}

Datei anzeigen

@ -0,0 +1,175 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.registry.state.PropertyKey;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import javax.annotation.Nullable;
public class PaperweightPostProcessor implements IBatchProcessor {
@Override
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
return set;
}
@SuppressWarnings("deprecation")
@Override
public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) {
boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS;
// The PostProcessor shouldn't be added, but just in case
if (!tickFluid) {
return;
}
PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet;
layer:
for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) {
char[] set = iChunkSet.loadIfPresent(layer);
if (set == null) {
// No edit means no need to process
continue;
}
char[] get = null;
for (int i = 0; i < 4096; i++) {
char ordinal = set[i];
char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
boolean fromGet = false; // Used for liquids
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
if (get == null) {
get = getBlocks.load(layer);
}
// If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't
// actually being set
if (get == null) {
continue layer;
}
fromGet = true;
ordinal = replacedOrdinal = get[i];
}
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
continue;
} else if (!fromGet) { // if fromGet, don't do the same again
if (get == null) {
get = getBlocks.load(layer);
}
replacedOrdinal = get[i];
}
boolean ticking = BlockTypesCache.ticking[ordinal];
boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal];
boolean replacedWasLiquid = false;
BlockState replacedState = null;
if (!ticking) {
// If the block being replaced was not ticking, it cannot be a liquid
if (!replacedWasTicking) {
continue;
}
// If the block being replaced is not fluid, we do not need to worry
if (!(replacedWasLiquid =
(replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) {
continue;
}
}
BlockState state = BlockState.getFromOrdinal(ordinal);
boolean liquid = state.getMaterial().isLiquid();
int x = i & 15;
int y = (i >> 8) & 15;
int z = (i >> 4) & 15;
BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z);
if (liquid || replacedWasLiquid) {
if (liquid) {
addFluid(getBlocks.serverLevel, state, position);
continue;
}
// If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this
// may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up
// being ticked anyway. We only need it to be "hit" once.
if (!wasAdjacentToWater(get, set, i, x, y, z)) {
continue;
}
addFluid(getBlocks.serverLevel, replacedState, position);
}
}
}
}
@Nullable
@Override
public Extent construct(final Extent child) {
throw new UnsupportedOperationException("Processing only");
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.READING_SET_BLOCKS;
}
private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) {
if (set == null || get == null) {
return false;
}
char ordinal;
char reserved = BlockTypesCache.ReservedIDs.__RESERVED__;
if (x > 0 && set[i - 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) {
return true;
}
}
if (x < 15 && set[i + 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) {
return true;
}
}
if (z > 0 && set[i - 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) {
return true;
}
}
if (z < 15 && set[i + 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) {
return true;
}
}
if (y > 0 && set[i - 256] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) {
return true;
}
}
if (y < 15 && set[i + 256] != reserved) {
return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal);
}
return false;
}
@SuppressWarnings("deprecation")
private boolean isFluid(char ordinal) {
return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid();
}
@SuppressWarnings("deprecation")
private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) {
Fluid type;
if (replacedState.getBlockType() == BlockTypes.LAVA) {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA;
} else {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
}
serverLevel.getLiquidTicks().scheduleTick(
position,
type,
type.getTickDelay(serverLevel)
);
}
}

Datei anzeigen

@ -1,24 +1,24 @@
package com.boydti.fawe.bukkit.adapter.mc1_16_5;
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.boydti.fawe.beta.IQueueChunk;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.lighting.NMSRelighter;
import com.boydti.fawe.beta.implementation.lighting.Relighter;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.v1_16_R3.ChunkCoordIntPair;
import net.minecraft.server.v1_16_R3.ChunkStatus;
import net.minecraft.server.v1_16_R3.LightEngineThreaded;
import net.minecraft.server.v1_16_R3.MCUtil;
import net.minecraft.server.v1_16_R3.TicketType;
import net.minecraft.server.v1_16_R3.Unit;
import net.minecraft.server.v1_16_R3.WorldServer;
import net.minecraft.server.MCUtil;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandle;
@ -33,31 +33,22 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
public class TuinityRelighter_1_16_5 implements Relighter {
public class PaperweightStarlightRelighter implements Relighter {
public static final MethodHandle RELIGHT;
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final MethodHandle RELIGHT;
private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32
private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting
private static final TicketType<Unit> FAWE_TICKET = TicketType.a("fawe_ticket", (a, b) -> 0);
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT);
private final WorldServer world;
private final ReentrantLock lock = new ReentrantLock();
private final Long2ObjectLinkedOpenHashMap<LongSet> regions = new Long2ObjectLinkedOpenHashMap<>();
private final ReentrantLock areaLock = new ReentrantLock();
private final NMSRelighter delegate;
static {
MethodHandle tmp = null;
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
tmp = lookup.findVirtual(LightEngineThreaded.class,
tmp = lookup.findVirtual(
ThreadedLevelLightEngine.class,
"relight",
MethodType.methodType(
int.class, // return type
@ -68,15 +59,25 @@ public class TuinityRelighter_1_16_5 implements Relighter {
)
);
} catch (NoSuchMethodException | IllegalAccessException e) {
LOGGER.error("Failed to locate relight method in LightEngineThreaded on Tuinity. " +
"Is everything up to date?", e);
LOGGER.error("Failed to locate 'relight' method in ThreadedLevelLightEngine. Is everything up to date?", e);
}
RELIGHT = tmp;
}
public TuinityRelighter_1_16_5(WorldServer world, IQueueExtent<IQueueChunk> queue) {
this.world = world;
this.delegate = new NMSRelighter(queue, false);
private final ServerLevel serverLevel;
private final ReentrantLock lock = new ReentrantLock();
private final Long2ObjectLinkedOpenHashMap<LongSet> regions = new Long2ObjectLinkedOpenHashMap<>();
private final ReentrantLock areaLock = new ReentrantLock();
private final NMSRelighter delegate;
@SuppressWarnings("rawtypes")
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<IQueueChunk> queue) {
this.serverLevel = serverLevel;
this.delegate = new NMSRelighter(queue);
}
public static boolean isUsable() {
return RELIGHT != null;
}
@Override
@ -86,7 +87,7 @@ public class TuinityRelighter_1_16_5 implements Relighter {
long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2);
// TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH?
LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2));
chunks.add(ChunkCoordIntPair.pair(cx, cz));
chunks.add(ChunkPos.asLong(cx, cz));
} finally {
areaLock.unlock();
}
@ -107,7 +108,9 @@ public class TuinityRelighter_1_16_5 implements Relighter {
public void fixLightingSafe(boolean sky) {
this.areaLock.lock();
try {
if (regions.isEmpty()) return;
if (regions.isEmpty()) {
return;
}
LongSet first = regions.removeFirst();
fixLighting(first, () -> fixLightingSafe(true));
} finally {
@ -121,46 +124,53 @@ public class TuinityRelighter_1_16_5 implements Relighter {
* (as required by the server).
*/
private void fixLighting(LongSet chunks, Runnable andThen) {
// convert from long keys to ChunkCoordIntPairs
Set<ChunkCoordIntPair> coords = new HashSet<>();
// convert from long keys to ChunkPos
Set<ChunkPos> coords = new HashSet<>();
LongIterator iterator = chunks.iterator();
while (iterator.hasNext()) {
coords.add(new ChunkCoordIntPair(iterator.nextLong()));
coords.add(new ChunkPos(iterator.nextLong()));
}
TaskManager.IMP.task(() -> {
TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkCoordIntPair pos : coords) {
futures.add(world.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> world.getChunkProvider().addTicketAtLevel(
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE))
Unit.INSTANCE
))
);
}
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v ->
invokeRelight(coords,
c -> { }, // no callback for single chunks required
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed " + i + " chunks instead of " + coords.size());
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.IMP.task(() -> postProcessChunks(coords));
TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads
TaskManager.IMP.async(andThen);
})
TaskManager.taskManager().async(andThen);
}
)
);
});
}
private void invokeRelight(Set<ChunkCoordIntPair> coords,
Consumer<ChunkCoordIntPair> chunkCallback,
IntConsumer processCallback) {
private void invokeRelight(
Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback,
IntConsumer processCallback
) {
try {
int unused = (int) RELIGHT.invokeExact(world.getChunkProvider().getLightEngine(),
int unused = (int) RELIGHT.invokeExact(
serverLevel.getChunkSource().getLightEngine(),
coords,
chunkCallback, // callback per chunk
processCallback // callback for all chunks
@ -174,15 +184,15 @@ public class TuinityRelighter_1_16_5 implements Relighter {
* Allow the server to unload the chunks again.
* Also, if chunk packets are sent delayed, we need to do that here
*/
private void postProcessChunks(Set<ChunkCoordIntPair> coords) {
boolean delay = Settings.IMP.LIGHTING.DELAY_PACKET_SENDING;
for (ChunkCoordIntPair pos : coords) {
private void postProcessChunks(Set<ChunkPos> coords) {
boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
for (ChunkPos pos : coords) {
int x = pos.x;
int z = pos.z;
if (delay) { // we still need to send the block changes of that chunk
BukkitAdapter_1_16_5.sendChunk(world, x, z, false);
PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false);
}
world.getChunkProvider().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
}
}
@ -225,4 +235,5 @@ public class TuinityRelighter_1_16_5 implements Relighter {
public void close() throws Exception {
fixLightingSafe(true);
}
}

Datei anzeigen

@ -0,0 +1,29 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import javax.annotation.Nonnull;
public class PaperweightStarlightRelighterFactory implements RelighterFactory {
@Override
public @Nonnull
@SuppressWarnings("rawtypes")
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
org.bukkit.World w = Bukkit.getWorld(world.getName());
if (w == null) {
return NullRelighter.INSTANCE;
}
return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue);
}
}

Datei anzeigen

@ -0,0 +1,161 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.nbt;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.LazyCompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import net.minecraft.nbt.NumericTag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class PaperweightLazyCompoundTag extends LazyCompoundTag {
private final Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier;
private CompoundTag compoundTag;
public PaperweightLazyCompoundTag(Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier) {
super(new HashMap<>());
this.compoundTagSupplier = compoundTagSupplier;
}
public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) {
this(() -> compoundTag);
}
public net.minecraft.nbt.CompoundTag get() {
return compoundTagSupplier.get();
}
@Override
@SuppressWarnings("unchecked")
public Map<String, Tag> getValue() {
if (compoundTag == null) {
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
}
return compoundTag.getValue();
}
@Override
public CompoundBinaryTag asBinaryTag() {
getValue();
return compoundTag.asBinaryTag();
}
public boolean containsKey(String key) {
return compoundTagSupplier.get().contains(key);
}
public byte[] getByteArray(String key) {
return compoundTagSupplier.get().getByteArray(key);
}
public byte getByte(String key) {
return compoundTagSupplier.get().getByte(key);
}
public double getDouble(String key) {
return compoundTagSupplier.get().getDouble(key);
}
public double asDouble(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsDouble();
}
return 0;
}
public float getFloat(String key) {
return compoundTagSupplier.get().getFloat(key);
}
public int[] getIntArray(String key) {
return compoundTagSupplier.get().getIntArray(key);
}
public int getInt(String key) {
return compoundTagSupplier.get().getInt(key);
}
public int asInt(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsInt();
}
return 0;
}
@SuppressWarnings("unchecked")
public List<Tag> getList(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
ArrayList<Tag> list = new ArrayList<>();
for (net.minecraft.nbt.Tag elem : nbtList) {
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
list.add(new PaperweightLazyCompoundTag(compoundTag));
} else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
}
}
return list;
}
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
public ListTag getListTag(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag) {
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
}
return new ListTag(StringTag.class, Collections.emptyList());
}
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
ListTag listTag = getListTag(key);
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
}
public long[] getLongArray(String key) {
return compoundTagSupplier.get().getLongArray(key);
}
public long getLong(String key) {
return compoundTagSupplier.get().getLong(key);
}
public long asLong(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsLong();
}
return 0;
}
public short getShort(String key) {
return compoundTagSupplier.get().getShort(key);
}
public String getString(String key) {
return compoundTagSupplier.get().getString(key);
}
@Override
public String toString() {
return compoundTagSupplier.get().toString();
}
}

Datei anzeigen

@ -0,0 +1,697 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_17_R1_2.PaperweightGetBlocks;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.io.file.SafeFiles;
import com.sk89q.worldedit.world.RegenOptions;
import io.papermc.lib.PaperLib;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.biome.Biomes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.LinearCongruentialGenerator;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.biome.OverworldBiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.SimpleRandomSource;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.levelgen.synth.ImprovedNoise;
import net.minecraft.world.level.newbiome.area.Area;
import net.minecraft.world.level.newbiome.area.AreaFactory;
import net.minecraft.world.level.newbiome.context.BigContext;
import net.minecraft.world.level.newbiome.layer.Layer;
import net.minecraft.world.level.newbiome.layer.Layers;
import net.minecraft.world.level.newbiome.layer.traits.PixelTransformer;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.CraftServer;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.generator.CustomChunkGenerator;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalLong;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier;
import java.util.function.LongFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field worldsField;
private static final Field paperConfigField;
private static final Field generateFlatBedrockField;
private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField;
private static final Field chunkSourceField;
//list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
static {
chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
chunkStati.put(
ChunkStatus.STRUCTURE_REFERENCES,
Concurrency.FULL
); // structure refs: radius 8, but only writes to current chunk
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(
ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
chunkStati.put(
ChunkStatus.LIGHT,
Concurrency.FULL
); // light: radius 1, but no writes to other chunks, only current chunk
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try {
worldsField = CraftServer.class.getDeclaredField("worlds");
worldsField.setAccessible(true);
Field tmpPaperConfigField;
Field tmpFlatBedrockField;
try { //only present on paper
tmpPaperConfigField = Level.class.getDeclaredField("paperConfig");
tmpPaperConfigField.setAccessible(true);
tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock");
tmpFlatBedrockField.setAccessible(true);
} catch (Exception e) {
tmpPaperConfigField = null;
tmpFlatBedrockField = null;
}
paperConfigField = tmpPaperConfigField;
generateFlatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "g"));
generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "e"));
generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "C"));
chunkSourceField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//runtime
private ServerLevel originalServerWorld;
private ServerChunkCache originalChunkProvider;
private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session;
private StructureManager structureManager;
private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator;
private Path tempDir;
private boolean generateFlatBedrock = false;
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
super(originalBukkitWorld, region, target, options);
}
@Override
protected boolean prepare() {
this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle();
originalChunkProvider = originalServerWorld.getChunkSource();
if (!(originalChunkProvider instanceof ServerChunkCache)) {
return false;
}
//flat bedrock? (only on paper)
if (paperConfigField != null) {
try {
generateFlatBedrock = generateFlatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) {
}
}
seed = options.getSeed().orElse(originalServerWorld.getSeed());
chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c));
return true;
}
@Override
protected boolean initNewWorld() throws Exception {
//world folder
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
//prepare for world init (see upstream implementation for reference)
org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment();
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
: originalOpts;
LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld",
originalWorldData.settings.gameType(),
originalWorldData.settings.hardcore(),
originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig()
);
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
//init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
server,
server.executor,
session,
newWorldData,
originalServerWorld.dimension(),
originalServerWorld.dimensionType(),
new RegenNoOpWorldLoadListener(),
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
newOpts.dimensions().get(levelStemResourceKey).generator(),
originalServerWorld.isDebug(),
seed,
ImmutableList.of(),
false,
environment,
generator,
biomeProvider
) {
private final Biome singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(
options
.getBiomeType()
.getId())) : null;
@Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
}
@Override
public Biome getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) {
return singleBiome;
}
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ);
}
}).get();
freshWorld.noSave = true;
removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
}
//generator
if (originalChunkProvider.getGenerator() instanceof FlatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = (FlatLevelGeneratorSettings) generatorSettingFlatField.get(
originalChunkProvider.getGenerator());
chunkGenerator = new FlatLevelSource(generatorSettingFlat);
} else if (originalChunkProvider.getGenerator() instanceof NoiseBasedChunkGenerator) {
Supplier<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Supplier<NoiseGeneratorSettings>) generatorSettingBaseSupplierField
.get(originalChunkProvider.getGenerator());
BiomeSource biomeSource;
if (options.hasBiomeType()) {
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options
.getBiomeType()
.getId())));
} else {
biomeSource = originalChunkProvider.getGenerator().getBiomeSource();
if (biomeSource instanceof OverworldBiomeSource) {
biomeSource = fastOverworldBiomeSource(biomeSource);
}
}
chunkGenerator = new NoiseBasedChunkGenerator(biomeSource, seed, generatorSettingBaseSupplier);
} else if (originalChunkProvider.getGenerator() instanceof CustomChunkGenerator) {
chunkGenerator = (ChunkGenerator) delegateField.get(originalChunkProvider.getGenerator());
} else {
LOGGER.error("Unsupported generator type {}", originalChunkProvider.getGenerator().getClass().getName());
return false;
}
if (generator != null) {
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable();
}
freshChunkProvider = new ServerChunkCache(
freshWorld,
session,
server.getFixerUpper(),
server.getStructureManager(),
server.executor,
chunkGenerator,
freshWorld.spigotConfig.viewDistance,
server.forceSynchronousWrites(),
new RegenNoOpWorldLoadListener(),
(chunkCoordIntPair, state) -> {
},
() -> server.overworld().getDataStorage()
) {
// redirect to LevelChunks created in #createChunks
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) {
ChunkAccess chunkAccess = getChunkAt(x, z);
if (chunkAccess == null && create) {
chunkAccess = createChunk(getProtoChunkAt(x, z));
}
return chunkAccess;
}
};
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
//let's start then
structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
return true;
}
@Override
protected void cleanup() {
try {
session.close();
} catch (Exception ignored) {
}
//shutdown chunk provider
try {
Fawe.instance().getQueueHandler().sync(() -> {
try {
freshChunkProvider.close(false);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (Exception ignored) {
}
//remove world from server
try {
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
} catch (Exception ignored) {
}
//delete directory
try {
SafeFiles.tryHardToDeleteDir(tempDir);
} catch (Exception ignored) {
}
}
@Override
protected ProtoChunk createProtoChunk(int x, int z) {
return PaperLib.isPaper()
? new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld, freshWorld) // paper
: new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld); // spigot
}
@Override
protected LevelChunk createChunk(ProtoChunk protoChunk) {
return new LevelChunk(
freshWorld,
protoChunk,
null // we don't want to add entities
);
}
@Override
protected ChunkStatusWrap getFullChunkStatus() {
return new ChunkStatusWrap(ChunkStatus.FULL);
}
@Override
protected List<BlockPopulator> getBlockPopulators() {
return originalServerWorld.getWorld().getPopulators();
}
@Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
}
@Override
protected IChunkCache<IChunkGet> initSourceQueueCache() {
return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) {
@Override
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) {
return getChunkAt(x, z);
}
};
}
//util
@SuppressWarnings("unchecked")
private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> {
try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) worldsField.get(Bukkit.getServer());
map.remove("faweregentempworld");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
return switch (env) {
case NETHER -> LevelStem.NETHER;
case THE_END -> LevelStem.END;
default -> LevelStem.OVERWORLD;
};
}
@SuppressWarnings({"unchecked", "rawtypes"})
private BiomeSource fastOverworldBiomeSource(BiomeSource biomeSource) throws Exception {
Field legacyBiomeInitLayerField = OverworldBiomeSource.class.getDeclaredField(
Refraction.pickName("legacyBiomeInitLayer", "i"));
legacyBiomeInitLayerField.setAccessible(true);
Field largeBiomesField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("largeBiomes", "j"));
largeBiomesField.setAccessible(true);
Field biomeRegistryField = OverworldBiomeSource.class.getDeclaredField(Refraction.pickName("biomes", "k"));
biomeRegistryField.setAccessible(true);
Field areaLazyField = Layer.class.getDeclaredField(Refraction.pickName("area", "b"));
areaLazyField.setAccessible(true);
Method initAreaFactoryMethod = Layers.class.getDeclaredMethod(
Refraction.pickName("getDefaultLayer", "a"),
boolean.class,
int.class,
int.class,
LongFunction.class
);
initAreaFactoryMethod.setAccessible(true);
//init new WorldChunkManagerOverworld
boolean legacyBiomeInitLayer = legacyBiomeInitLayerField.getBoolean(biomeSource);
boolean largebiomes = largeBiomesField.getBoolean(biomeSource);
Registry<Biome> biomeRegistryMojang = (Registry<Biome>) biomeRegistryField.get(biomeSource);
Registry<Biome> biomeRegistry;
if (options.hasBiomeType()) {
Biome biome = BuiltinRegistries.BIOME.get(ResourceLocation.tryParse(options.getBiomeType().getId()));
biomeRegistry = new MappedRegistry<>(
ResourceKey.createRegistryKey(new ResourceLocation("fawe_biomes")),
Lifecycle.experimental()
);
((MappedRegistry) biomeRegistry).registerMapping(0, BuiltinRegistries.BIOME.getResourceKey(biome).get(), biome,
Lifecycle.experimental()
);
} else {
biomeRegistry = biomeRegistryMojang;
}
//replace genLayer
AreaFactory<FastAreaLazy> factory = (AreaFactory<FastAreaLazy>) initAreaFactoryMethod.invoke(
null,
legacyBiomeInitLayer,
largebiomes ? 6 : 4,
4,
(LongFunction) (salt -> new FastWorldGenContextArea(seed, salt))
);
biomeSource = new FastOverworldBiomeSource(biomeRegistry, new FastGenLayer(factory));
return biomeSource;
}
private static class FastOverworldBiomeSource extends BiomeSource {
private final Registry<Biome> biomeRegistry;
private final boolean isSingleRegistry;
private final FastGenLayer fastGenLayer;
public FastOverworldBiomeSource(
Registry<Biome> biomeRegistry,
FastGenLayer genLayer
) {
super(biomeRegistry.stream().collect(Collectors.toList()));
this.biomeRegistry = biomeRegistry;
this.isSingleRegistry = biomeRegistry.entrySet().size() == 1;
this.fastGenLayer = genLayer;
}
@Override
protected Codec<? extends BiomeSource> codec() {
return OverworldBiomeSource.CODEC;
}
@Override
public BiomeSource withSeed(final long seed) {
return null;
}
@Override
public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (this.isSingleRegistry) {
return this.biomeRegistry.byId(0);
}
return this.fastGenLayer.get(this.biomeRegistry, biomeX, biomeZ);
}
}
private static class FastWorldGenContextArea implements BigContext<FastAreaLazy> {
private final ConcurrentHashMap<Long, Integer> sharedAreaMap = new ConcurrentHashMap<>();
private final ImprovedNoise improvedNoise;
private final long magicrandom;
private final ConcurrentHashMap<Long, Long> map = new ConcurrentHashMap<>(); //needed for multithreaded generation
public FastWorldGenContextArea(long seed, long lconst) {
this.magicrandom = mix(seed, lconst);
this.improvedNoise = new ImprovedNoise(new SimpleRandomSource(seed));
}
private static long mix(long seed, long salt) {
long l = LinearCongruentialGenerator.next(salt, salt);
l = LinearCongruentialGenerator.next(l, salt);
l = LinearCongruentialGenerator.next(l, salt);
long m = LinearCongruentialGenerator.next(seed, l);
m = LinearCongruentialGenerator.next(m, l);
m = LinearCongruentialGenerator.next(m, l);
return m;
}
@Override
public FastAreaLazy createResult(PixelTransformer pixelTransformer) {
return new FastAreaLazy(sharedAreaMap, pixelTransformer);
}
@Override
public void initRandom(long x, long z) {
long l = this.magicrandom;
l = LinearCongruentialGenerator.next(l, x);
l = LinearCongruentialGenerator.next(l, z);
l = LinearCongruentialGenerator.next(l, x);
l = LinearCongruentialGenerator.next(l, z);
this.map.put(Thread.currentThread().getId(), l);
}
@Override
public int nextRandom(int y) {
long tid = Thread.currentThread().getId();
long e = this.map.computeIfAbsent(tid, i -> 0L);
int mod = (int) Math.floorMod(e >> 24L, (long) y);
this.map.put(tid, LinearCongruentialGenerator.next(e, this.magicrandom));
return mod;
}
@Override
public ImprovedNoise getBiomeNoise() {
return this.improvedNoise;
}
}
private static class FastGenLayer extends Layer {
private final FastAreaLazy fastAreaLazy;
public FastGenLayer(AreaFactory<FastAreaLazy> factory) {
super(() -> null);
this.fastAreaLazy = factory.make();
}
@Override
public Biome get(Registry<Biome> registry, int x, int z) {
ResourceKey<Biome> key = Biomes.byId(this.fastAreaLazy.get(x, z));
if (key == null) {
return registry.get(Biomes.byId(0));
}
Biome biome = registry.get(key);
if (biome == null) {
return registry.get(Biomes.byId(0));
}
return biome;
}
}
private record FastAreaLazy(ConcurrentHashMap<Long, Integer> sharedMap, PixelTransformer transformer) implements Area {
@Override
public int get(int x, int z) {
long zx = ChunkPos.asLong(x, z);
return this.sharedMap.computeIfAbsent(zx, i -> this.transformer.apply(x, z));
}
}
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
private RegenNoOpWorldLoadListener() {
}
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
// TODO Paper only(?) @Override
public void setChunkRadius(int radius) {
}
}
private class FastProtoChunk extends ProtoChunk {
// avoid warning on paper
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, ServerLevel serverLevel) {
super(pos, upgradeData, world, serverLevel);
}
// compatibility with spigot
public FastProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor) {
super(pos, upgradeData, levelHeightAccessor);
}
public boolean generateFlatBedrock() {
return generateFlatBedrock;
}
// no one will ever see the entities!
@Override
public List<CompoundTag> getEntities() {
return Collections.emptyList();
}
}
protected class ChunkStatusWrap extends ChunkStatusWrapper<ChunkAccess> {
private final ChunkStatus chunkStatus;
public ChunkStatusWrap(ChunkStatus chunkStatus) {
this.chunkStatus = chunkStatus;
}
@Override
public int requiredNeighborChunkRadius() {
return chunkStatus.getRange();
}
@Override
public String name() {
return chunkStatus.getName();
}
@Override
public CompletableFuture<?> processChunk(Long xz, List<ChunkAccess> accessibleChunks) {
return chunkStatus.generate(
Runnable::run, // TODO revisit, we might profit from this somehow?
freshWorld,
chunkGenerator,
structureManager,
threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks
);
}
}
}

Datei anzeigen

@ -0,0 +1,17 @@
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
plugins {
java
}
applyPaperweightAdapterConfiguration()
repositories {
gradlePluginPortal()
}
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.18.2-R0.1-20220920.010157-167")
compileOnly(libs.paperlib)
}

Datei anzeigen

@ -0,0 +1,103 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stat;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.OptionalInt;
import java.util.UUID;
class PaperweightFakePlayer extends ServerPlayer {
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
UUID.nameUUIDFromBytes("worldedit".getBytes()),
"[WorldEdit]"
);
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
PaperweightFakePlayer(ServerLevel world) {
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE);
}
@Override
public Vec3 position() {
return ORIGIN;
}
@Override
public void tick() {
}
@Override
public void die(DamageSource damagesource) {
}
@Override
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
return this;
}
@Override
public OptionalInt openMenu(MenuProvider factory) {
return OptionalInt.empty();
}
@Override
public void updateOptions(ServerboundClientInformationPacket packet) {
}
@Override
public void displayClientMessage(Component message, boolean actionBar) {
}
@Override
public void sendMessage(Component message, ChatType type, UUID sender) {
}
@Override
public void awardStat(Stat<?> stat, int amount) {
}
@Override
public void awardStat(Stat<?> stat) {
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return true;
}
@Override
public void openTextEdit(SignBlockEntity sign) {
}
}

Datei anzeigen

@ -0,0 +1,211 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import java.lang.ref.WeakReference;
import java.util.Objects;
import javax.annotation.Nullable;
public class PaperweightWorldNativeAccess implements
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private final PaperweightAdapter adapter;
private final WeakReference<ServerLevel> world;
private SideEffectSet sideEffectSet;
public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference<ServerLevel> world) {
this.adapter = adapter;
this.world = world;
}
private ServerLevel getWorld() {
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getWorld().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state);
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) {
return chunk.getBlockState(position);
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState state
) {
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState block,
BlockPos position
) {
return Block.updateFromNeighbourShapes(block, getWorld(), position);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos position) {
getWorld().getChunkSource().getLightEngine().checkBlock(position);
}
@Override
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
return false;
}
@Override
public void notifyBlockUpdate(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk chunk) {
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk chunk, BlockPos position) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().getChunkSource().blockChanged(position);
}
}
@Override
public void notifyNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
ServerLevel world = getWorld();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
world.updateNeighborsAt(pos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
Block block = oldState.getBlock();
fireNeighborChanged(pos, world, block, pos.west());
fireNeighborChanged(pos, world, block, pos.east());
fireNeighborChanged(pos, world, block, pos.below());
fireNeighborChanged(pos, world, block, pos.above());
fireNeighborChanged(pos, world, block, pos.north());
fireNeighborChanged(pos, world, block, pos.south());
}
if (newState.hasAnalogOutputSignal()) {
world.updateNeighbourForOutputSignal(pos, newState.getBlock());
}
}
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
}
@Override
public void updateNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
ServerLevel world = getWorld();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = world.getWorld();
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
CraftBlockData.fromData(newState)
);
world.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getWorld().onBlockStateChange(pos, oldState, newState);
}
//FAWE start
@Override
public void flush() {
}
//FAWE end
}

Datei anzeigen

@ -0,0 +1,189 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block;
private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial;
private final int opacity;
private final CompoundTag tile;
public PaperweightBlockMaterial(Block block) {
this(block, block.defaultBlockState());
}
public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block;
this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aO"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO,
blockState
);
tile = tileEntity == null
? null
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
}
public Block getBlock() {
return block;
}
public BlockState getState() {
return blockState;
}
public CraftBlockData getCraftBlockData() {
return craftBlockData;
}
public Material getMaterial() {
return material;
}
@Override
public boolean isAir() {
return blockState.isAir();
}
@Override
public boolean isFullCube() {
return craftMaterial.isOccluding();
}
@Override
public boolean isOpaque() {
return material.isSolidBlocking();
}
@Override
public boolean isPowerSource() {
return blockState.isSignalSource();
}
@Override
public boolean isLiquid() {
return material.isLiquid();
}
@Override
public boolean isSolid() {
return material.isSolid();
}
@Override
public float getHardness() {
return craftBlockData.getState().destroySpeed;
}
@Override
public float getResistance() {
return block.getExplosionResistance();
}
@Override
public float getSlipperiness() {
return block.getFriction();
}
@Override
public int getLightValue() {
return blockState.getLightEmission();
}
@Override
public int getLightOpacity() {
return opacity;
}
@Override
public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY;
}
@Override
public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK;
}
@Override
public boolean isTicksRandomly() {
return block.isRandomlyTicking(blockState);
}
@Override
public boolean isMovementBlocker() {
return material.isSolid();
}
@Override
public boolean isBurnable() {
return material.isFlammable();
}
@Override
public boolean isToolRequired() {
// Removed in 1.16.1, this is not present in higher versions
return false;
}
@Override
public boolean isReplacedDuringPlacement() {
return material.isReplaceable();
}
@Override
public boolean isTranslucent() {
return isTranslucent;
}
@Override
public boolean hasContainer() {
return block instanceof EntityBlock;
}
@Override
public boolean isTile() {
return block instanceof EntityBlock;
}
@Override
public CompoundTag getDefaultTile() {
return tile;
}
@Override
public int getMapColor() {
// rgb field
return material.getColor().col;
}
}

Datei anzeigen

@ -0,0 +1,700 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_18_R2.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen.PaperweightRegen;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import io.papermc.lib.PaperLib;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.WritableRegistry;
import net.minecraft.nbt.IntTag;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_18_R2.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final PaperweightAdapter parent;
// ------------------------------------------------------------------------
// Code that may break between versions of Minecraft
// ------------------------------------------------------------------------
private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil();
private char[] ibdToStateOrdinal = null;
private int[] ordinalToIbdID = null;
private boolean initialised = false;
private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter();
}
@Nullable
private static String getEntityId(Entity entity) {
ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType());
return resourceLocation == null ? null : resourceLocation.toString();
}
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent;
}
private synchronized boolean init() {
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false;
}
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState blockState = BlockTypesCache.states[i];
PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial();
int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState());
char ordinal = blockState.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
}
Map<String, List<Property<?>>> properties = new HashMap<>();
try {
for (Field field : BlockStateProperties.class.getDeclaredFields()) {
Object obj = field.get(null);
if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property<?> state)) {
continue;
}
Property<?> property;
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
property = new BooleanProperty(
state.getName(),
(List<Boolean>) ImmutableList.copyOf(state.getPossibleValues())
);
} else if (state instanceof DirectionProperty) {
property = new DirectionalProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase()))
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
property = new EnumProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> ((StringRepresentable) e).getSerializedName())
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
property = new IntegerProperty(
state.getName(),
(List<Integer>) ImmutableList.copyOf(state.getPossibleValues())
);
} else {
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state
.getClass()
.getSimpleName());
}
properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> {
if (v == null) {
v = new ArrayList<>(Collections.singletonList(property));
} else {
v.add(property);
}
return v;
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
allBlockProperties = ImmutableMap.copyOf(properties);
}
initialised = true;
return true;
}
@Override
public BlockMaterial getMaterial(BlockType blockType) {
Block block = getBlock(blockType);
return new PaperweightBlockMaterial(block);
}
@Override
public synchronized BlockMaterial getMaterial(BlockState state) {
net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
return new PaperweightBlockMaterial(blockState.getBlock(), blockState);
}
public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
}
@Deprecated
@Override
public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
if (state.getBlockType().getMaterial().hasContainer()) {
// Read the NBT data
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
}
}
return state.toBaseBlock();
}
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
}
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess(
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
}
@Override
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
Preconditions.checkNotNull(entity);
CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle();
String id = getEntityId(mcEntity);
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
tags.put("Id", StringBinaryTag.of(id));
return CompoundBinaryTag.from(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
return null;
}
}
@Override
public Component getRichBlockName(BlockType blockType) {
return parent.getRichBlockName(blockType);
}
@Override
public Component getRichItemName(ItemType itemType) {
return parent.getRichItemName(itemType);
}
@Override
public Component getRichItemName(BaseItemStack itemStack) {
return parent.getRichItemName(itemStack);
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState();
return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState));
}
@Override
public BlockState adapt(BlockData blockData) {
CraftBlockData cbd = ((CraftBlockData) blockData);
net.minecraft.world.level.block.state.BlockState ibd = cbd.getState();
return adapt(ibd);
}
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
return BlockTypesCache.states[adaptToChar(blockState)];
}
public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) {
int id = Block.BLOCK_STATE_REGISTRY.getId(blockState);
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
try {
init();
return ibdToStateOrdinal[id];
} catch (ArrayIndexOutOfBoundsException e1) {
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
);
return BlockTypesCache.ReservedIDs.AIR;
}
}
}
public char ibdIDToOrdinal(int id) {
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
init();
return ibdToStateOrdinal[id];
}
}
@Override
public char[] getIbdToStateOrdinal() {
if (initialised) {
return ibdToStateOrdinal;
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal;
}
init();
return ibdToStateOrdinal;
}
}
public int ordinalToIbdID(char ordinal) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
init();
return ordinalToIbdID[ordinal];
}
}
@Override
public int[] getOrdinalToIbdID() {
if (initialised) {
return ordinalToIbdID;
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID;
}
init();
return ordinalToIbdID;
}
}
@Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
return material.getCraftBlockData();
}
@Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle();
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && map.wasAccessibleSinceLastSave()) {
// PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
*/ Stream.empty();
ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle();
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
.forEach(entityPlayer -> {
synchronized (chunkPacket) {
ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
if (nmsPacket == null) {
nmsPacket = mapUtil.create(this, chunkPacket);
chunkPacket.setNativePacket(nmsPacket);
}
try {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
entityPlayer.connection.send(nmsPacket);
} finally {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
}
}
});
}
}
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
return getParent().getProperties(blockType);
}
@Override
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
);
}
@Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount()
);
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
return CraftItemStack.asCraftMirror(stack);
}
@Override
public boolean generateTree(
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
org.bukkit.World bukkitWorld
) {
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) {
blockVector3 = blockVector3.add(
0,
1,
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back
}
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle();
final BlockVector3 finalBlockVector = blockVector3;
// Sync to main thread to ensure no clashes occur
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> {
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true;
try {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
}
@Override
public List<org.bukkit.entity.Entity> getEntities(org.bukkit.World world) {
// Quickly add each entity to a list copy.
List<Entity> mcEntities = new ArrayList<>();
((CraftWorld) world).getHandle().entityManager.getEntityGetter().getAll().forEach(mcEntities::add);
List<org.bukkit.entity.Entity> list = new ArrayList<>();
mcEntities.forEach((mcEnt) -> {
org.bukkit.entity.Entity bukkitEntity = mcEnt.getBukkitEntity();
if (bukkitEntity.isValid()) {
list.add(bukkitEntity);
}
});
return list;
}
@Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack;
}
@Override
public Tag toNative(net.minecraft.nbt.Tag foreign) {
return parent.toNative(foreign);
}
@Override
public BinaryTag toNativeBinary(final net.minecraft.nbt.Tag foreign) {
return parent.toNativeBinary(foreign);
}
@Override
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
if (foreign instanceof PaperweightLazyCompoundTag) {
return ((PaperweightLazyCompoundTag) foreign).get();
}
return (net.minecraft.nbt.Tag) parent.fromNative(foreign);
}
@Override
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
}
@Override
public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) {
return new PaperweightGetBlocks(world, chunkX, chunkZ);
}
@Override
public int getInternalBiomeId(BiomeType biomeType) {
final Registry<Biome> registry = MinecraftServer
.getServer()
.registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
Biome biome = registry.get(resourceLocation);
return registry.getId(biome);
}
@Override
public Iterable<NamespacedKey> getRegisteredBiomes() {
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
.getServer()
.registryAccess()
.ownedRegistryOrThrow(
Registry.BIOME_REGISTRY);
List<ResourceLocation> keys = biomeRegistry.stream()
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
List<NamespacedKey> namespacedKeys = new ArrayList<>();
for (ResourceLocation key : keys) {
try {
namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key));
} catch (IllegalArgumentException e) {
LOGGER.error("Error converting biome key {}", key.toString(), e);
}
}
return namespacedKeys;
}
@Override
public RelighterFactory getRelighterFactory() {
if (PaperLib.isPaper()) {
return new PaperweightStarlightRelighterFactory();
} else {
return new NMSRelighterFactory();
}
}
@Override
public Map<String, List<Property<?>>> getAllProperties() {
if (initialised) {
return allBlockProperties;
}
synchronized (this) {
if (initialised) {
return allBlockProperties;
}
init();
return allBlockProperties;
}
}
@Override
public IBatchProcessor getTickingPostProcessor() {
return new PaperweightPostProcessor();
}
}

Datei anzeigen

@ -0,0 +1,286 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.task.RunnableVal;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private static final Direction[] NEIGHBOUR_ORDER = {
Direction.EAST,
Direction.WEST,
Direction.DOWN,
Direction.UP,
Direction.NORTH,
Direction.SOUTH
};
private final PaperweightFaweAdapter paperweightFaweAdapter;
private final WeakReference<Level> level;
private final AtomicInteger lastTick;
private final Set<CachedChange> cachedChanges = new HashSet<>();
private final Set<IntPair> cachedChunksToSend = new HashSet<>();
private SideEffectSet sideEffectSet;
public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference<Level> level) {
this.paperweightFaweAdapter = paperweightFaweAdapter;
this.level = level;
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
}
private Level getLevel() {
return Objects.requireNonNull(level.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getLevel().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) {
int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) {
return levelChunk.getBlockState(blockPos);
}
@Nullable
@Override
public synchronized net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
}
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) {
lastTick.set(currentTick);
}
flushAsync(nextTick);
}
return blockState;
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState blockState,
BlockPos blockPos
) {
return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos blockPos) {
getLevel().getChunkSource().getLightEngine().checkBlock(blockPos);
}
@Override
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
// We will assume that the tile entity was created for us,
// though we do not do this on the other versions
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
if (blockEntity == null) {
return false;
}
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
blockEntity.load((CompoundTag) nativeTag);
return true;
}
@Override
public void notifyBlockUpdate(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos);
}
}
@Override
public void notifyNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
Level level = getLevel();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
level.blockUpdated(blockPos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
// Un-nest neighbour updating
for (Direction direction : NEIGHBOUR_ORDER) {
BlockPos shifted = blockPos.relative(direction);
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
}
}
if (newState.hasAnalogOutputSignal()) {
level.updateNeighbourForOutputSignal(blockPos, newState.getBlock());
}
}
@Override
public void updateNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
Level level = getLevel();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = level.getWorld();
if (craftWorld != null) {
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
CraftBlockData.fromData(newState)
);
level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
}
newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getLevel().onBlockStateChange(blockPos, oldState, newState);
}
private synchronized void flushAsync(final boolean sendChunks) {
final Set<CachedChange> changes = Set.copyOf(cachedChanges);
cachedChanges.clear();
final Set<IntPair> toSend;
if (sendChunks) {
toSend = Set.copyOf(cachedChunksToSend);
cachedChunksToSend.clear();
} else {
toSend = Collections.emptySet();
}
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
if (!sendChunks) {
return;
}
for (IntPair chunk : toSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
}
@Override
public synchronized void flush() {
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
for (IntPair chunk : cachedChunksToSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
if (Fawe.isMainThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
}
cachedChanges.clear();
cachedChunksToSend.clear();
}
private record CachedChange(
LevelChunk levelChunk,
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
}
}

Datei anzeigen

@ -0,0 +1,236 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.PalettedContainer;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet {
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks;
private final int minHeight;
private final int maxHeight;
final ServerLevel serverLevel;
final LevelChunk levelChunk;
private PalettedContainer<Holder<Biome>>[] biomes = null;
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
this.levelChunk = levelChunk;
this.serverLevel = levelChunk.level;
this.minHeight = serverLevel.getMinBuildHeight();
this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive.
this.blocks = new char[getSectionCount()][];
}
protected void storeTile(BlockEntity blockEntity) {
tiles.put(
BlockVector3.at(
blockEntity.getBlockPos().getX(),
blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ()
),
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
);
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return tiles;
}
@Override
@Nullable
public CompoundTag getTile(int x, int y, int z) {
return tiles.get(BlockVector3.at(x, y, z));
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
entity.save(compoundTag);
entities.add((CompoundTag) adapter.toNative(compoundTag));
}
@Override
public Set<CompoundTag> getEntities() {
return this.entities;
}
@Override
public CompoundTag getEntity(UUID uuid) {
for (CompoundTag tag : entities) {
if (uuid.equals(tag.getUUID())) {
return tag;
}
}
return null;
}
@Override
public boolean isCreateCopy() {
return false;
}
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setHeightmapToGet(HeightMapType type, int[] data) {
}
@Override
public int getMaxY() {
return maxHeight;
}
@Override
public int getMinY() {
return minHeight;
}
@Override
public int getMaxSectionPosition() {
return maxHeight >> 4;
}
@Override
public int getMinSectionPosition() {
return minHeight >> 4;
}
@Override
public BiomeType getBiomeType(int x, int y, int z) {
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
}
@Override
public void removeSectionLighting(int layer, boolean sky) {
}
@Override
public boolean trim(boolean aggressive, int layer) {
return false;
}
@Override
public IBlocks reset() {
return null;
}
@Override
public int getSectionCount() {
return serverLevel.getSectionsCount();
}
protected void storeSection(int layer, char[] data) {
blocks[layer] = data;
}
protected void storeBiomes(int layer, PalettedContainer<Holder<Biome>> biomeData) {
if (biomes == null) {
biomes = new PalettedContainer[getSectionCount()];
}
biomes[layer] = biomeData;
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)];
return state.toBaseBlock(this, x, y, z);
}
@Override
public boolean hasSection(int layer) {
layer -= getMinSectionPosition();
return blocks[layer] != null;
}
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public char[] loadIfPresent(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)];
}
@Override
public int getSkyLight(int x, int y, int z) {
return 0;
}
@Override
public int getEmittedLight(int x, int y, int z) {
return 0;
}
@Override
public int[] getHeightMap(HeightMapType type) {
return new int[0];
}
@Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
return null;
}
public char get(int x, int y, int z) {
final int layer = (y >> 4) - getMinSectionPosition();
final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index];
}
@Override
public boolean trim(boolean aggressive) {
return false;
}
}

Datei anzeigen

@ -0,0 +1,34 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
//TODO un-very-break-this
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkWithLightPacket> {
public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a"));
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b"));
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c"));
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
fieldX.setAccessible(true);
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
}
@Override
public ClientboundLevelChunkWithLightPacket createPacket() {
// TODO ??? return new ClientboundLevelChunkPacket();
throw new UnsupportedOperationException();
}
}

Datei anzeigen

@ -0,0 +1,663 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.mojang.datafixers.util.Either;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.IdMap;
import net.minecraft.core.Registry;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.BitStorage;
import net.minecraft.util.SimpleBitStorage;
import net.minecraft.util.ThreadingDetector;
import net.minecraft.util.Unit;
import net.minecraft.util.ZeroBitStorage;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.GlobalPalette;
import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.SingleValuePalette;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftChunk;
import sun.misc.Unsafe;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
public final class PaperweightPlatformAdapter extends NMSAdapter {
public static final Field fieldData;
public static final Constructor<?> dataConstructor;
public static final Field fieldStorage;
public static final Field fieldPalette;
private static final Field fieldTickingFluidCount;
private static final Field fieldTickingBlockCount;
private static final Field fieldNonEmptyBlockCount;
private static final MethodHandle methodGetVisibleChunk;
private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;
private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;
private static final Field fieldLock;
private static final long fieldLockOffset;
private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity;
private static final Field fieldRemove;
private static final Logger LOGGER = LogManagerCompat.getLogger();
static {
try {
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
fieldData.setAccessible(true);
Class<?> dataClazz = fieldData.getType();
dataConstructor = dataClazz.getDeclaredConstructors()[0];
dataConstructor.setAccessible(true);
fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b"));
fieldStorage.setAccessible(true);
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
fieldPalette.setAccessible(true);
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
fieldTickingFluidCount.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
fieldNonEmptyBlockCount.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
"getVisibleChunkIfPresent",
"b"
), long.class);
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
} else {
// in paper, the used methods are synchronized properly
fieldThreadingDetector = null;
fieldThreadingDetectorOffset = -1;
fieldLock = null;
fieldLockOffset = -1;
}
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Refraction.pickName("removeGameEventListener", "d"),
BlockEntity.class
);
removeGameEventListener.setAccessible(true);
methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName(
"removeBlockEntityTicker",
"l"
), BlockPos.class
);
removeBlockEntityTicker.setAccessible(true);
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
rethrow.printStackTrace();
throw new RuntimeException(rethrow);
}
}
static boolean setSectionAtomic(
LevelChunkSection[] sections,
LevelChunkSection expected,
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
}
return false;
}
// There is no point in having a functional semaphore for paper servers.
private static final ThreadLocal<DelegateSemaphore> SEMAPHORE_THREAD_LOCAL =
ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null));
static DelegateSemaphore applyLock(LevelChunkSection section) {
if (PaperLib.isPaper()) {
return SEMAPHORE_THREAD_LOCAL.get();
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
blocks,
fieldThreadingDetectorOffset
);
synchronized (currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
return newLock;
}
}
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) {
if (!PaperLib.isPaper()) {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false);
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
try {
CraftChunk chunk;
try {
chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
String world = serverLevel.getWorld().getName();
// We've already taken 10 seconds we can afford to wait a little here.
boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null);
if (loaded) {
LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world);
// Retry chunk load
chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get();
} else {
throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!");
}
}
return chunk.getHandle();
} catch (Throwable e) {
e.printStackTrace();
}
}
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
}
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
// Ensure chunk is definitely loaded before applying a ticket
net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
.getChunkSource()
.addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
}
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap;
try {
return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ));
} catch (Throwable thr) {
throw new RuntimeException(thr);
}
}
@SuppressWarnings("deprecation")
public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) {
ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ);
if (chunkHolder == null) {
return;
}
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
// UNLOADED_CHUNK
Optional<LevelChunk> optional = ((Either) chunkHolder
.getTickingChunkFuture()
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only
optional = optional.or(() -> Optional.ofNullable(nmsWorld
.getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ)));
}
if (optional.isEmpty()) {
return;
}
LevelChunk levelChunk = optional.get();
TaskManager.taskManager().task(() -> {
ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) {
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true,
false // last false is to not bother with x-ray
);
} else {
// deprecated on paper - deprecation suppressed
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true
);
}
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
});
}
private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
}
/*
NMS conversion
*/
public static LevelChunkSection newChunkSection(
final int layer,
final char[] blocks,
CachedBukkitAdapter adapter,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
return newChunkSection(layer, null, blocks, adapter, biomeRegistry, biomes);
}
public static LevelChunkSection newChunkSection(
final int layer,
final Function<Integer, char[]> get,
char[] set,
CachedBukkitAdapter adapter,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
if (set == null) {
return newChunkSection(layer, biomeRegistry, biomes);
}
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get();
final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get();
try {
int num_palette;
if (get == null) {
num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, null);
} else {
num_palette = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, get, set, adapter, null);
}
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (bitsPerEntry > 0 && bitsPerEntry < 5) {
bitsPerEntry = 4;
} else if (bitsPerEntry > 8) {
bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1);
}
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong);
if (num_palette == 1) {
for (int i = 0; i < blockBitArrayEnd; i++) {
blockStates[i] = 0;
}
} else {
final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntryNonZero, 4096, blockStates);
bitArray.fromRaw(blocksCopy);
}
final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd);
final BitStorage nmsBits;
if (bitsPerEntry == 0) {
nmsBits = new ZeroBitStorage(4096);
} else {
nmsBits = new SimpleBitStorage(bitsPerEntry, 4096, bits);
}
List<net.minecraft.world.level.block.state.BlockState> palette;
if (bitsPerEntry < 9) {
palette = new ArrayList<>();
for (int i = 0; i < num_palette; i++) {
int ordinal = paletteToBlock[i];
blockToPalette[ordinal] = Integer.MAX_VALUE;
final BlockState state = BlockTypesCache.states[ordinal];
palette.add(((PaperweightBlockMaterial) state.getMaterial()).getState());
}
} else {
palette = List.of();
}
// Create palette with data
@SuppressWarnings("deprecation") // constructor is deprecated on paper, but needed to keep compatibility with spigot
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blockStatePalettedContainer =
new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
PalettedContainer.Strategy.SECTION_STATES,
PalettedContainer.Strategy.SECTION_STATES.getConfiguration(Block.BLOCK_STATE_REGISTRY, bitsPerEntry),
nmsBits,
palette
);
if (biomes == null) {
IdMap<Holder<Biome>> biomeHolderIdMap = biomeRegistry.asHolderIdMap();
biomes = new PalettedContainer<>(
biomeHolderIdMap,
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(
BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
}
return new LevelChunkSection(layer, blockStatePalettedContainer, biomes);
} catch (final Throwable e) {
throw e;
} finally {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
Arrays.fill(paletteToBlock, Integer.MAX_VALUE);
Arrays.fill(blockStates, 0);
Arrays.fill(blocksCopy, 0);
}
}
@SuppressWarnings("deprecation") // Only deprecated in paper
private static LevelChunkSection newChunkSection(
int layer,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
if (biomes == null) {
return new LevelChunkSection(layer, biomeRegistry);
}
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
Blocks.AIR.defaultBlockState(),
PalettedContainer.Strategy.SECTION_STATES,
null
);
return new LevelChunkSection(layer, dataPaletteBlocks, biomes);
}
/**
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
*/
public static PalettedContainer<Holder<Biome>> getBiomePalettedContainer(
BiomeType[] biomes,
IdMap<Holder<Biome>> biomeRegistry
) {
if (biomes == null) {
return null;
}
BukkitImplAdapter<?> adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
// Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length
Map<BiomeType, Holder<Biome>> palette = new HashMap<>();
for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) {
Holder<Biome> biome;
if (biomeType == null) {
biome = biomeRegistry.byId(adapter.getInternalBiomeId(BiomeTypes.PLAINS));
} else {
biome = biomeRegistry.byId(adapter.getInternalBiomeId(biomeType));
}
palette.put(biomeType, biome);
}
int biomeCount = palette.size();
int bitsPerEntry = MathMan.log2nlz(biomeCount - 1);
Object configuration = PalettedContainer.Strategy.SECTION_STATES.getConfiguration(
new FakeIdMapBiome(biomeCount),
bitsPerEntry
);
if (bitsPerEntry > 3) {
bitsPerEntry = MathMan.log2nlz(biomeRegistry.size() - 1);
}
PalettedContainer<Holder<Biome>> biomePalettedContainer = new PalettedContainer<>(
biomeRegistry,
biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
final Palette<Holder<Biome>> biomePalette;
if (bitsPerEntry == 0) {
biomePalette = new SingleValuePalette<>(
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else if (bitsPerEntry == 4) {
biomePalette = LinearPalette.create(
4,
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else if (bitsPerEntry < 9) {
biomePalette = HashMapPalette.create(
bitsPerEntry,
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else {
biomePalette = GlobalPalette.create(
bitsPerEntry,
biomePalettedContainer.registry,
biomePalettedContainer,
null // unused
);
}
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
final int arrayLength = MathMan.ceilZero(64f / blocksPerLong);
BitStorage bitStorage = bitsPerEntry == 0 ? new ZeroBitStorage(64) : new SimpleBitStorage(
bitsPerEntry,
64,
new long[arrayLength]
);
try {
Object data = dataConstructor.newInstance(configuration, bitStorage, biomePalette);
fieldData.set(biomePalettedContainer, data);
int index = 0;
for (int y = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, index++) {
BiomeType biomeType = biomes[index];
if (biomeType == null) {
continue;
}
Holder<Biome> biome = biomeRegistry.byId(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(biomeType));
if (biome == null) {
continue;
}
biomePalettedContainer.set(x, y, z, biome);
}
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return biomePalettedContainer;
}
public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException {
fieldTickingFluidCount.setShort(section, (short) 0);
fieldTickingBlockCount.setShort(section, (short) 0);
}
public static BiomeType adapt(Holder<Biome> biome, LevelAccessor levelAccessor) {
final Registry<Biome> biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
if (biomeRegistry.getKey(biome.value()) == null) {
return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN
: null;
}
return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString());
}
@SuppressWarnings("unchecked")
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try {
// Do the method ourselves to avoid trying to reflect generic method parameters
// similar to removeGameEventListener
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) {
if (!levelChunk.level.isClientSide) {
methodRemoveGameEventListener.invoke(levelChunk, beacon);
}
fieldRemove.set(beacon, true);
}
}
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
static List<Entity> getEntities(LevelChunk chunk) {
return chunk.level.entityManager.getEntities(chunk.getPos());
}
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
@Override
public int getId(final net.minecraft.world.level.block.state.BlockState entry) {
return 0;
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState byId(final int index) {
return null;
}
@Nonnull
@Override
public Iterator<net.minecraft.world.level.block.state.BlockState> iterator() {
return Collections.emptyIterator();
}
}
record FakeIdMapBiome(int size) implements IdMap<Biome> {
@Override
public int getId(final Biome entry) {
return 0;
}
@Nullable
@Override
public Biome byId(final int index) {
return null;
}
@Nonnull
@Override
public Iterator<Biome> iterator() {
return Collections.emptyIterator();
}
}
}

Datei anzeigen

@ -0,0 +1,175 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.registry.state.PropertyKey;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import javax.annotation.Nullable;
public class PaperweightPostProcessor implements IBatchProcessor {
@Override
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
return set;
}
@SuppressWarnings("deprecation")
@Override
public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) {
boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS;
// The PostProcessor shouldn't be added, but just in case
if (!tickFluid) {
return;
}
PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet;
layer:
for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) {
char[] set = iChunkSet.loadIfPresent(layer);
if (set == null) {
// No edit means no need to process
continue;
}
char[] get = null;
for (int i = 0; i < 4096; i++) {
char ordinal = set[i];
char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
boolean fromGet = false; // Used for liquids
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
if (get == null) {
get = getBlocks.load(layer);
}
// If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't
// actually being set
if (get == null) {
continue layer;
}
fromGet = true;
ordinal = replacedOrdinal = get[i];
}
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
continue;
} else if (!fromGet) { // if fromGet, don't do the same again
if (get == null) {
get = getBlocks.load(layer);
}
replacedOrdinal = get[i];
}
boolean ticking = BlockTypesCache.ticking[ordinal];
boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal];
boolean replacedWasLiquid = false;
BlockState replacedState = null;
if (!ticking) {
// If the block being replaced was not ticking, it cannot be a liquid
if (!replacedWasTicking) {
continue;
}
// If the block being replaced is not fluid, we do not need to worry
if (!(replacedWasLiquid =
(replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) {
continue;
}
}
BlockState state = BlockState.getFromOrdinal(ordinal);
boolean liquid = state.getMaterial().isLiquid();
int x = i & 15;
int y = (i >> 8) & 15;
int z = (i >> 4) & 15;
BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z);
if (liquid || replacedWasLiquid) {
if (liquid) {
addFluid(getBlocks.serverLevel, state, position);
continue;
}
// If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this
// may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up
// being ticked anyway. We only need it to be "hit" once.
if (!wasAdjacentToWater(get, set, i, x, y, z)) {
continue;
}
addFluid(getBlocks.serverLevel, replacedState, position);
}
}
}
}
@Nullable
@Override
public Extent construct(final Extent child) {
throw new UnsupportedOperationException("Processing only");
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.READING_SET_BLOCKS;
}
private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) {
if (set == null || get == null) {
return false;
}
char ordinal;
char reserved = BlockTypesCache.ReservedIDs.__RESERVED__;
if (x > 0 && set[i - 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) {
return true;
}
}
if (x < 15 && set[i + 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) {
return true;
}
}
if (z > 0 && set[i - 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) {
return true;
}
}
if (z < 15 && set[i + 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) {
return true;
}
}
if (y > 0 && set[i - 256] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) {
return true;
}
}
if (y < 15 && set[i + 256] != reserved) {
return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal);
}
return false;
}
@SuppressWarnings("deprecation")
private boolean isFluid(char ordinal) {
return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid();
}
@SuppressWarnings("deprecation")
private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) {
Fluid type;
if (replacedState.getBlockType() == BlockTypes.LAVA) {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA;
} else {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
}
serverLevel.scheduleTick(
position,
type,
type.getTickDelay(serverLevel)
);
}
}

Datei anzeigen

@ -0,0 +1,205 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.MCUtil;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
public class PaperweightStarlightRelighter implements Relighter {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32
private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
private static final int LIGHT_LEVEL = MCUtil.getTicketLevelFor(ChunkStatus.LIGHT);
private final ServerLevel serverLevel;
private final ReentrantLock lock = new ReentrantLock();
private final Long2ObjectLinkedOpenHashMap<LongSet> regions = new Long2ObjectLinkedOpenHashMap<>();
private final ReentrantLock areaLock = new ReentrantLock();
private final NMSRelighter delegate;
@SuppressWarnings("rawtypes")
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<IQueueChunk> queue) {
this.serverLevel = serverLevel;
this.delegate = new NMSRelighter(queue);
}
@Override
public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) {
areaLock.lock();
try {
long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2);
// TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH?
LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2));
chunks.add(ChunkPos.asLong(cx, cz));
} finally {
areaLock.unlock();
}
return true;
}
@Override
public void addLightUpdate(int x, int y, int z) {
delegate.addLightUpdate(x, y, z);
}
/*
* This method is called "recursively", iterating and removing elements
* from the regions linked map. This way, chunks are loaded in batches to avoid
* OOMEs.
*/
@Override
public void fixLightingSafe(boolean sky) {
this.areaLock.lock();
try {
if (regions.isEmpty()) {
return;
}
LongSet first = regions.removeFirst();
fixLighting(first, () -> fixLightingSafe(true));
} finally {
this.areaLock.unlock();
}
}
/*
* Processes a set of chunks and runs an action afterwards.
* The action is run async, the chunks are partly processed on the main thread
* (as required by the server).
*/
private void fixLighting(LongSet chunks, Runnable andThen) {
// convert from long keys to ChunkPos
Set<ChunkPos> coords = new HashSet<>();
LongIterator iterator = chunks.iterator();
while (iterator.hasNext()) {
coords.add(new ChunkPos(iterator.nextLong()));
}
TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE
))
);
}
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v ->
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads
TaskManager.taskManager().async(andThen);
}
)
);
});
}
private void invokeRelight(
Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback,
IntConsumer processCallback
) {
try {
serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
} catch (Exception e) {
LOGGER.error("Error occurred on relighting", e);
}
}
/*
* Allow the server to unload the chunks again.
* Also, if chunk packets are sent delayed, we need to do that here
*/
private void postProcessChunks(Set<ChunkPos> coords) {
boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
for (ChunkPos pos : coords) {
int x = pos.x;
int z = pos.z;
if (delay) { // we still need to send the block changes of that chunk
PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false);
}
serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
}
}
@Override
public void clear() {
}
@Override
public void removeLighting() {
this.delegate.removeLighting();
}
@Override
public void fixBlockLighting() {
fixLightingSafe(true);
}
@Override
public void fixSkyLighting() {
fixLightingSafe(true);
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ReentrantLock getLock() {
return this.lock;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public void close() throws Exception {
fixLightingSafe(true);
}
}

Datei anzeigen

@ -0,0 +1,28 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import javax.annotation.Nonnull;
public class PaperweightStarlightRelighterFactory implements RelighterFactory {
@Override
public @Nonnull
@SuppressWarnings("rawtypes")
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
org.bukkit.World w = Bukkit.getWorld(world.getName());
if (w == null) {
return NullRelighter.INSTANCE;
}
return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue);
}
}

Datei anzeigen

@ -0,0 +1,161 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.LazyCompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import net.minecraft.nbt.NumericTag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class PaperweightLazyCompoundTag extends LazyCompoundTag {
private final Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier;
private CompoundTag compoundTag;
public PaperweightLazyCompoundTag(Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier) {
super(new HashMap<>());
this.compoundTagSupplier = compoundTagSupplier;
}
public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) {
this(() -> compoundTag);
}
public net.minecraft.nbt.CompoundTag get() {
return compoundTagSupplier.get();
}
@Override
@SuppressWarnings("unchecked")
public Map<String, Tag> getValue() {
if (compoundTag == null) {
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
}
return compoundTag.getValue();
}
@Override
public CompoundBinaryTag asBinaryTag() {
getValue();
return compoundTag.asBinaryTag();
}
public boolean containsKey(String key) {
return compoundTagSupplier.get().contains(key);
}
public byte[] getByteArray(String key) {
return compoundTagSupplier.get().getByteArray(key);
}
public byte getByte(String key) {
return compoundTagSupplier.get().getByte(key);
}
public double getDouble(String key) {
return compoundTagSupplier.get().getDouble(key);
}
public double asDouble(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsDouble();
}
return 0;
}
public float getFloat(String key) {
return compoundTagSupplier.get().getFloat(key);
}
public int[] getIntArray(String key) {
return compoundTagSupplier.get().getIntArray(key);
}
public int getInt(String key) {
return compoundTagSupplier.get().getInt(key);
}
public int asInt(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsInt();
}
return 0;
}
@SuppressWarnings("unchecked")
public List<Tag> getList(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
ArrayList<Tag> list = new ArrayList<>();
for (net.minecraft.nbt.Tag elem : nbtList) {
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
list.add(new PaperweightLazyCompoundTag(compoundTag));
} else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
}
}
return list;
}
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
public ListTag getListTag(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag) {
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
}
return new ListTag(StringTag.class, Collections.emptyList());
}
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
ListTag listTag = getListTag(key);
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
}
public long[] getLongArray(String key) {
return compoundTagSupplier.get().getLongArray(key);
}
public long getLong(String key) {
return compoundTagSupplier.get().getLong(key);
}
public long asLong(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsLong();
}
return 0;
}
public short getShort(String key) {
return compoundTagSupplier.get().getShort(key);
}
public String getString(String key) {
return compoundTagSupplier.get().getString(key);
}
@Override
public String toString() {
return compoundTagSupplier.get().toString();
}
}

Datei anzeigen

@ -0,0 +1,541 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Lifecycle;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightGetBlocks;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.io.file.SafeFiles;
import com.sk89q.worldedit.world.RegenOptions;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.CraftServer;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.generator.CustomChunkGenerator;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalLong;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field serverWorldsField;
private static final Field paperConfigField;
private static final Field flatBedrockField;
private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField;
private static final Field chunkSourceField;
private static final Field ringPositionsField;
private static final Field hasGeneratedPositionsField;
//list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
static {
chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
chunkStati.put(
ChunkStatus.STRUCTURE_REFERENCES,
Concurrency.FULL
); // structure refs: radius 8, but only writes to current chunk
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(
ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
chunkStati.put(
ChunkStatus.LIGHT,
Concurrency.FULL
); // light: radius 1, but no writes to other chunks, only current chunk
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try {
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true);
Field tmpPaperConfigField;
Field tmpFlatBedrockField;
try { //only present on paper
tmpPaperConfigField = Level.class.getDeclaredField("paperConfig");
tmpPaperConfigField.setAccessible(true);
tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock");
tmpFlatBedrockField.setAccessible(true);
} catch (Exception e) {
tmpPaperConfigField = null;
tmpFlatBedrockField = null;
}
paperConfigField = tmpPaperConfigField;
flatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "h"));
generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "g"));
generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "K"));
chunkSourceField.setAccessible(true);
ringPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("ringPositions", "h"));
ringPositionsField.setAccessible(true);
hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "i"));
hasGeneratedPositionsField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//runtime
private ServerLevel originalServerWorld;
private ServerChunkCache originalChunkProvider;
private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session;
private StructureManager structureManager;
private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator;
private Path tempDir;
private boolean generateFlatBedrock = false;
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
super(originalBukkitWorld, region, target, options);
}
@Override
protected boolean prepare() {
this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle();
originalChunkProvider = originalServerWorld.getChunkSource();
if (!(originalChunkProvider instanceof ServerChunkCache)) {
return false;
}
//flat bedrock? (only on paper)
if (paperConfigField != null) {
try {
generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) {
}
}
seed = options.getSeed().orElse(originalServerWorld.getSeed());
chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c));
return true;
}
@Override
@SuppressWarnings("unchecked")
protected boolean initNewWorld() throws Exception {
//world folder
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
//prepare for world init (see upstream implementation for reference)
org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment();
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
BiomeProvider biomeProvider = getBiomeProvider();
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
: originalOpts;
LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld",
originalWorldData.settings.gameType(),
originalWorldData.settings.hardcore(),
originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig()
);
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
//init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
server,
server.executor,
session,
newWorldData,
originalServerWorld.dimension(),
originalServerWorld.dimensionTypeRegistration(),
new RegenNoOpWorldLoadListener(),
// placeholder. Required for new ChunkProviderServer, but we create and then set it later
newOpts.dimensions().getOrThrow(levelStemResourceKey).generator(),
originalServerWorld.isDebug(),
seed,
ImmutableList.of(),
false,
environment,
generator,
biomeProvider
) {
private final Holder<Biome> singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
) : null;
@Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
}
@Override
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) {
return singleBiome;
}
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ,
PaperweightRegen.this.chunkGenerator.climateSampler()
);
}
}).get();
freshWorld.noSave = true;
removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig);
}
//generator
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat);
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier =
(Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField
.get(originalGenerator);
BiomeSource biomeSource;
if (options.hasBiomeType()) {
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME
.asHolderIdMap()
.byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())));
} else {
biomeSource = originalGenerator.getBiomeSource();
}
chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets, noiseBasedChunkGenerator.noises,
biomeSource, seed,
generatorSettingBaseSupplier
);
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
chunkGenerator = customChunkGenerator.delegate;
} else {
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
return false;
}
if (generator != null) {
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable();
}
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
// Optimisation for needless ring position calculation when the seed and biome is the same.
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator);
if (hasGeneratedPositions) {
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> ringPositions =
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(
originalGenerator);
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(ringPositions);
ringPositionsField.set(chunkGenerator, copy);
hasGeneratedPositionsField.setBoolean(chunkGenerator, true);
}
}
chunkGenerator.conf = originalServerWorld.spigotConfig;
freshChunkProvider = new ServerChunkCache(
freshWorld,
session,
server.getFixerUpper(),
server.getStructureManager(),
server.executor,
chunkGenerator,
freshWorld.spigotConfig.viewDistance,
freshWorld.spigotConfig.simulationDistance,
server.forceSynchronousWrites(),
new RegenNoOpWorldLoadListener(),
(chunkCoordIntPair, state) -> {
},
() -> server.overworld().getDataStorage()
) {
// redirect to LevelChunks created in #createChunks
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) {
ChunkAccess chunkAccess = getChunkAt(x, z);
if (chunkAccess == null && create) {
chunkAccess = createChunk(getProtoChunkAt(x, z));
}
return chunkAccess;
}
};
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
//let's start then
structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
return true;
}
@Override
protected void cleanup() {
try {
session.close();
} catch (Exception ignored) {
}
//shutdown chunk provider
try {
Fawe.instance().getQueueHandler().sync(() -> {
try {
freshChunkProvider.close(false);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
} catch (Exception ignored) {
}
//remove world from server
try {
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
} catch (Exception ignored) {
}
//delete directory
try {
SafeFiles.tryHardToDeleteDir(tempDir);
} catch (Exception ignored) {
}
}
@Override
protected ProtoChunk createProtoChunk(int x, int z) {
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null
);
}
@Override
protected LevelChunk createChunk(ProtoChunk protoChunk) {
return new LevelChunk(
freshWorld,
protoChunk,
null // we don't want to add entities
);
}
@Override
protected ChunkStatusWrap getFullChunkStatus() {
return new ChunkStatusWrap(ChunkStatus.FULL);
}
@Override
protected List<BlockPopulator> getBlockPopulators() {
return originalServerWorld.getWorld().getPopulators();
}
@Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
}
@Override
protected IChunkCache<IChunkGet> initSourceQueueCache() {
return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) {
@Override
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) {
return getChunkAt(x, z);
}
};
}
//util
@SuppressWarnings("unchecked")
private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> {
try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
map.remove("faweregentempworld");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
return switch (env) {
case NETHER -> LevelStem.NETHER;
case THE_END -> LevelStem.END;
default -> LevelStem.OVERWORLD;
};
}
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
private RegenNoOpWorldLoadListener() {
}
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
// TODO Paper only(?) @Override
public void setChunkRadius(int radius) {
}
}
private class FastProtoChunk extends ProtoChunk {
public FastProtoChunk(
final ChunkPos pos,
final UpgradeData upgradeData,
final LevelHeightAccessor world,
final Registry<Biome> biomeRegistry,
@Nullable final BlendingData blendingData
) {
super(pos, upgradeData, world, biomeRegistry, blendingData);
}
// avoid warning on paper
// compatibility with spigot
public boolean generateFlatBedrock() {
return generateFlatBedrock;
}
// no one will ever see the entities!
@Override
public List<CompoundTag> getEntities() {
return Collections.emptyList();
}
}
protected class ChunkStatusWrap extends ChunkStatusWrapper<ChunkAccess> {
private final ChunkStatus chunkStatus;
public ChunkStatusWrap(ChunkStatus chunkStatus) {
this.chunkStatus = chunkStatus;
}
@Override
public int requiredNeighborChunkRadius() {
return chunkStatus.getRange();
}
@Override
public String name() {
return chunkStatus.getName();
}
@Override
public CompletableFuture<?> processChunk(Long xz, List<ChunkAccess> accessibleChunks) {
return chunkStatus.generate(
Runnable::run, // TODO revisit, we might profit from this somehow?
freshWorld,
chunkGenerator,
structureManager,
threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks,
true
);
}
}
}

Datei anzeigen

@ -0,0 +1,16 @@
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
plugins {
java
}
applyPaperweightAdapterConfiguration()
repositories {
gradlePluginPortal()
}
dependencies {
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.19.2-R0.1-20221206.184705-189")
compileOnly(libs.paperlib)
}

Datei anzeigen

@ -0,0 +1,99 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.chat.ChatType;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stat;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.OptionalInt;
import java.util.UUID;
class PaperweightFakePlayer extends ServerPlayer {
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(
UUID.nameUUIDFromBytes("worldedit".getBytes()),
"[WorldEdit]"
);
private static final Vec3 ORIGIN = new Vec3(0.0D, 0.0D, 0.0D);
PaperweightFakePlayer(ServerLevel world) {
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, null);
}
@Override
public Vec3 position() {
return ORIGIN;
}
@Override
public void tick() {
}
@Override
public void die(DamageSource damagesource) {
}
@Override
public Entity changeDimension(ServerLevel worldserver, TeleportCause cause) {
return this;
}
@Override
public OptionalInt openMenu(MenuProvider factory) {
return OptionalInt.empty();
}
@Override
public void updateOptions(ServerboundClientInformationPacket packet) {
}
@Override
public void displayClientMessage(Component message, boolean actionBar) {
}
@Override
public void awardStat(Stat<?> stat, int amount) {
}
@Override
public void awardStat(Stat<?> stat) {
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return true;
}
@Override
public void openTextEdit(SignBlockEntity sign) {
}
}

Datei anzeigen

@ -0,0 +1,210 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Objects;
public class PaperweightWorldNativeAccess implements
WorldNativeAccess<LevelChunk, net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private final PaperweightAdapter adapter;
private final WeakReference<ServerLevel> world;
private SideEffectSet sideEffectSet;
public PaperweightWorldNativeAccess(PaperweightAdapter adapter, WeakReference<ServerLevel> world) {
this.adapter = adapter;
this.world = world;
}
private ServerLevel getWorld() {
return Objects.requireNonNull(world.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getWorld().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state);
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk chunk, BlockPos position) {
return chunk.getBlockState(position);
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState state
) {
return chunk.setBlockState(position, state, false, this.sideEffectSet.shouldApply(SideEffect.UPDATE));
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState block,
BlockPos position
) {
return Block.updateFromNeighbourShapes(block, getWorld(), position);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos position) {
getWorld().getChunkSource().getLightEngine().checkBlock(position);
}
@Override
public boolean updateTileEntity(final BlockPos position, final CompoundBinaryTag tag) {
return false;
}
@Override
public void notifyBlockUpdate(
LevelChunk chunk,
BlockPos position,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk chunk) {
return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk chunk, BlockPos position) {
if (chunk.getSections()[getWorld().getSectionIndex(position.getY())] != null) {
getWorld().getChunkSource().blockChanged(position);
}
}
@Override
public void notifyNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
ServerLevel world = getWorld();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
world.updateNeighborsAt(pos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
Block block = oldState.getBlock();
fireNeighborChanged(pos, world, block, pos.west());
fireNeighborChanged(pos, world, block, pos.east());
fireNeighborChanged(pos, world, block, pos.below());
fireNeighborChanged(pos, world, block, pos.above());
fireNeighborChanged(pos, world, block, pos.north());
fireNeighborChanged(pos, world, block, pos.south());
}
if (newState.hasAnalogOutputSignal()) {
world.updateNeighbourForOutputSignal(pos, newState.getBlock());
}
}
@SuppressWarnings("deprecation")
private void fireNeighborChanged(BlockPos pos, ServerLevel world, Block block, BlockPos neighborPos) {
world.getBlockState(neighborPos).neighborChanged(world, neighborPos, block, pos, false);
}
@Override
public void updateNeighbors(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
ServerLevel world = getWorld();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = world.getWorld();
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()),
CraftBlockData.fromData(newState)
);
world.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos pos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getWorld().onBlockStateChange(pos, oldState, newState);
}
@Override
public void flush() {
}
}

Datei anzeigen

@ -0,0 +1,189 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.util.ReflectionUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
public class PaperweightBlockMaterial implements BlockMaterial {
private final Block block;
private final BlockState blockState;
private final Material material;
private final boolean isTranslucent;
private final CraftBlockData craftBlockData;
private final org.bukkit.Material craftMaterial;
private final int opacity;
private final CompoundTag tile;
public PaperweightBlockMaterial(Block block) {
this(block, block.defaultBlockState());
}
public PaperweightBlockMaterial(Block block, BlockState blockState) {
this.block = block;
this.blockState = blockState;
this.material = blockState.getMaterial();
this.craftBlockData = CraftBlockData.fromData(blockState);
this.craftMaterial = craftBlockData.getMaterial();
BlockBehaviour.Properties blockInfo = ReflectionUtil.getField(BlockBehaviour.class, block, Refraction.pickName(
"properties", "aO"));
this.isTranslucent = !(boolean) ReflectionUtil.getField(BlockBehaviour.Properties.class, blockInfo,
Refraction.pickName("canOcclude", "n")
);
opacity = blockState.getLightBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
BlockEntity tileEntity = !(block instanceof EntityBlock) ? null : ((EntityBlock) block).newBlockEntity(
BlockPos.ZERO,
blockState
);
tile = tileEntity == null
? null
: new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId));
}
public Block getBlock() {
return block;
}
public BlockState getState() {
return blockState;
}
public CraftBlockData getCraftBlockData() {
return craftBlockData;
}
public Material getMaterial() {
return material;
}
@Override
public boolean isAir() {
return blockState.isAir();
}
@Override
public boolean isFullCube() {
return craftMaterial.isOccluding();
}
@Override
public boolean isOpaque() {
return material.isSolidBlocking();
}
@Override
public boolean isPowerSource() {
return blockState.isSignalSource();
}
@Override
public boolean isLiquid() {
return material.isLiquid();
}
@Override
public boolean isSolid() {
return material.isSolid();
}
@Override
public float getHardness() {
return craftBlockData.getState().destroySpeed;
}
@Override
public float getResistance() {
return block.getExplosionResistance();
}
@Override
public float getSlipperiness() {
return block.getFriction();
}
@Override
public int getLightValue() {
return blockState.getLightEmission();
}
@Override
public int getLightOpacity() {
return opacity;
}
@Override
public boolean isFragileWhenPushed() {
return material.getPushReaction() == PushReaction.DESTROY;
}
@Override
public boolean isUnpushable() {
return material.getPushReaction() == PushReaction.BLOCK;
}
@Override
public boolean isTicksRandomly() {
return block.isRandomlyTicking(blockState);
}
@Override
public boolean isMovementBlocker() {
return material.isSolid();
}
@Override
public boolean isBurnable() {
return material.isFlammable();
}
@Override
public boolean isToolRequired() {
// Removed in 1.16.1, this is not present in higher versions
return false;
}
@Override
public boolean isReplacedDuringPlacement() {
return material.isReplaceable();
}
@Override
public boolean isTranslucent() {
return isTranslucent;
}
@Override
public boolean hasContainer() {
return block instanceof EntityBlock;
}
@Override
public boolean isTile() {
return block instanceof EntityBlock;
}
@Override
public CompoundTag getDefaultTile() {
return tile;
}
@Override
public int getMapColor() {
// rgb field
return material.getColor().col;
}
}

Datei anzeigen

@ -0,0 +1,701 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_19_R1.PaperweightAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.regen.PaperweightRegen;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.nbt.BinaryTag;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.util.nbt.StringBinaryTag;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import io.papermc.lib.PaperLib;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.WritableRegistry;
import net.minecraft.nbt.IntTag;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockState;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_19_R1.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class PaperweightFaweAdapter extends CachedBukkitAdapter implements
IDelegateBukkitImplAdapter<net.minecraft.nbt.Tag> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static Method CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE;
static {
try {
CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE = ChunkHolder.class.getDeclaredMethod("wasAccessibleSinceLastSave");
} catch (NoSuchMethodException ignored) { // may not be present in newer paper versions
}
}
private final PaperweightAdapter parent;
// ------------------------------------------------------------------------
// Code that may break between versions of Minecraft
// ------------------------------------------------------------------------
private final PaperweightMapChunkUtil mapUtil = new PaperweightMapChunkUtil();
private char[] ibdToStateOrdinal = null;
private int[] ordinalToIbdID = null;
private boolean initialised = false;
private Map<String, List<Property<?>>> allBlockProperties = null;
public PaperweightFaweAdapter() throws NoSuchFieldException, NoSuchMethodException {
this.parent = new PaperweightAdapter();
}
@Nullable
private static String getEntityId(Entity entity) {
ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType());
return resourceLocation == null ? null : resourceLocation.toString();
}
private static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTag compoundTag) {
entity.save(compoundTag);
}
@Override
public BukkitImplAdapter<net.minecraft.nbt.Tag> getParent() {
return parent;
}
private synchronized boolean init() {
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false;
}
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState blockState = BlockTypesCache.states[i];
PaperweightBlockMaterial material = (PaperweightBlockMaterial) blockState.getMaterial();
int id = Block.BLOCK_STATE_REGISTRY.getId(material.getState());
char ordinal = blockState.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
}
Map<String, List<Property<?>>> properties = new HashMap<>();
try {
for (Field field : BlockStateProperties.class.getDeclaredFields()) {
Object obj = field.get(null);
if (!(obj instanceof net.minecraft.world.level.block.state.properties.Property<?> state)) {
continue;
}
Property<?> property;
if (state instanceof net.minecraft.world.level.block.state.properties.BooleanProperty) {
property = new BooleanProperty(
state.getName(),
(List<Boolean>) ImmutableList.copyOf(state.getPossibleValues())
);
} else if (state instanceof DirectionProperty) {
property = new DirectionalProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> Direction.valueOf(((StringRepresentable) e).getSerializedName().toUpperCase()))
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.EnumProperty) {
property = new EnumProperty(
state.getName(),
state
.getPossibleValues()
.stream()
.map(e -> ((StringRepresentable) e).getSerializedName())
.collect(Collectors.toList())
);
} else if (state instanceof net.minecraft.world.level.block.state.properties.IntegerProperty) {
property = new IntegerProperty(
state.getName(),
(List<Integer>) ImmutableList.copyOf(state.getPossibleValues())
);
} else {
throw new IllegalArgumentException("FastAsyncWorldEdit needs an update to support " + state
.getClass()
.getSimpleName());
}
properties.compute(property.getName().toLowerCase(Locale.ROOT), (k, v) -> {
if (v == null) {
v = new ArrayList<>(Collections.singletonList(property));
} else {
v.add(property);
}
return v;
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
allBlockProperties = ImmutableMap.copyOf(properties);
}
initialised = true;
return true;
}
@Override
public BlockMaterial getMaterial(BlockType blockType) {
Block block = getBlock(blockType);
return new PaperweightBlockMaterial(block);
}
@Override
public synchronized BlockMaterial getMaterial(BlockState state) {
net.minecraft.world.level.block.state.BlockState blockState = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
return new PaperweightBlockMaterial(blockState.getBlock(), blockState);
}
public Block getBlock(BlockType blockType) {
return Registry.BLOCK.get(new ResourceLocation(blockType.getNamespace(), blockType.getResource()));
}
@Deprecated
@Override
public BlockState getBlock(Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
return state;
}
@Override
public BaseBlock getFullBlock(final Location location) {
Preconditions.checkNotNull(location);
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
final ServerLevel handle = craftWorld.getHandle();
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
final BlockPos blockPos = new BlockPos(x, y, z);
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
BlockState state = adapt(blockData);
if (state == null) {
org.bukkit.block.Block bukkitBlock = location.getBlock();
state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
}
if (state.getBlockType().getMaterial().hasContainer()) {
// Read the NBT data
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = blockEntity.saveWithId();
return state.toBaseBlock((CompoundBinaryTag) toNativeBinary(tag));
}
}
return state.toBaseBlock();
}
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
}
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
CraftChunk craftChunk = (CraftChunk) chunk;
LevelChunk levelChunk = craftChunk.getHandle();
Level level = levelChunk.getLevel();
BlockPos blockPos = new BlockPos(x, y, z);
net.minecraft.world.level.block.state.BlockState blockState = ((PaperweightBlockMaterial) state.getMaterial()).getState();
LevelChunkSection[] levelChunkSections = levelChunk.getSections();
int y4 = y >> 4;
LevelChunkSection section = levelChunkSections[y4];
net.minecraft.world.level.block.state.BlockState existing;
if (section == null) {
existing = ((PaperweightBlockMaterial) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
} else {
existing = section.getBlockState(x & 15, y & 15, z & 15);
}
levelChunk.removeBlockEntity(blockPos); // Force delete the old tile entity
CompoundBinaryTag compoundTag = state instanceof BaseBlock ? state.getNbt() : null;
if (compoundTag != null || existing instanceof TileEntityBlock) {
level.setBlock(blockPos, blockState, 0);
// remove tile
if (compoundTag != null) {
// We will assume that the tile entity was created for us,
// though we do not do this on the Forge version
BlockEntity blockEntity = level.getBlockEntity(blockPos);
if (blockEntity != null) {
net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) fromNativeBinary(compoundTag);
tag.put("x", IntTag.valueOf(x));
tag.put("y", IntTag.valueOf(y));
tag.put("z", IntTag.valueOf(z));
blockEntity.load(tag); // readTagIntoTileEntity - load data
}
}
} else {
if (existing == blockState) {
return true;
}
levelChunk.setBlockState(blockPos, blockState, false);
}
if (update) {
level.getMinecraftWorld().sendBlockUpdated(blockPos, existing, blockState, 0);
}
return true;
}
@Override
public WorldNativeAccess<?, ?, ?> createWorldNativeAccess(org.bukkit.World world) {
return new PaperweightFaweWorldNativeAccess(
this,
new WeakReference<>(((CraftWorld) world).getHandle())
);
}
@Override
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
Preconditions.checkNotNull(entity);
CraftEntity craftEntity = ((CraftEntity) entity);
Entity mcEntity = craftEntity.getHandle();
String id = getEntityId(mcEntity);
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundBinaryTag> saveTag = () -> {
final net.minecraft.nbt.CompoundTag minecraftTag = new net.minecraft.nbt.CompoundTag();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
final CompoundBinaryTag tag = (CompoundBinaryTag) toNativeBinary(minecraftTag);
final Map<String, BinaryTag> tags = NbtUtils.getCompoundBinaryTagValues(tag);
tags.put("Id", StringBinaryTag.of(id));
return CompoundBinaryTag.from(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
return null;
}
}
@Override
public Component getRichBlockName(BlockType blockType) {
return parent.getRichBlockName(blockType);
}
@Override
public Component getRichItemName(ItemType itemType) {
return parent.getRichItemName(itemType);
}
@Override
public Component getRichItemName(BaseItemStack itemStack) {
return parent.getRichItemName(itemStack);
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
net.minecraft.world.level.block.state.BlockState mcState = material.getCraftBlockData().getState();
return OptionalInt.of(Block.BLOCK_STATE_REGISTRY.getId(mcState));
}
@Override
public BlockState adapt(BlockData blockData) {
CraftBlockData cbd = ((CraftBlockData) blockData);
net.minecraft.world.level.block.state.BlockState ibd = cbd.getState();
return adapt(ibd);
}
public BlockState adapt(net.minecraft.world.level.block.state.BlockState blockState) {
return BlockTypesCache.states[adaptToChar(blockState)];
}
public char adaptToChar(net.minecraft.world.level.block.state.BlockState blockState) {
int id = Block.BLOCK_STATE_REGISTRY.getId(blockState);
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
try {
init();
return ibdToStateOrdinal[id];
} catch (ArrayIndexOutOfBoundsException e1) {
LOGGER.error("Attempted to convert {} with ID {} to char. ibdToStateOrdinal length: {}. Defaulting to air!",
blockState.getBlock(), Block.BLOCK_STATE_REGISTRY.getId(blockState), ibdToStateOrdinal.length, e1
);
return BlockTypesCache.ReservedIDs.AIR;
}
}
}
public char ibdIDToOrdinal(int id) {
if (initialised) {
return ibdToStateOrdinal[id];
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal[id];
}
init();
return ibdToStateOrdinal[id];
}
}
@Override
public char[] getIbdToStateOrdinal() {
if (initialised) {
return ibdToStateOrdinal;
}
synchronized (this) {
if (initialised) {
return ibdToStateOrdinal;
}
init();
return ibdToStateOrdinal;
}
}
public int ordinalToIbdID(char ordinal) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID[ordinal];
}
init();
return ordinalToIbdID[ordinal];
}
}
@Override
public int[] getOrdinalToIbdID() {
if (initialised) {
return ordinalToIbdID;
}
synchronized (this) {
if (initialised) {
return ordinalToIbdID;
}
init();
return ordinalToIbdID;
}
}
@Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
PaperweightBlockMaterial material = (PaperweightBlockMaterial) state.getMaterial();
return material.getCraftBlockData();
}
@Override
public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket chunkPacket) {
ServerLevel nmsWorld = ((CraftWorld) world).getHandle();
ChunkHolder map = PaperweightPlatformAdapter.getPlayerChunk(nmsWorld, chunkPacket.getChunkX(), chunkPacket.getChunkZ());
if (map != null && wasAccessibleSinceLastSave(map)) {
boolean flag = false;
// PlayerChunk.d players = map.players;
Stream<ServerPlayer> stream = /*players.a(new ChunkCoordIntPair(packet.getChunkX(), packet.getChunkZ()), flag)
*/ Stream.empty();
ServerPlayer checkPlayer = player == null ? null : ((CraftPlayer) player).getHandle();
stream.filter(entityPlayer -> checkPlayer == null || entityPlayer == checkPlayer)
.forEach(entityPlayer -> {
synchronized (chunkPacket) {
ClientboundLevelChunkWithLightPacket nmsPacket = (ClientboundLevelChunkWithLightPacket) chunkPacket.getNativePacket();
if (nmsPacket == null) {
nmsPacket = mapUtil.create(this, chunkPacket);
chunkPacket.setNativePacket(nmsPacket);
}
try {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(true);
entityPlayer.connection.send(nmsPacket);
} finally {
FaweCache.INSTANCE.CHUNK_FLAG.get().set(false);
}
}
});
}
}
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
return getParent().getProperties(blockType);
}
@Override
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
int internalId = BlockStateIdAccess.getBlockStateId(blockState);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(internalId);
return blockState1.hasPostProcess(
((CraftWorld) world).getHandle(),
new BlockPos(blockVector3.getX(), blockVector3.getY(), blockVector3.getZ())
);
}
@Override
public org.bukkit.inventory.ItemStack adapt(BaseItemStack baseItemStack) {
ItemStack stack = new ItemStack(
Registry.ITEM.get(ResourceLocation.tryParse(baseItemStack.getType().getId())),
baseItemStack.getAmount()
);
stack.setTag(((net.minecraft.nbt.CompoundTag) fromNative(baseItemStack.getNbtData())));
return CraftItemStack.asCraftMirror(stack);
}
@Override
public boolean generateTree(
TreeGenerator.TreeType treeType, EditSession editSession, BlockVector3 blockVector3,
org.bukkit.World bukkitWorld
) {
TreeType bukkitType = BukkitWorld.toBukkitTreeType(treeType);
if (bukkitType == TreeType.CHORUS_PLANT) {
blockVector3 = blockVector3.add(
0,
1,
0
); // bukkit skips the feature gen which does this offset normally, so we have to add it back
}
ServerLevel serverLevel = ((CraftWorld) bukkitWorld).getHandle();
final BlockVector3 finalBlockVector = blockVector3;
// Sync to main thread to ensure no clashes occur
Map<BlockPos, CraftBlockState> placed = TaskManager.taskManager().sync(() -> {
serverLevel.captureTreeGeneration = true;
serverLevel.captureBlockStates = true;
try {
if (!bukkitWorld.generateTree(BukkitAdapter.adapt(bukkitWorld, finalBlockVector), bukkitType)) {
return null;
}
return ImmutableMap.copyOf(serverLevel.capturedBlockStates);
} finally {
serverLevel.captureBlockStates = false;
serverLevel.captureTreeGeneration = false;
serverLevel.capturedBlockStates.clear();
}
});
if (placed == null || placed.isEmpty()) {
return false;
}
for (CraftBlockState craftBlockState : placed.values()) {
if (craftBlockState == null || craftBlockState.getType() == Material.AIR) {
continue;
}
editSession.setBlock(craftBlockState.getX(), craftBlockState.getY(), craftBlockState.getZ(),
BukkitAdapter.adapt(((org.bukkit.block.BlockState) craftBlockState).getBlockData())
);
}
return true;
}
@Override
public BaseItemStack adapt(org.bukkit.inventory.ItemStack itemStack) {
final ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
final BaseItemStack weStack = new BaseItemStack(BukkitAdapter.asItemType(itemStack.getType()), itemStack.getAmount());
weStack.setNbt(((CompoundBinaryTag) toNativeBinary(nmsStack.getTag())));
return weStack;
}
@Override
public Tag toNative(net.minecraft.nbt.Tag foreign) {
return parent.toNative(foreign);
}
@Override
public net.minecraft.nbt.Tag fromNative(Tag foreign) {
if (foreign instanceof PaperweightLazyCompoundTag) {
return ((PaperweightLazyCompoundTag) foreign).get();
}
return parent.fromNative(foreign);
}
@Override
public boolean regenerate(org.bukkit.World bukkitWorld, Region region, Extent target, RegenOptions options) throws Exception {
return new PaperweightRegen(bukkitWorld, region, target, options).regenerate();
}
@Override
public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) {
return new PaperweightGetBlocks(world, chunkX, chunkZ);
}
@Override
public int getInternalBiomeId(BiomeType biomeType) {
final Registry<Biome> registry = MinecraftServer
.getServer()
.registryAccess()
.ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
ResourceLocation resourceLocation = ResourceLocation.tryParse(biomeType.getId());
Biome biome = registry.get(resourceLocation);
return registry.getId(biome);
}
@Override
public Iterable<NamespacedKey> getRegisteredBiomes() {
WritableRegistry<Biome> biomeRegistry = (WritableRegistry<Biome>) ((CraftServer) Bukkit.getServer())
.getServer()
.registryAccess()
.ownedRegistryOrThrow(
Registry.BIOME_REGISTRY);
List<ResourceLocation> keys = biomeRegistry.stream()
.map(biomeRegistry::getKey).filter(Objects::nonNull).toList();
List<NamespacedKey> namespacedKeys = new ArrayList<>();
for (ResourceLocation key : keys) {
try {
namespacedKeys.add(CraftNamespacedKey.fromMinecraft(key));
} catch (IllegalArgumentException e) {
LOGGER.error("Error converting biome key {}", key.toString(), e);
}
}
return namespacedKeys;
}
@Override
public RelighterFactory getRelighterFactory() {
if (PaperLib.isPaper()) {
return new PaperweightStarlightRelighterFactory();
} else {
return new NMSRelighterFactory();
}
}
@Override
public Map<String, List<Property<?>>> getAllProperties() {
if (initialised) {
return allBlockProperties;
}
synchronized (this) {
if (initialised) {
return allBlockProperties;
}
init();
return allBlockProperties;
}
}
@Override
public IBatchProcessor getTickingPostProcessor() {
return new PaperweightPostProcessor();
}
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {
if (!PaperLib.isPaper() || !PaperweightPlatformAdapter.POST_CHUNK_REWRITE) {
try {
return (boolean) CHUNK_HOLDER_WAS_ACCESSIBLE_SINCE_LAST_SAVE.invoke(holder);
} catch (IllegalAccessException | InvocationTargetException ignored) {
// fall-through
}
}
// Papers new chunk system has no related replacement - therefor we assume true.
return true;
}
}

Datei anzeigen

@ -0,0 +1,286 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.math.IntPair;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.task.RunnableVal;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.internal.wna.WorldNativeAccess;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.event.block.BlockPhysicsEvent;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<LevelChunk,
net.minecraft.world.level.block.state.BlockState, BlockPos> {
private static final int UPDATE = 1;
private static final int NOTIFY = 2;
private static final Direction[] NEIGHBOUR_ORDER = {
Direction.EAST,
Direction.WEST,
Direction.DOWN,
Direction.UP,
Direction.NORTH,
Direction.SOUTH
};
private final PaperweightFaweAdapter paperweightFaweAdapter;
private final WeakReference<Level> level;
private final AtomicInteger lastTick;
private final Set<CachedChange> cachedChanges = new HashSet<>();
private final Set<IntPair> cachedChunksToSend = new HashSet<>();
private SideEffectSet sideEffectSet;
public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference<Level> level) {
this.paperweightFaweAdapter = paperweightFaweAdapter;
this.level = level;
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
}
private Level getLevel() {
return Objects.requireNonNull(level.get(), "The reference to the world was lost");
}
@Override
public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public LevelChunk getChunk(int x, int z) {
return getLevel().getChunk(x, z);
}
@Override
public net.minecraft.world.level.block.state.BlockState toNative(BlockState blockState) {
int stateId = paperweightFaweAdapter.ordinalToIbdID(blockState.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId)
? Block.stateById(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(blockState)).getState();
}
@Override
public net.minecraft.world.level.block.state.BlockState getBlockState(LevelChunk levelChunk, BlockPos blockPos) {
return levelChunk.getBlockState(blockPos);
}
@Nullable
@Override
public synchronized net.minecraft.world.level.block.state.BlockState setBlockState(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
int currentTick = MinecraftServer.currentTick;
if (Fawe.isMainThread()) {
return levelChunk.setBlockState(blockPos, blockState,
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE)
);
}
// Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( )
cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState));
cachedChunksToSend.add(new IntPair(levelChunk.bukkitChunk.getX(), levelChunk.bukkitChunk.getZ()));
boolean nextTick = lastTick.get() > currentTick;
if (nextTick || cachedChanges.size() >= 1024) {
if (nextTick) {
lastTick.set(currentTick);
}
flushAsync(nextTick);
}
return blockState;
}
@Override
public net.minecraft.world.level.block.state.BlockState getValidBlockForPosition(
net.minecraft.world.level.block.state.BlockState blockState,
BlockPos blockPos
) {
return Block.updateFromNeighbourShapes(blockState, getLevel(), blockPos);
}
@Override
public BlockPos getPosition(int x, int y, int z) {
return new BlockPos(x, y, z);
}
@Override
public void updateLightingForBlock(BlockPos blockPos) {
getLevel().getChunkSource().getLightEngine().checkBlock(blockPos);
}
@Override
public boolean updateTileEntity(BlockPos blockPos, CompoundBinaryTag tag) {
// We will assume that the tile entity was created for us,
// though we do not do this on the other versions
BlockEntity blockEntity = getLevel().getBlockEntity(blockPos);
if (blockEntity == null) {
return false;
}
net.minecraft.nbt.Tag nativeTag = paperweightFaweAdapter.fromNativeBinary(tag);
blockEntity.load((CompoundTag) nativeTag);
return true;
}
@Override
public void notifyBlockUpdate(
LevelChunk levelChunk, BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
getLevel().sendBlockUpdated(blockPos, oldState, newState, UPDATE | NOTIFY);
}
}
@Override
public boolean isChunkTicking(LevelChunk levelChunk) {
return levelChunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING);
}
@Override
public void markBlockChanged(LevelChunk levelChunk, BlockPos blockPos) {
if (levelChunk.getSections()[level.get().getSectionIndex(blockPos.getY())] != null) {
((ServerChunkCache) getLevel().getChunkSource()).blockChanged(blockPos);
}
}
@Override
public void notifyNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
Level level = getLevel();
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
level.blockUpdated(blockPos, oldState.getBlock());
} else {
// When we don't want events, manually run the physics without them.
// Un-nest neighbour updating
for (Direction direction : NEIGHBOUR_ORDER) {
BlockPos shifted = blockPos.relative(direction);
level.getBlockState(shifted).neighborChanged(level, shifted, oldState.getBlock(), blockPos, false);
}
}
if (newState.hasAnalogOutputSignal()) {
level.updateNeighbourForOutputSignal(blockPos, newState.getBlock());
}
}
@Override
public void updateNeighbors(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState,
int recursionLimit
) {
Level level = getLevel();
// a == updateNeighbors
// b == updateDiagonalNeighbors
oldState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
if (sideEffectSet.shouldApply(SideEffect.EVENTS)) {
CraftWorld craftWorld = level.getWorld();
if (craftWorld != null) {
BlockPhysicsEvent event = new BlockPhysicsEvent(
craftWorld.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()),
CraftBlockData.fromData(newState)
);
level.getCraftServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
}
newState.triggerEvent(level, blockPos, NOTIFY, recursionLimit);
newState.updateIndirectNeighbourShapes(level, blockPos, NOTIFY, recursionLimit);
}
@Override
public void onBlockStateChange(
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState oldState,
net.minecraft.world.level.block.state.BlockState newState
) {
getLevel().onBlockStateChange(blockPos, oldState, newState);
}
private synchronized void flushAsync(final boolean sendChunks) {
final Set<CachedChange> changes = Set.copyOf(cachedChanges);
cachedChanges.clear();
final Set<IntPair> toSend;
if (sendChunks) {
toSend = Set.copyOf(cachedChunksToSend);
cachedChunksToSend.clear();
} else {
toSend = Collections.emptySet();
}
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
changes.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
if (!sendChunks) {
return;
}
for (IntPair chunk : toSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal));
}
@Override
public synchronized void flush() {
RunnableVal<Object> runnableVal = new RunnableVal<>() {
@Override
public void run(Object value) {
cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState,
sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE)
));
for (IntPair chunk : cachedChunksToSend) {
PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false);
}
}
};
if (Fawe.isMainThread()) {
runnableVal.run();
} else {
TaskManager.taskManager().sync(runnableVal);
}
cachedChanges.clear();
cachedChunksToSend.clear();
}
private record CachedChange(
LevelChunk levelChunk,
BlockPos blockPos,
net.minecraft.world.level.block.state.BlockState blockState
) {
}
}

Datei anzeigen

@ -0,0 +1,248 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt.PaperweightLazyCompoundTag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.PalettedContainerRO;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
public class PaperweightGetBlocks_Copy implements IChunkGet {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>();
private final char[][] blocks;
private final int minHeight;
private final int maxHeight;
final ServerLevel serverLevel;
final LevelChunk levelChunk;
private PalettedContainer<Holder<Biome>>[] biomes = null;
protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) {
this.levelChunk = levelChunk;
this.serverLevel = levelChunk.level;
this.minHeight = serverLevel.getMinBuildHeight();
this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive.
this.blocks = new char[getSectionCount()][];
}
protected void storeTile(BlockEntity blockEntity) {
tiles.put(
BlockVector3.at(
blockEntity.getBlockPos().getX(),
blockEntity.getBlockPos().getY(),
blockEntity.getBlockPos().getZ()
),
new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId))
);
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return tiles;
}
@Override
@Nullable
public CompoundTag getTile(int x, int y, int z) {
return tiles.get(BlockVector3.at(x, y, z));
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
entity.save(compoundTag);
entities.add((CompoundTag) adapter.toNative(compoundTag));
}
@Override
public Set<CompoundTag> getEntities() {
return this.entities;
}
@Override
public CompoundTag getEntity(UUID uuid) {
for (CompoundTag tag : entities) {
if (uuid.equals(tag.getUUID())) {
return tag;
}
}
return null;
}
@Override
public boolean isCreateCopy() {
return false;
}
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) {
}
@Override
public void setHeightmapToGet(HeightMapType type, int[] data) {
}
@Override
public int getMaxY() {
return maxHeight;
}
@Override
public int getMinY() {
return minHeight;
}
@Override
public int getMaxSectionPosition() {
return maxHeight >> 4;
}
@Override
public int getMinSectionPosition() {
return minHeight >> 4;
}
@Override
public BiomeType getBiomeType(int x, int y, int z) {
Holder<Biome> biome = biomes[(y >> 4) - getMinSectionPosition()].get(x >> 2, (y & 15) >> 2, z >> 2);
return PaperweightPlatformAdapter.adapt(biome, serverLevel);
}
@Override
public void removeSectionLighting(int layer, boolean sky) {
}
@Override
public boolean trim(boolean aggressive, int layer) {
return false;
}
@Override
public IBlocks reset() {
return null;
}
@Override
public int getSectionCount() {
return serverLevel.getSectionsCount();
}
protected void storeSection(int layer, char[] data) {
blocks[layer] = data;
}
protected void storeBiomes(int layer, PalettedContainerRO<Holder<Biome>> biomeData) {
if (biomes == null) {
biomes = new PalettedContainer[getSectionCount()];
}
if (biomeData instanceof PalettedContainer<Holder<Biome>> palettedContainer) {
biomes[layer] = palettedContainer.copy();
} else {
LOGGER.error(
"Cannot correctly save biomes to history. Expected class type {} but got {}",
PalettedContainer.class.getSimpleName(),
biomeData.getClass().getSimpleName()
);
}
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)];
return state.toBaseBlock(this, x, y, z);
}
@Override
public boolean hasSection(int layer) {
layer -= getMinSectionPosition();
return blocks[layer] != null;
}
@Override
public char[] load(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public char[] loadIfPresent(int layer) {
layer -= getMinSectionPosition();
return blocks[layer];
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)];
}
@Override
public int getSkyLight(int x, int y, int z) {
return 0;
}
@Override
public int getEmittedLight(int x, int y, int z) {
return 0;
}
@Override
public int[] getHeightMap(HeightMapType type) {
return new int[0];
}
@Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
return null;
}
public char get(int x, int y, int z) {
final int layer = (y >> 4) - getMinSectionPosition();
final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index];
}
@Override
public boolean trim(boolean aggressive) {
return false;
}
}

Datei anzeigen

@ -0,0 +1,35 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.bukkit.adapter.MapChunkUtil;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
//TODO un-very-break-this
public class PaperweightMapChunkUtil extends MapChunkUtil<ClientboundLevelChunkWithLightPacket> {
public PaperweightMapChunkUtil() throws NoSuchFieldException {
fieldX = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("TWO_MEGABYTES", "a"));
fieldZ = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("x", "a"));
fieldBitMask = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("z", "b"));
fieldHeightMap = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("heightmaps", "b"));
fieldChunkData = ClientboundLevelChunkWithLightPacket.class.getDeclaredField(Refraction.pickName("chunkData", "c"));
fieldBlockEntities = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("buffer", "c"));
fieldFull = ClientboundLevelChunkPacketData.class.getDeclaredField(Refraction.pickName("blockEntitiesData", "d"));
fieldX.setAccessible(true);
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
}
@Override
public ClientboundLevelChunkWithLightPacket createPacket() {
// TODO ??? return new ClientboundLevelChunkPacket();
throw new UnsupportedOperationException();
}
}

Datei anzeigen

@ -0,0 +1,703 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.destroystokyo.paper.util.maplist.EntityList;
import com.fastasyncworldedit.bukkit.adapter.CachedBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.DelegateSemaphore;
import com.fastasyncworldedit.bukkit.adapter.NMSAdapter;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.math.BitArrayUnstretched;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.mojang.datafixers.util.Either;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import io.papermc.lib.PaperLib;
import io.papermc.paper.world.ChunkEntitySlices;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.IdMap;
import net.minecraft.core.Registry;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.BitStorage;
import net.minecraft.util.ExceptionCollector;
import net.minecraft.util.SimpleBitStorage;
import net.minecraft.util.ThreadingDetector;
import net.minecraft.util.Unit;
import net.minecraft.util.ZeroBitStorage;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.GlobalPalette;
import net.minecraft.world.level.chunk.HashMapPalette;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LinearPalette;
import net.minecraft.world.level.chunk.Palette;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.SingleValuePalette;
import net.minecraft.world.level.entity.PersistentEntitySectionManager;
import net.minecraft.world.level.gameevent.GameEventDispatcher;
import net.minecraft.world.level.gameevent.GameEventListener;
import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
import sun.misc.Unsafe;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.function.Function;
public final class PaperweightPlatformAdapter extends NMSAdapter {
public static final Field fieldData;
public static final Constructor<?> dataConstructor;
public static final Field fieldStorage;
public static final Field fieldPalette;
private static final Field fieldTickingFluidCount;
private static final Field fieldTickingBlockCount;
private static final Field fieldNonEmptyBlockCount;
private static final MethodHandle methodGetVisibleChunk;
private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;
private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;
private static final Field fieldLock;
private static final long fieldLockOffset;
private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity;
private static final Field fieldRemove;
static final boolean POST_CHUNK_REWRITE;
private static Method PAPER_CHUNK_GEN_ALL_ENTITIES;
private static Field LEVEL_CHUNK_ENTITIES;
private static Field SERVER_LEVEL_ENTITY_MANAGER;
static {
try {
fieldData = PalettedContainer.class.getDeclaredField(Refraction.pickName("data", "d"));
fieldData.setAccessible(true);
Class<?> dataClazz = fieldData.getType();
dataConstructor = dataClazz.getDeclaredConstructors()[0];
dataConstructor.setAccessible(true);
fieldStorage = dataClazz.getDeclaredField(Refraction.pickName("storage", "b"));
fieldStorage.setAccessible(true);
fieldPalette = dataClazz.getDeclaredField(Refraction.pickName("palette", "c"));
fieldPalette.setAccessible(true);
fieldTickingFluidCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingFluidCount", "h"));
fieldTickingFluidCount.setAccessible(true);
fieldTickingBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("tickingBlockCount", "g"));
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount = LevelChunkSection.class.getDeclaredField(Refraction.pickName("nonEmptyBlockCount", "f"));
fieldNonEmptyBlockCount.setAccessible(true);
Method getVisibleChunkIfPresent = ChunkMap.class.getDeclaredMethod(Refraction.pickName(
"getVisibleChunkIfPresent",
"b"
), long.class);
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);
Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
} else {
// in paper, the used methods are synchronized properly
fieldThreadingDetector = null;
fieldThreadingDetectorOffset = -1;
fieldLock = null;
fieldLockOffset = -1;
}
Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Refraction.pickName("removeGameEventListener", "a"),
BlockEntity.class,
ServerLevel.class
);
removeGameEventListener.setAccessible(true);
methodRemoveGameEventListener = MethodHandles.lookup().unreflect(removeGameEventListener);
Method removeBlockEntityTicker = LevelChunk.class.getDeclaredMethod(
Refraction.pickName(
"removeBlockEntityTicker",
"l"
), BlockPos.class
);
removeBlockEntityTicker.setAccessible(true);
methodremoveTickingBlockEntity = MethodHandles.lookup().unreflect(removeBlockEntityTicker);
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);
CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
boolean chunkRewrite;
try {
ServerLevel.class.getDeclaredMethod("getEntityLookup");
chunkRewrite = true;
PAPER_CHUNK_GEN_ALL_ENTITIES = ChunkEntitySlices.class.getDeclaredMethod("getAllEntities");
PAPER_CHUNK_GEN_ALL_ENTITIES.setAccessible(true);
} catch (NoSuchMethodException ignored) {
chunkRewrite = false;
}
try {
// Paper - Pre-Chunk-Update
LEVEL_CHUNK_ENTITIES = LevelChunk.class.getDeclaredField("entities");
LEVEL_CHUNK_ENTITIES.setAccessible(true);
} catch (NoSuchFieldException ignored) {
}
try {
// Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "P"));
SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) {
}
POST_CHUNK_REWRITE = chunkRewrite;
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
rethrow.printStackTrace();
throw new RuntimeException(rethrow);
}
}
static boolean setSectionAtomic(
LevelChunkSection[] sections,
LevelChunkSection expected,
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
}
return false;
}
// There is no point in having a functional semaphore for paper servers.
private static final ThreadLocal<DelegateSemaphore> SEMAPHORE_THREAD_LOCAL =
ThreadLocal.withInitial(() -> new DelegateSemaphore(1, null));
static DelegateSemaphore applyLock(LevelChunkSection section) {
if (PaperLib.isPaper()) {
return SEMAPHORE_THREAD_LOCAL.get();
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
blocks,
fieldThreadingDetectorOffset
);
synchronized (currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
return newLock;
}
}
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int chunkZ) {
if (!PaperLib.isPaper()) {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunk(chunkX, chunkZ, false);
if (nmsChunk != null) {
return nmsChunk;
}
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
} else {
LevelChunk nmsChunk = serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
nmsChunk = serverLevel.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (nmsChunk != null) {
addTicket(serverLevel, chunkX, chunkZ);
return nmsChunk;
}
// Avoid "async" methods from the main thread.
if (Fawe.isMainThread()) {
return serverLevel.getChunk(chunkX, chunkZ);
}
CompletableFuture<org.bukkit.Chunk> future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true);
try {
CraftChunk chunk = (CraftChunk) future.get();
return chunk.getHandle();
} catch (Throwable e) {
e.printStackTrace();
}
}
return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ));
}
private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) {
// Ensure chunk is definitely loaded before applying a ticket
io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel
.getChunkSource()
.addRegionTicket(TicketType.PLUGIN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE));
}
public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) {
ChunkMap chunkMap = nmsWorld.getChunkSource().chunkMap;
try {
return (ChunkHolder) methodGetVisibleChunk.invoke(chunkMap, ChunkPos.asLong(chunkX, chunkZ));
} catch (Throwable thr) {
throw new RuntimeException(thr);
}
}
@SuppressWarnings("deprecation")
public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boolean lighting) {
ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ);
if (chunkHolder == null) {
return;
}
ChunkPos coordIntPair = new ChunkPos(chunkX, chunkZ);
LevelChunk levelChunk;
if (PaperLib.isPaper()) {
// getChunkAtIfLoadedImmediately is paper only
levelChunk = nmsWorld
.getChunkSource()
.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
} else {
levelChunk = ((Optional<LevelChunk>) ((Either) chunkHolder
.getTickingChunkFuture() // method is not present with new paper chunk system
.getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left())
.orElse(null);
}
if (levelChunk == null) {
return;
}
TaskManager.taskManager().task(() -> {
ClientboundLevelChunkWithLightPacket packet;
if (PaperLib.isPaper()) {
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true,
false // last false is to not bother with x-ray
);
} else {
// deprecated on paper - deprecation suppressed
packet = new ClientboundLevelChunkWithLightPacket(
levelChunk,
nmsWorld.getChunkSource().getLightEngine(),
null,
null,
true
);
}
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
});
}
private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
}
/*
NMS conversion
*/
public static LevelChunkSection newChunkSection(
final int layer,
final char[] blocks,
CachedBukkitAdapter adapter,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
return newChunkSection(layer, null, blocks, adapter, biomeRegistry, biomes);
}
public static LevelChunkSection newChunkSection(
final int layer,
final Function<Integer, char[]> get,
char[] set,
CachedBukkitAdapter adapter,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
if (set == null) {
return newChunkSection(layer, biomeRegistry, biomes);
}
final int[] blockToPalette = FaweCache.INSTANCE.BLOCK_TO_PALETTE.get();
final int[] paletteToBlock = FaweCache.INSTANCE.PALETTE_TO_BLOCK.get();
final long[] blockStates = FaweCache.INSTANCE.BLOCK_STATES.get();
final int[] blocksCopy = FaweCache.INSTANCE.SECTION_BLOCKS.get();
try {
int num_palette;
if (get == null) {
num_palette = createPalette(blockToPalette, paletteToBlock, blocksCopy, set, adapter, null);
} else {
num_palette = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, get, set, adapter, null);
}
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (bitsPerEntry > 0 && bitsPerEntry < 5) {
bitsPerEntry = 4;
} else if (bitsPerEntry > 8) {
bitsPerEntry = MathMan.log2nlz(Block.BLOCK_STATE_REGISTRY.size() - 1);
}
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
final int blockBitArrayEnd = MathMan.ceilZero((float) 4096 / blocksPerLong);
if (num_palette == 1) {
for (int i = 0; i < blockBitArrayEnd; i++) {
blockStates[i] = 0;
}
} else {
final BitArrayUnstretched bitArray = new BitArrayUnstretched(bitsPerEntryNonZero, 4096, blockStates);
bitArray.fromRaw(blocksCopy);
}
final long[] bits = Arrays.copyOfRange(blockStates, 0, blockBitArrayEnd);
final BitStorage nmsBits;
if (bitsPerEntry == 0) {
nmsBits = new ZeroBitStorage(4096);
} else {
nmsBits = new SimpleBitStorage(bitsPerEntry, 4096, bits);
}
List<net.minecraft.world.level.block.state.BlockState> palette;
if (bitsPerEntry < 9) {
palette = new ArrayList<>();
for (int i = 0; i < num_palette; i++) {
int ordinal = paletteToBlock[i];
blockToPalette[ordinal] = Integer.MAX_VALUE;
final BlockState state = BlockTypesCache.states[ordinal];
palette.add(((PaperweightBlockMaterial) state.getMaterial()).getState());
}
} else {
palette = List.of();
}
// Create palette with data
@SuppressWarnings("deprecation") // constructor is deprecated on paper, but needed to keep compatibility with spigot
final PalettedContainer<net.minecraft.world.level.block.state.BlockState> blockStatePalettedContainer =
new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
PalettedContainer.Strategy.SECTION_STATES,
PalettedContainer.Strategy.SECTION_STATES.getConfiguration(Block.BLOCK_STATE_REGISTRY, bitsPerEntry),
nmsBits,
palette
);
if (biomes == null) {
IdMap<Holder<Biome>> biomeHolderIdMap = biomeRegistry.asHolderIdMap();
biomes = new PalettedContainer<>(
biomeHolderIdMap,
biomeHolderIdMap.byIdOrThrow(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(
BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
}
return new LevelChunkSection(layer, blockStatePalettedContainer, biomes);
} catch (final Throwable e) {
throw e;
} finally {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
Arrays.fill(paletteToBlock, Integer.MAX_VALUE);
Arrays.fill(blockStates, 0);
Arrays.fill(blocksCopy, 0);
}
}
@SuppressWarnings("deprecation") // Only deprecated in paper
private static LevelChunkSection newChunkSection(
int layer,
Registry<Biome> biomeRegistry,
@Nullable PalettedContainer<Holder<Biome>> biomes
) {
if (biomes == null) {
return new LevelChunkSection(layer, biomeRegistry);
}
PalettedContainer<net.minecraft.world.level.block.state.BlockState> dataPaletteBlocks = new PalettedContainer<>(
Block.BLOCK_STATE_REGISTRY,
Blocks.AIR.defaultBlockState(),
PalettedContainer.Strategy.SECTION_STATES,
null
);
return new LevelChunkSection(layer, dataPaletteBlocks, biomes);
}
/**
* Create a new {@link PalettedContainer<Biome>}. Should only be used if no biome container existed beforehand.
*/
public static PalettedContainer<Holder<Biome>> getBiomePalettedContainer(
BiomeType[] biomes,
IdMap<Holder<Biome>> biomeRegistry
) {
if (biomes == null) {
return null;
}
BukkitImplAdapter<?> adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
// Don't stream this as typically will see 1-4 biomes; stream overhead is large for the small length
Map<BiomeType, Holder<Biome>> palette = new HashMap<>();
for (BiomeType biomeType : new LinkedList<>(Arrays.asList(biomes))) {
Holder<Biome> biome;
if (biomeType == null) {
biome = biomeRegistry.byId(adapter.getInternalBiomeId(BiomeTypes.PLAINS));
} else {
biome = biomeRegistry.byId(adapter.getInternalBiomeId(biomeType));
}
palette.put(biomeType, biome);
}
int biomeCount = palette.size();
int bitsPerEntry = MathMan.log2nlz(biomeCount - 1);
Object configuration = PalettedContainer.Strategy.SECTION_STATES.getConfiguration(
new FakeIdMapBiome(biomeCount),
bitsPerEntry
);
if (bitsPerEntry > 3) {
bitsPerEntry = MathMan.log2nlz(biomeRegistry.size() - 1);
}
PalettedContainer<Holder<Biome>> biomePalettedContainer = new PalettedContainer<>(
biomeRegistry,
biomeRegistry.byIdOrThrow(adapter.getInternalBiomeId(BiomeTypes.PLAINS)),
PalettedContainer.Strategy.SECTION_BIOMES,
null
);
final Palette<Holder<Biome>> biomePalette;
if (bitsPerEntry == 0) {
biomePalette = new SingleValuePalette<>(
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else if (bitsPerEntry == 4) {
biomePalette = LinearPalette.create(
4,
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else if (bitsPerEntry < 9) {
biomePalette = HashMapPalette.create(
bitsPerEntry,
biomePalettedContainer.registry,
biomePalettedContainer,
new ArrayList<>(palette.values()) // Must be modifiable
);
} else {
biomePalette = GlobalPalette.create(
bitsPerEntry,
biomePalettedContainer.registry,
biomePalettedContainer,
null // unused
);
}
int bitsPerEntryNonZero = Math.max(bitsPerEntry, 1); // We do want to use zero sometimes
final int blocksPerLong = MathMan.floorZero((double) 64 / bitsPerEntryNonZero);
final int arrayLength = MathMan.ceilZero(64f / blocksPerLong);
BitStorage bitStorage = bitsPerEntry == 0 ? new ZeroBitStorage(64) : new SimpleBitStorage(
bitsPerEntry,
64,
new long[arrayLength]
);
try {
Object data = dataConstructor.newInstance(configuration, bitStorage, biomePalette);
fieldData.set(biomePalettedContainer, data);
int index = 0;
for (int y = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
for (int x = 0; x < 4; x++, index++) {
BiomeType biomeType = biomes[index];
if (biomeType == null) {
continue;
}
Holder<Biome> biome = biomeRegistry.byId(WorldEditPlugin
.getInstance()
.getBukkitImplAdapter()
.getInternalBiomeId(biomeType));
if (biome == null) {
continue;
}
biomePalettedContainer.set(x, y, z, biome);
}
}
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
return biomePalettedContainer;
}
public static void clearCounts(final LevelChunkSection section) throws IllegalAccessException {
fieldTickingFluidCount.setShort(section, (short) 0);
fieldTickingBlockCount.setShort(section, (short) 0);
}
public static BiomeType adapt(Holder<Biome> biome, LevelAccessor levelAccessor) {
final Registry<Biome> biomeRegistry = levelAccessor.registryAccess().ownedRegistryOrThrow(Registry.BIOME_REGISTRY);
if (biomeRegistry.getKey(biome.value()) == null) {
return biomeRegistry.asHolderIdMap().getId(biome) == -1 ? BiomeTypes.OCEAN
: null;
}
return BiomeTypes.get(biome.unwrapKey().orElseThrow().location().toString());
}
static void removeBeacon(BlockEntity beacon, LevelChunk levelChunk) {
try {
if (levelChunk.loaded || levelChunk.level.isClientSide()) {
BlockEntity blockEntity = levelChunk.blockEntities.remove(beacon.getBlockPos());
if (blockEntity != null) {
if (!levelChunk.level.isClientSide) {
methodRemoveGameEventListener.invoke(levelChunk, beacon, levelChunk.level);
}
fieldRemove.set(beacon, true);
}
}
methodremoveTickingBlockEntity.invoke(levelChunk, beacon.getBlockPos());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
static List<Entity> getEntities(LevelChunk chunk) {
ExceptionCollector<RuntimeException> collector = new ExceptionCollector<>();
if (PaperLib.isPaper()) {
if (POST_CHUNK_REWRITE) {
try {
//noinspection unchecked
return (List<Entity>) PAPER_CHUNK_GEN_ALL_ENTITIES.invoke(chunk.level.getEntityLookup().getChunk(chunk.locX, chunk.locZ));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=true]", e);
}
}
try {
EntityList entityList = (EntityList) LEVEL_CHUNK_ENTITIES.get(chunk);
return List.of(entityList.getRawData());
} catch (IllegalAccessException e) {
collector.add(new RuntimeException("Failed to lookup entities [POST_CHUNK_REWRITE=false]", e));
// fall through
}
}
try {
//noinspection unchecked
return ((PersistentEntitySectionManager<Entity>) (SERVER_LEVEL_ENTITY_MANAGER.get(chunk.level))).getEntities(chunk.getPos());
} catch (IllegalAccessException e) {
collector.add(new RuntimeException("Failed to lookup entities [PAPER=false]", e));
}
collector.throwIfPresent();
return List.of();
}
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
@Override
public int getId(final net.minecraft.world.level.block.state.BlockState entry) {
return 0;
}
@Nullable
@Override
public net.minecraft.world.level.block.state.BlockState byId(final int index) {
return null;
}
@Nonnull
@Override
public Iterator<net.minecraft.world.level.block.state.BlockState> iterator() {
return Collections.emptyIterator();
}
}
record FakeIdMapBiome(int size) implements IdMap<Biome> {
@Override
public int getId(final Biome entry) {
return 0;
}
@Nullable
@Override
public Biome byId(final int index) {
return null;
}
@Nonnull
@Override
public Iterator<Biome> iterator() {
return Collections.emptyIterator();
}
}
}

Datei anzeigen

@ -0,0 +1,175 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.registry.state.PropertyKey;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import javax.annotation.Nullable;
public class PaperweightPostProcessor implements IBatchProcessor {
@Override
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
return set;
}
@SuppressWarnings("deprecation")
@Override
public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final IChunkSet iChunkSet) {
boolean tickFluid = Settings.settings().EXPERIMENTAL.ALLOW_TICK_FLUIDS;
// The PostProcessor shouldn't be added, but just in case
if (!tickFluid) {
return;
}
PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet;
layer:
for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) {
char[] set = iChunkSet.loadIfPresent(layer);
if (set == null) {
// No edit means no need to process
continue;
}
char[] get = null;
for (int i = 0; i < 4096; i++) {
char ordinal = set[i];
char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__;
boolean fromGet = false; // Used for liquids
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
if (get == null) {
get = getBlocks.load(layer);
}
// If this is null, then it's because we're loading a layer in the range of 0->15, but blocks aren't
// actually being set
if (get == null) {
continue layer;
}
fromGet = true;
ordinal = replacedOrdinal = get[i];
}
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
continue;
} else if (!fromGet) { // if fromGet, don't do the same again
if (get == null) {
get = getBlocks.load(layer);
}
replacedOrdinal = get[i];
}
boolean ticking = BlockTypesCache.ticking[ordinal];
boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal];
boolean replacedWasLiquid = false;
BlockState replacedState = null;
if (!ticking) {
// If the block being replaced was not ticking, it cannot be a liquid
if (!replacedWasTicking) {
continue;
}
// If the block being replaced is not fluid, we do not need to worry
if (!(replacedWasLiquid =
(replacedState = BlockState.getFromOrdinal(replacedOrdinal)).getMaterial().isLiquid())) {
continue;
}
}
BlockState state = BlockState.getFromOrdinal(ordinal);
boolean liquid = state.getMaterial().isLiquid();
int x = i & 15;
int y = (i >> 8) & 15;
int z = (i >> 4) & 15;
BlockPos position = new BlockPos((chunk.getX() << 4) + x, (layer << 4) + y, (chunk.getZ() << 4) + z);
if (liquid || replacedWasLiquid) {
if (liquid) {
addFluid(getBlocks.serverLevel, state, position);
continue;
}
// If the replaced fluid (is?) adjacent to water. Do not bother to check adjacent chunks(sections) as this
// may be time consuming. Chances are any fluid blocks in adjacent chunks are being replaced or will end up
// being ticked anyway. We only need it to be "hit" once.
if (!wasAdjacentToWater(get, set, i, x, y, z)) {
continue;
}
addFluid(getBlocks.serverLevel, replacedState, position);
}
}
}
}
@Nullable
@Override
public Extent construct(final Extent child) {
throw new UnsupportedOperationException("Processing only");
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.READING_SET_BLOCKS;
}
private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) {
if (set == null || get == null) {
return false;
}
char ordinal;
char reserved = BlockTypesCache.ReservedIDs.__RESERVED__;
if (x > 0 && set[i - 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) {
return true;
}
}
if (x < 15 && set[i + 1] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) {
return true;
}
}
if (z > 0 && set[i - 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) {
return true;
}
}
if (z < 15 && set[i + 16] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) {
return true;
}
}
if (y > 0 && set[i - 256] != reserved) {
if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) {
return true;
}
}
if (y < 15 && set[i + 256] != reserved) {
return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal);
}
return false;
}
@SuppressWarnings("deprecation")
private boolean isFluid(char ordinal) {
return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid();
}
@SuppressWarnings("deprecation")
private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) {
Fluid type;
if (replacedState.getBlockType() == BlockTypes.LAVA) {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.LAVA : Fluids.FLOWING_LAVA;
} else {
type = (int) replacedState.getState(PropertyKey.LEVEL) == 0 ? Fluids.WATER : Fluids.FLOWING_WATER;
}
serverLevel.scheduleTick(
position,
type,
type.getTickDelay(serverLevel)
);
}
}

Datei anzeigen

@ -0,0 +1,205 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.lighting.NMSRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.util.Unit;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
public class PaperweightStarlightRelighter implements Relighter {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final int CHUNKS_PER_BATCH = 1024; // 32 * 32
private static final int CHUNKS_PER_BATCH_SQRT_LOG2 = 5; // for shifting
private static final TicketType<Unit> FAWE_TICKET = TicketType.create("fawe_ticket", (a, b) -> 0);
private static final int LIGHT_LEVEL = ChunkMap.MAX_VIEW_DISTANCE + ChunkStatus.getDistance(ChunkStatus.LIGHT);
private final ServerLevel serverLevel;
private final ReentrantLock lock = new ReentrantLock();
private final Long2ObjectLinkedOpenHashMap<LongSet> regions = new Long2ObjectLinkedOpenHashMap<>();
private final ReentrantLock areaLock = new ReentrantLock();
private final NMSRelighter delegate;
@SuppressWarnings("rawtypes")
public PaperweightStarlightRelighter(ServerLevel serverLevel, IQueueExtent<IQueueChunk> queue) {
this.serverLevel = serverLevel;
this.delegate = new NMSRelighter(queue);
}
@Override
public boolean addChunk(int cx, int cz, byte[] skipReason, int bitmask) {
areaLock.lock();
try {
long key = MathMan.pairInt(cx >> CHUNKS_PER_BATCH_SQRT_LOG2, cz >> CHUNKS_PER_BATCH_SQRT_LOG2);
// TODO probably submit here already if chunks.size == CHUNKS_PER_BATCH?
LongSet chunks = this.regions.computeIfAbsent(key, k -> new LongArraySet(CHUNKS_PER_BATCH >> 2));
chunks.add(ChunkPos.asLong(cx, cz));
} finally {
areaLock.unlock();
}
return true;
}
@Override
public void addLightUpdate(int x, int y, int z) {
delegate.addLightUpdate(x, y, z);
}
/*
* This method is called "recursively", iterating and removing elements
* from the regions linked map. This way, chunks are loaded in batches to avoid
* OOMEs.
*/
@Override
public void fixLightingSafe(boolean sky) {
this.areaLock.lock();
try {
if (regions.isEmpty()) {
return;
}
LongSet first = regions.removeFirst();
fixLighting(first, () -> fixLightingSafe(true));
} finally {
this.areaLock.unlock();
}
}
/*
* Processes a set of chunks and runs an action afterwards.
* The action is run async, the chunks are partly processed on the main thread
* (as required by the server).
*/
private void fixLighting(LongSet chunks, Runnable andThen) {
// convert from long keys to ChunkPos
Set<ChunkPos> coords = new HashSet<>();
LongIterator iterator = chunks.iterator();
while (iterator.hasNext()) {
coords.add(new ChunkPos(iterator.nextLong()));
}
TaskManager.taskManager().task(() -> {
// trigger chunk load and apply ticket on main thread
List<CompletableFuture<?>> futures = new ArrayList<>();
for (ChunkPos pos : coords) {
futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z)
.thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel(
FAWE_TICKET,
pos,
LIGHT_LEVEL,
Unit.INSTANCE
))
);
}
// collect futures and trigger relight once all chunks are loaded
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(v ->
invokeRelight(
coords,
c -> {
}, // no callback for single chunks required
i -> {
if (i != coords.size()) {
LOGGER.warn("Processed {} chunks instead of {}", i, coords.size());
}
// post process chunks on main thread
TaskManager.taskManager().task(() -> postProcessChunks(coords));
// call callback on our own threads
TaskManager.taskManager().async(andThen);
}
)
);
});
}
private void invokeRelight(
Set<ChunkPos> coords,
Consumer<ChunkPos> chunkCallback,
IntConsumer processCallback
) {
try {
serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback);
} catch (Exception e) {
LOGGER.error("Error occurred on relighting", e);
}
}
/*
* Allow the server to unload the chunks again.
* Also, if chunk packets are sent delayed, we need to do that here
*/
private void postProcessChunks(Set<ChunkPos> coords) {
boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING;
for (ChunkPos pos : coords) {
int x = pos.x;
int z = pos.z;
if (delay) { // we still need to send the block changes of that chunk
PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false);
}
serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE);
}
}
@Override
public void clear() {
}
@Override
public void removeLighting() {
this.delegate.removeLighting();
}
@Override
public void fixBlockLighting() {
fixLightingSafe(true);
}
@Override
public void fixSkyLighting() {
fixLightingSafe(true);
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ReentrantLock getLock() {
return this.lock;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public void close() throws Exception {
fixLightingSafe(true);
}
}

Datei anzeigen

@ -0,0 +1,28 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1;
import com.fastasyncworldedit.core.extent.processor.lighting.NullRelighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.world.World;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import javax.annotation.Nonnull;
public class PaperweightStarlightRelighterFactory implements RelighterFactory {
@Override
public @Nonnull
@SuppressWarnings("rawtypes")
Relighter createRelighter(RelightMode relightMode, World world, IQueueExtent<IQueueChunk> queue) {
org.bukkit.World w = Bukkit.getWorld(world.getName());
if (w == null) {
return NullRelighter.INSTANCE;
}
return new PaperweightStarlightRelighter(((CraftWorld) w).getHandle(), queue);
}
}

Datei anzeigen

@ -0,0 +1,161 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.nbt;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.LazyCompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
import net.minecraft.nbt.NumericTag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class PaperweightLazyCompoundTag extends LazyCompoundTag {
private final Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier;
private CompoundTag compoundTag;
public PaperweightLazyCompoundTag(Supplier<net.minecraft.nbt.CompoundTag> compoundTagSupplier) {
super(new HashMap<>());
this.compoundTagSupplier = compoundTagSupplier;
}
public PaperweightLazyCompoundTag(net.minecraft.nbt.CompoundTag compoundTag) {
this(() -> compoundTag);
}
public net.minecraft.nbt.CompoundTag get() {
return compoundTagSupplier.get();
}
@Override
@SuppressWarnings("unchecked")
public Map<String, Tag> getValue() {
if (compoundTag == null) {
compoundTag = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(compoundTagSupplier.get());
}
return compoundTag.getValue();
}
@Override
public CompoundBinaryTag asBinaryTag() {
getValue();
return compoundTag.asBinaryTag();
}
public boolean containsKey(String key) {
return compoundTagSupplier.get().contains(key);
}
public byte[] getByteArray(String key) {
return compoundTagSupplier.get().getByteArray(key);
}
public byte getByte(String key) {
return compoundTagSupplier.get().getByte(key);
}
public double getDouble(String key) {
return compoundTagSupplier.get().getDouble(key);
}
public double asDouble(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsDouble();
}
return 0;
}
public float getFloat(String key) {
return compoundTagSupplier.get().getFloat(key);
}
public int[] getIntArray(String key) {
return compoundTagSupplier.get().getIntArray(key);
}
public int getInt(String key) {
return compoundTagSupplier.get().getInt(key);
}
public int asInt(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsInt();
}
return 0;
}
@SuppressWarnings("unchecked")
public List<Tag> getList(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag nbtList) {
ArrayList<Tag> list = new ArrayList<>();
for (net.minecraft.nbt.Tag elem : nbtList) {
if (elem instanceof net.minecraft.nbt.CompoundTag compoundTag) {
list.add(new PaperweightLazyCompoundTag(compoundTag));
} else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
}
}
return list;
}
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
public ListTag getListTag(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof net.minecraft.nbt.ListTag) {
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
}
return new ListTag(StringTag.class, Collections.emptyList());
}
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
ListTag listTag = getListTag(key);
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
}
public long[] getLongArray(String key) {
return compoundTagSupplier.get().getLongArray(key);
}
public long getLong(String key) {
return compoundTagSupplier.get().getLong(key);
}
public long asLong(String key) {
net.minecraft.nbt.Tag tag = compoundTagSupplier.get().get(key);
if (tag instanceof NumericTag numTag) {
return numTag.getAsLong();
}
return 0;
}
public short getShort(String key) {
return compoundTagSupplier.get().getShort(key);
}
public String getString(String key) {
return compoundTagSupplier.get().getString(key);
}
@Override
public String toString() {
return compoundTagSupplier.get().toString();
}
}

Datei anzeigen

@ -0,0 +1,564 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.regen;
import com.fastasyncworldedit.bukkit.adapter.Regenerator;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.queue.IChunkCache;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Lifecycle;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.Refraction;
import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R1.PaperweightGetBlocks;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.io.file.SafeFiles;
import com.sk89q.worldedit.world.RegenOptions;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.thread.ProcessorHandle;
import net.minecraft.util.thread.ProcessorMailbox;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.generator.CustomChunkGenerator;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalLong;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
public class PaperweightRegen extends Regenerator<ChunkAccess, ProtoChunk, LevelChunk, PaperweightRegen.ChunkStatusWrap> {
private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final Field serverWorldsField;
private static final Field paperConfigField;
private static final Field flatBedrockField;
private static final Field generatorSettingFlatField;
private static final Field generatorSettingBaseSupplierField;
private static final Field delegateField;
private static final Field chunkSourceField;
private static final Field ringPositionsField;
private static final Field hasGeneratedPositionsField;
//list of chunk stati in correct order without FULL
private static final Map<ChunkStatus, Concurrency> chunkStati = new LinkedHashMap<>();
static {
chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing
chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps
chunkStati.put(
ChunkStatus.STRUCTURE_REFERENCES,
Concurrency.FULL
); // structure refs: radius 8, but only writes to current chunk
chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0
chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8
chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE
chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(
ChunkStatus.LIQUID_CARVERS,
Concurrency.NONE
); // liquid carvers: radius 0, but RADIUS and FULL change results
chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps
chunkStati.put(
ChunkStatus.LIGHT,
Concurrency.FULL
); // light: radius 1, but no writes to other chunks, only current chunk
chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0
chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0
try {
serverWorldsField = CraftServer.class.getDeclaredField("worlds");
serverWorldsField.setAccessible(true);
Field tmpPaperConfigField;
Field tmpFlatBedrockField;
try { //only present on paper
tmpPaperConfigField = Level.class.getDeclaredField("paperConfig");
tmpPaperConfigField.setAccessible(true);
tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock");
tmpFlatBedrockField.setAccessible(true);
} catch (Exception e) {
tmpPaperConfigField = null;
tmpFlatBedrockField = null;
}
paperConfigField = tmpPaperConfigField;
flatBedrockField = tmpFlatBedrockField;
generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName(
"settings", "g"));
generatorSettingBaseSupplierField.setAccessible(true);
generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "f"));
generatorSettingFlatField.setAccessible(true);
delegateField = CustomChunkGenerator.class.getDeclaredField("delegate");
delegateField.setAccessible(true);
chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "L"));
chunkSourceField.setAccessible(true);
ringPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("ringPositions", "i"));
ringPositionsField.setAccessible(true);
hasGeneratedPositionsField = ChunkGenerator.class.getDeclaredField(Refraction.pickName("hasGeneratedPositions", "j"));
hasGeneratedPositionsField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//runtime
private ServerLevel originalServerWorld;
private ServerChunkCache originalChunkProvider;
private ServerLevel freshWorld;
private ServerChunkCache freshChunkProvider;
private LevelStorageSource.LevelStorageAccess session;
private StructureTemplateManager structureTemplateManager;
private ThreadedLevelLightEngine threadedLevelLightEngine;
private ChunkGenerator chunkGenerator;
private Path tempDir;
private boolean generateFlatBedrock = false;
public PaperweightRegen(org.bukkit.World originalBukkitWorld, Region region, Extent target, RegenOptions options) {
super(originalBukkitWorld, region, target, options);
}
@Override
protected boolean prepare() {
this.originalServerWorld = ((CraftWorld) originalBukkitWorld).getHandle();
originalChunkProvider = originalServerWorld.getChunkSource();
if (!(originalChunkProvider instanceof ServerChunkCache)) {
return false;
}
//flat bedrock? (only on paper)
if (paperConfigField != null) {
try {
generateFlatBedrock = flatBedrockField.getBoolean(paperConfigField.get(originalServerWorld));
} catch (Exception ignored) {
}
}
seed = options.getSeed().orElse(originalServerWorld.getSeed());
chunkStati.forEach((s, c) -> super.chunkStati.put(new ChunkStatusWrap(s), c));
return true;
}
@Override
@SuppressWarnings("unchecked")
protected boolean initNewWorld() throws Exception {
//world folder
tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen");
//prepare for world init (see upstream implementation for reference)
org.bukkit.World.Environment environment = originalBukkitWorld.getEnvironment();
org.bukkit.generator.ChunkGenerator generator = originalBukkitWorld.getGenerator();
LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(tempDir);
ResourceKey<LevelStem> levelStemResourceKey = getWorldDimKey(environment);
session = levelStorageSource.createAccess("faweregentempworld", levelStemResourceKey);
PrimaryLevelData originalWorldData = originalServerWorld.serverLevelData;
MinecraftServer server = originalServerWorld.getCraftServer().getServer();
WorldGenSettings originalOpts = originalWorldData.worldGenSettings();
WorldGenSettings newOpts = options.getSeed().isPresent()
? originalOpts.withSeed(originalWorldData.isHardcore(), OptionalLong.of(seed))
: originalOpts;
LevelSettings newWorldSettings = new LevelSettings(
"faweregentempworld",
originalWorldData.settings.gameType(),
originalWorldData.settings.hardcore(),
originalWorldData.settings.difficulty(),
originalWorldData.settings.allowCommands(),
originalWorldData.settings.gameRules(),
originalWorldData.settings.getDataPackConfig()
);
PrimaryLevelData newWorldData = new PrimaryLevelData(newWorldSettings, newOpts, Lifecycle.stable());
BiomeProvider biomeProvider = getBiomeProvider();
//init world
freshWorld = Fawe.instance().getQueueHandler().sync((Supplier<ServerLevel>) () -> new ServerLevel(
server,
server.executor,
session,
newWorldData,
originalServerWorld.dimension(),
newOpts.dimensions().getOrThrow(levelStemResourceKey),
new RegenNoOpWorldLoadListener(),
originalServerWorld.isDebug(),
seed,
ImmutableList.of(),
false,
environment,
generator,
biomeProvider
) {
private final Holder<Biome> singleBiome = options.hasBiomeType() ? BuiltinRegistries.BIOME.asHolderIdMap().byId(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())
) : null;
@Override
public void tick(BooleanSupplier shouldKeepTicking) { //no ticking
}
@Override
public Holder<Biome> getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) {
if (options.hasBiomeType()) {
return singleBiome;
}
return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome(
biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler()
);
}
}).get();
freshWorld.noSave = true;
removeWorldFromWorldsMap();
newWorldData.checkName(originalServerWorld.serverLevelData.getLevelName()); //rename to original world name
if (paperConfigField != null) {
paperConfigField.set(freshWorld, originalServerWorld.paperConfig());
}
ChunkGenerator originalGenerator = originalChunkProvider.getGenerator();
if (originalGenerator instanceof FlatLevelSource flatLevelSource) {
FlatLevelGeneratorSettings generatorSettingFlat = flatLevelSource.settings();
chunkGenerator = new FlatLevelSource(originalGenerator.structureSets, generatorSettingFlat);
} else if (originalGenerator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
Holder<NoiseGeneratorSettings> generatorSettingBaseSupplier = (Holder<NoiseGeneratorSettings>) generatorSettingBaseSupplierField.get(
originalGenerator);
BiomeSource biomeSource;
if (options.hasBiomeType()) {
biomeSource = new FixedBiomeSource(BuiltinRegistries.BIOME
.asHolderIdMap()
.byId(WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType())));
} else {
biomeSource = originalGenerator.getBiomeSource();
}
chunkGenerator = new NoiseBasedChunkGenerator(originalGenerator.structureSets,
noiseBasedChunkGenerator.noises,
biomeSource,
generatorSettingBaseSupplier
);
} else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) {
chunkGenerator = customChunkGenerator.getDelegate();
} else {
LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName());
return false;
}
if (generator != null) {
chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator);
generateConcurrent = generator.isParallelCapable();
}
chunkGenerator.conf = freshWorld.spigotConfig;
if (seed == originalOpts.seed() && !options.hasBiomeType()) {
// Optimisation for needless ring position calculation when the seed and biome is the same.
boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(originalGenerator);
if (hasGeneratedPositions) {
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> ringPositions =
(Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>>) ringPositionsField.get(
originalGenerator);
Map<ConcentricRingsStructurePlacement, CompletableFuture<List<ChunkPos>>> copy = new Object2ObjectArrayMap<>(ringPositions);
ringPositionsField.set(chunkGenerator, copy);
hasGeneratedPositionsField.setBoolean(chunkGenerator, true);
}
}
freshChunkProvider = new ServerChunkCache(
freshWorld,
session,
server.getFixerUpper(),
server.getStructureManager(),
server.executor,
chunkGenerator,
freshWorld.spigotConfig.viewDistance,
freshWorld.spigotConfig.simulationDistance,
server.forceSynchronousWrites(),
new RegenNoOpWorldLoadListener(),
(chunkCoordIntPair, state) -> {
},
() -> server.overworld().getDataStorage()
) {
// redirect to LevelChunks created in #createChunks
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) {
ChunkAccess chunkAccess = getChunkAt(x, z);
if (chunkAccess == null && create) {
chunkAccess = createChunk(getProtoChunkAt(x, z));
}
return chunkAccess;
}
};
ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
//let's start then
structureTemplateManager = server.getStructureManager();
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
return true;
}
@Override
protected void cleanup() {
try {
session.close();
} catch (Exception ignored) {
}
//shutdown chunk provider
try {
Fawe.instance().getQueueHandler().sync(() -> {
try {
freshChunkProvider.close(false);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} catch (Exception ignored) {
}
//remove world from server
try {
Fawe.instance().getQueueHandler().sync(this::removeWorldFromWorldsMap);
} catch (Exception ignored) {
}
//delete directory
try {
SafeFiles.tryHardToDeleteDir(tempDir);
} catch (Exception ignored) {
}
}
@Override
protected ProtoChunk createProtoChunk(int x, int z) {
return new FastProtoChunk(new ChunkPos(x, z), UpgradeData.EMPTY, freshWorld,
this.freshWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null
);
}
@Override
protected LevelChunk createChunk(ProtoChunk protoChunk) {
return new LevelChunk(
freshWorld,
protoChunk,
null // we don't want to add entities
);
}
@Override
protected ChunkStatusWrap getFullChunkStatus() {
return new ChunkStatusWrap(ChunkStatus.FULL);
}
@Override
protected List<BlockPopulator> getBlockPopulators() {
return originalServerWorld.getWorld().getPopulators();
}
@Override
protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) {
// BlockPopulator#populate has to be called synchronously for TileEntity access
TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()));
}
@Override
protected IChunkCache<IChunkGet> initSourceQueueCache() {
return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) {
@Override
public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) {
return getChunkAt(x, z);
}
};
}
//util
@SuppressWarnings("unchecked")
private void removeWorldFromWorldsMap() {
Fawe.instance().getQueueHandler().sync(() -> {
try {
Map<String, org.bukkit.World> map = (Map<String, org.bukkit.World>) serverWorldsField.get(Bukkit.getServer());
map.remove("faweregentempworld");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
private ResourceKey<LevelStem> getWorldDimKey(org.bukkit.World.Environment env) {
return switch (env) {
case NETHER -> LevelStem.NETHER;
case THE_END -> LevelStem.END;
default -> LevelStem.OVERWORLD;
};
}
private static class RegenNoOpWorldLoadListener implements ChunkProgressListener {
private RegenNoOpWorldLoadListener() {
}
@Override
public void updateSpawnPos(ChunkPos spawnPos) {
}
@Override
public void onStatusChange(ChunkPos pos, @Nullable ChunkStatus status) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
// TODO Paper only(?) @Override
public void setChunkRadius(int radius) {
}
}
private class FastProtoChunk extends ProtoChunk {
public FastProtoChunk(
final ChunkPos pos,
final UpgradeData upgradeData,
final LevelHeightAccessor world,
final Registry<Biome> biomeRegistry,
@Nullable final BlendingData blendingData
) {
super(pos, upgradeData, world, biomeRegistry, blendingData);
}
// avoid warning on paper
// compatibility with spigot
public boolean generateFlatBedrock() {
return generateFlatBedrock;
}
// no one will ever see the entities!
@Override
public List<CompoundTag> getEntities() {
return Collections.emptyList();
}
}
protected class ChunkStatusWrap extends ChunkStatusWrapper<ChunkAccess> {
private final ChunkStatus chunkStatus;
public ChunkStatusWrap(ChunkStatus chunkStatus) {
this.chunkStatus = chunkStatus;
}
@Override
public int requiredNeighborChunkRadius() {
return chunkStatus.getRange();
}
@Override
public String name() {
return chunkStatus.getName();
}
@Override
public CompletableFuture<?> processChunk(Long xz, List<ChunkAccess> accessibleChunks) {
return chunkStatus.generate(
Runnable::run, // TODO revisit, we might profit from this somehow?
freshWorld,
chunkGenerator,
structureTemplateManager,
threadedLevelLightEngine,
c -> CompletableFuture.completedFuture(Either.left(c)),
accessibleChunks,
true
);
}
}
/**
* A light engine that does nothing. As light is calculated after pasting anyway, we can avoid
* work this way.
*/
static class NoOpLightEngine extends ThreadedLevelLightEngine {
private static final ProcessorMailbox<Runnable> MAILBOX = ProcessorMailbox.create(task -> {}, "fawe-no-op");
private static final ProcessorHandle<Message<Runnable>> HANDLE = ProcessorHandle.of("fawe-no-op", m -> {});
public NoOpLightEngine(final ServerChunkCache chunkProvider) {
super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE);
}
@Override
public CompletableFuture<ChunkAccess> retainData(final ChunkAccess chunk) {
return CompletableFuture.completedFuture(chunk);
}
@Override
public CompletableFuture<ChunkAccess> lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) {
return CompletableFuture.completedFuture(chunk);
}
}
}

Datei anzeigen

@ -0,0 +1,17 @@
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension
plugins {
java
}
applyPaperweightAdapterConfiguration()
repositories {
gradlePluginPortal()
}
dependencies {
// https://papermc.io/repo/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.19.3-R0.1-20230312.180621-141")
compileOnly(libs.paperlib)
}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen