Compare commits

...

89 Commits

Author SHA1 Message Date
70baca7145 Better naming for "legacy" block state populator 2022-06-11 16:32:54 +01:00
2a90015037 Address comments
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-06-11 16:04:38 +01:00
f17aa377b7 Better exception handling when setting data to LimitedRegion during chunk population 2022-06-11 13:29:57 +01:00
e159fa054d Clean up HybridGen
- There's no need for while loops acting as a modulo after we've already performed a modulo
 - Make the code-sections calculating if positions are in the wall/road more readable
 - Collaps duplicate if-elseif bodies
2022-06-11 13:24:03 +01:00
058c65e34c Ensure Location is still sealed, and add api description annotation to public methods in UncheckedWorldLocation 2022-06-11 13:04:05 +01:00
8608604306 Address comments regarding javadocs/comments 2022-06-11 13:03:09 +01:00
8d0cc68721 Don't do the big error if heads don't work 2022-06-09 22:00:51 +01:00
2a79c0a419 Javadocs 2022-06-09 21:07:49 +01:00
90d42b8b9f Implement tile entities to generation using Populators
- Fixes #3051
2022-06-09 20:49:43 +01:00
a79c474957 Deprecate methods for removal that will be removed/had their signatures changed in v7 2022-06-09 13:49:58 +01:00
4bb480a238 chore: Update Code of conduct email (#3661) 2022-06-09 12:58:31 +02:00
9ffa935c0c build: Switch to bill of materials (#3653)
* build: Switch to managed dependencies

* build: Move bom to root build script

* build: Update bom

* Update build.gradle.kts

* fix: Use the correct bom version
2022-06-09 12:57:37 +02:00
0a32268784 Prevent blocks moving/generating below and above build height (#3641)
* fix: cancel BlockFormEvent outside of build limit

* refactor: rename variables for easier readability

* fix: cancel liquid flow outside build limit

* refactor: implement to/from context
2022-06-05 20:51:07 +02:00
ae3b8c06f6 chore: Address Paper javadoc warnings (#3648) 2022-06-05 20:50:49 +02:00
713c4ad0d2 Remove aggregation of cross module javadocs (#3646)
chore: Don't aggregate javadocs anymore
2022-06-03 23:13:41 +02:00
48386c0828 build: Back to snapshot for development 2022-06-01 20:12:50 +02:00
625b3921e1 build: Release 6.8.1 2022-06-01 20:09:36 +02:00
48aa37d173 Update Readme SVG (#3642)
docs: Update Readme SVG
2022-05-30 13:47:25 +02:00
2c2314e95c refactor: return info.server for %plotsquared_currentplot_owner% if plot is a server plot (#3640) 2022-05-25 10:18:10 +02:00
5eb2fc3ad0 Kick players on merged plots appropriately (#3639)
fix: kick denied player regardless on all connected plots
2022-05-24 20:30:06 +02:00
82cd9a092c build: Update fawe to v2.2.0 (#3637)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-24 13:33:54 +02:00
62754362c2 build: Don't expose jcip and findbugs annotations to the world on runtime (#3533)
* build: Don't expose jcip and findbugs

* build: Revert relocation change of unpublished, shaded deps

* chore: Exclude .DS_Store files
2022-05-21 10:01:06 +00:00
2e9dfd6f6f chore: Update PaperMC repository endpoint (#3633)
Migration - New PaperMC endpoints
2022-05-21 07:57:22 +02:00
fc9fe1462f build: Back to snapshot for development 2022-05-18 22:07:22 +02:00
41f546ca6b build: Release 6.8.0 2022-05-18 22:05:31 +02:00
d037da33cb chore: Ignore .DS_Store files 2022-05-18 21:59:09 +02:00
dc2d08c67e build: Update release-drafter/release-drafter action to v5.20.0 (#3624)
* 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:19:23 +02:00
96dfc27411 Fix lag caused when generating augmented worlds with roads (#3614)
- Begin by implementing forceSync to the queue system as we know the chunk will be accessible to edits in some cases (i.e. population).
 - Also implement custom SideEffectSets to override any decided by the default chunk consumer, as we do NOT want to update neighbours in population (this caused infinite generation to be required causing the lag and server death). We also do not want to enqueue the QueueCoordinator in AugmentedUtils as this would write to the world and update neighbours before we might want to (plus it's just used to restrict and offset the blocks being set)
 - Then implement disabling any biomes from being saved/set to the queue to prevent augmented worlds having their biomes overridden in roads
 - Consequently fix ScopedQueueCoordinator, preventing the y value of blocks being set from needlessly being changed, fixing road heights in augmented worlds
 - Finally we do not need a method with chunkObject in the signature in AugmentedUtils as this is no longer used by the method
2022-05-16 13:27:41 +01:00
171d2e5e99 Fix generation of augmented/partial worlds when single worlds are enabled (#3615) 2022-05-16 13:21:43 +01:00
4433892431 fix: Block Endermites from spawning if mob spawning is disabled (#3623) 2022-05-16 13:20:03 +01:00
98a07dad1b Fix plot analysis (#3618)
* Fix plot analysis
 - Stop using deprecated ChunkQueueCoordinator and create a new purpose-built coordinator
 - Generation is chunk-by-chunk thus the old blocks cache needs to be filled accordingly
 - Remove the **four** System#gc calls
 - Fixes #3464
 - Fix really weird dumb... maths? in ExpiryTask
 - Fixes #3600

* Add since annotation

* Address comments and maxY should be inclusive

* Annotate new queue as internal use only
2022-05-15 11:58:04 +02:00
0ffa22b7a6 Deprecations to Queues (#3613)
* Deprecations and niceties
 - Deprecate ScopedQueueCoordinator as it is poorly named
 - Deprecate ChunkQueueCoordinator for complete removal as it is poorly designed (though still used)

* Add since tags
2022-05-15 11:57:26 +02:00
60a0129fe9 Correctly use yIndex when regenerating plots in certain world configurations (#3601)
- Fixes #3597
2022-05-15 11:42:19 +02:00
d5f8a0842b make y location of homes always absolute part 2 (#3620) 2022-05-13 15:46:52 +02:00
f7d55ce105 Implement restoring tags directly using a supplied block (#3616)
- Reduces overhead when setting blocks via fallback
 - Also means blocks will not be accessed via world when they should be access via chunk (https://github.com/IntellectualSites/PlotSquared/pull/3612)
2022-05-11 13:12:19 +01:00
85911646f3 Add ability to disable random Mojang uuid API calls (#3586)
* feature: ability to disable impromtu Mojang uuid API calls

* refactor: update comment for the new setting
2022-05-11 13:11:57 +01:00
8b75dece69 Implement chunkObject into queueing (#3612) 2022-05-11 13:11:38 +01:00
7d6e515ba8 Improvements to /plot list command (#3585)
* refactor: list command shows owner better
added check for:
- unknown owners (UUID not cached/invalid)
- server plots
- plots owner by everyone

* fix: show correct color in list command if plot is owned by everyone

* refactor: improved List command for server plots

(cherry picked from commit fed700f0d8)

* refactor: removed duplicate code

* refactor: renamed placeholders to reflect their use

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-05-10 09:50:27 +02:00
13d7357c85 Niceties
- Better ordering of augmented information printed to consol on startup
 - Override
2022-05-10 01:43:01 +01:00
16e26b910c build: Update dependency com.github.spotbugs:spotbugs-annotations to v4.7.0 (#3606)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-09 13:53:59 +02:00
faadebd30e chore: Update my name (#3599) 2022-05-07 15:56:24 +02:00
2aeacb3dcf build: Back to snapshot for development 2022-05-05 10:07:58 +02:00
9db7791835 build: Release 6.7.0 2022-05-05 09:58:14 +02:00
f49ddb819d Add Plot flag for projectiles (#3581)
* feature: add flag for projectiles

* build: add License to ProjectilesFlag.java

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-05-04 23:21:24 +02:00
d71c62771e build: Update dependency org.checkerframework:checker-qual to v3.22.0 (#3595)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-03 09:58:14 +02:00
a6aaa9538f Set plot biome chunk by chunk (#3590)
* Actually set plot biome chunk by chunk

* Better variable name for chunk position
2022-04-30 14:16:58 +02:00
0974fb2834 [ci skip] build: Update com.fastasyncworldedit to v2.1.2 (#3588)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-25 16:56:30 +02:00
8982b33b6c build: Update github/codeql-action action to v2 (#3589)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-25 15:59:30 +02:00
a7b3b3b7df build: Back to snapshot for development 2022-04-19 08:50:50 +02:00
888bb20e78 build: Release 6.6.3 2022-04-19 08:45:44 +02:00
b11bb6fa22 make y location of homes always absolute (#3568) 2022-04-19 00:48:51 +02:00
e5764b958d build: Replace jsr305 with spotbugs (#3576) 2022-04-19 00:48:23 +02:00
bfe3141ff1 style: Emphasize project icon in idea selection (#3577) 2022-04-19 00:47:38 +02:00
73c82deeb0 build: Switch back to upstream SquirrelID (#3575) 2022-04-19 00:46:39 +02:00
38682ecff6 fix: share the QueueCoordinator in PlotModificationManager#unlinkPlot (#3571)
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2022-04-15 07:01:53 +00:00
6a54dc7eff fix: typo (MaxBuildHeight -> MinBuildHeight) (#3572) 2022-04-15 08:59:01 +02:00
8454c29c91 fix: Make PlayerManager#resolveName blocking for entry title (#3556) 2022-04-11 14:38:02 +00:00
b2c9311a47 build: Update com.fastasyncworldedit to v2.1.1 (#3562)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 15:32:02 +02:00
c4aa497a2b build: Update actions/setup-java action to v3.1.0 (#3563)
* 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:31:53 +02:00
c13f544390 build: Back to snapshot for development 2022-04-04 13:03:49 +02:00
c28177d6af build: Release 6.6.2 2022-04-04 12:56:13 +02:00
8a80f252cf chore: Fill in since TODOs 2022-04-04 12:54:42 +02:00
93571c72d1 build: Update dependency org.checkerframework:checker-qual to v3.21.4 (#3561)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 12:47:38 +02:00
6fd7379221 build: Update dependency gradle to v7.4.2 (#3560)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-04 12:46:49 +02:00
dc5c80d812 clean up PlayerCommandPreprocess listener (#3557) 2022-04-01 19:30:37 +02:00
96e9a61e7c refactor: Deprecate Load#secToTime() (#3558) 2022-04-01 19:30:11 +02:00
b9bd9b81e6 Make confirm tasks synchronous. It was changed in 7ac3f7ca03 (#3551) 2022-03-23 15:04:39 +01:00
ec77812879 build: Update com.sk89q.worldedit to v7.2.10 (#3554)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-21 11:49:34 +01:00
efc2083798 Change the default sign orientation to better match the wall location 2022-03-15 16:25:40 +00:00
3a6f845c01 Use correct field for unsaved in 1.18 2022-03-15 16:25:23 +00:00
7efd42ae45 build: Ignore kyori updates until we update MM
Closes #3543
2022-03-14 20:09:52 +01:00
f43f4cbf5d build: Update com.fastasyncworldedit to v2.1.0 (#3541)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 15:36:43 +01:00
104cc4b7a4 build: Update dependency net.essentialsx:EssentialsX to v2.19.4 (#3540)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 12:40:03 +01:00
218be43143 build: Update dependency gradle to v7.4.1 (#3539)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-14 12:39:46 +01:00
308dba5601 Only add extent to WE operations once (#3537) 2022-03-10 22:40:09 +01:00
5f233bb5d1 Use new FAWE method including actor for schematic pasting 2022-03-09 16:31:33 +01:00
5e188d114f build: Misc dependency updates 2022-03-08 20:50:19 +01:00
660e05d27f build: Back to snapshot for development 2022-03-08 20:21:23 +01:00
4c0ad148bf build: Release 6.6.1 2022-03-08 20:15:16 +01:00
5c7bfb988c Fix #3532 2022-03-08 18:14:19 +00:00
b46f486680 build: Update actions/checkout action to v3 (#3530)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-07 23:14:24 +01:00
05797d0c78 build: Update dependency org.checkerframework:checker-qual to v3.21.3 (#3528)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-07 20:55:39 +01:00
36ef2cf9ba build: Update dependency net.essentialsx:EssentialsX to v2.19.3 (#3527)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-07 20:55:28 +01:00
26ec31a012 build: Back to snapshot for development 2022-03-07 15:55:25 +01:00
fd4a542062 build: Release 6.6.0 2022-03-07 15:35:00 +01:00
dc13f2565f ci: Pin GH workflow dependencies 2022-03-07 15:26:41 +01:00
9f632af0ae Implement extended world heights from Y-64 to Y319 #3473 (#3473)
* Begin to implement extended world heights:
 - Implemented in Bukkit module (and where required in Core module)

* Implement extended world heights into core module

* Add min gen height to setup,

* Default gen/build heights based on minecraft version

* Few fixes

* Fix up queues

* Address comments

* Make road schematic stuff slightly more efficient by sharing queues

* Minor fixes, don't overlay error many times for the same y

* Fix incorrect schematic paste height, undo changes to HybridUtils

* Overhall regenallroads method to make it work, make sure BukkitChunkCoordinator can/will finish

* Process chunks in order when regenerating all roads

* Address comments

* Address comments

* Ground level//bedrock is at min gen height
 - Add comment on == rather than <= being used
 - It's because it's only checking for the bedrock layer being broken if that's disabled

* Fix offset for min build height in SchematicHandler

* Better javadoc

Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>

* Address inclusivity issues for max world height

* Javadocs/comments/deprecation

* Use world min/max heights if present in QueueCoordinator

* Address some deprecations for regions and biome setting

* Add a count for chunks we're currently trying to load to not skip chunks at the end of a queue's edit

* Use minGenHeight + 1 rather than build height in AugmentedUtils

* Create utility method for layer index in GenChunk

* Correct height in HybridUtils, also use minGenHeight + 1

* Don't magically split to 128 height in regeneration

* Add utility methods for world height in QueueCoordinator

* Clean up ClassicPlotManager road creation/removal

* Start generation at min gen height if bedrock is disabled

* min gen height is set in PlotArea

* Add note on schem y normalisation

* Improve plot getVolume method readability

* Don't overly extend height when regenerating road region

* y index utility method in ChunknQueueCoordinator

* Layer index utility method in LocalChunk

* Use version min/max heights if world not present in QueueCoordinator

* Fix min -> max

* Don't allow players to modify outside build height when using plot set  / schematics.
 - Also fixes schematic height issues

* Remove debug

* Address comments

* Switch loadingChunks to AtomicInteger to be safe (in case of multi-threaded)

* Fix "security" issue that was already present

* Ensure sign isn't physicsed

Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2022-03-05 19:03:39 +01:00
d698c6a1e5 [ci skip] Update issue templates for 1.18.2 2022-03-04 13:25:50 +01:00
40e1bd9897 build: Update dependency cloud.commandframework:cloud-services to v1.6.2 (#3522)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-01 16:31:40 +01:00
98 changed files with 2413 additions and 981 deletions

View File

@ -27,6 +27,7 @@ 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. 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 multiple: false
options: options:
- '1.18.2'
- '1.18.1' - '1.18.1'
- '1.18' - '1.18'
- '1.17.1' - '1.17.1'

View File

@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v2.4.0 uses: actions/checkout@v3
- name: Validate Gradle Wrapper" - name: Validate Gradle Wrapper"
uses: gradle/wrapper-validation-action@v1.0.4 uses: gradle/wrapper-validation-action@v1
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3.0.0 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 17 java-version: 17

View File

@ -23,15 +23,15 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v2

View File

@ -14,6 +14,6 @@ jobs:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: release-drafter/release-drafter@v5.18.1 - uses: release-drafter/release-drafter@v5
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

10
.gitignore vendored
View File

@ -41,7 +41,8 @@ hs_err_pid*
*.iml *.iml
## Directory-based project format: ## Directory-based project format:
.idea/ /.idea/*
!/.idea/icon.svg
# if you remove the above rule, at least ignore the following: # if you remove the above rule, at least ignore the following:
# User-specific stuff: # User-specific stuff:
@ -74,9 +75,6 @@ hs_err_pid*
# IntelliJ # IntelliJ
/out/ /out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin # JIRA plugin
atlassian-ide-plugin.xml atlassian-ide-plugin.xml
@ -133,5 +131,9 @@ local.properties
checkstyle.xml checkstyle.xml
classes/ classes/
*.bat *.bat
# Other
docs/ docs/
build/ build/
.DS_Store

50
.idea/icon.svg generated Normal file
View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" id="svg2" xml:space="preserve" width="4000" height="3333.3333" viewBox="0 0 4000 3333.3333" sodipodi:docname="PlotSquared.ai">
<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>
</defs>
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview4" />
<g id="g10" inkscape:groupmode="layer" inkscape:label="PlotSquared" transform="matrix(1.3333333,0,0,-1.3333333,0,3333.3333)">
<g id="g12">
<g id="g14" clip-path="url(#clipPath18)">
<g id="g20" transform="translate(1486.1511,2242.6453)">
<path d="m 0,0 c 16.533,10.846 33.211,21.453 50.104,31.699 78.972,-48.281 153.985,-102.704 227.269,-159.144 148.61,-115.422 287.884,-243.01 414.393,-382.333 111.39,-122.861 212.751,-255.152 298.898,-396.971 52.744,-87.322 100.544,-177.884 139.514,-272.214 -11.638,-3.551 -23.108,-7.655 -34.362,-12.286 l -0.24,0.288 c -11.135,12.982 -24.141,24.212 -34.915,37.506 -22.557,23.013 -45.425,45.737 -68.03,68.678 -19.725,20.253 -40.601,39.45 -58.958,60.974 -36.355,36.451 -72.517,73.093 -108.944,109.471 -22.628,26.013 -48.064,49.385 -71.965,74.197 -19.029,19.485 -38.706,38.346 -57.519,57.999 -12.166,14.998 -26.684,27.716 -39.93,41.658 -27.668,27.524 -54.903,55.479 -82.571,82.979 -23.924,27.956 -51.664,52.264 -76.692,79.164 -4.68,4.487 -8.855,10.774 -15.886,11.326 -22.34,34.027 -58.311,57.327 -97.377,67.502 -104.312,99.153 -215.487,191.202 -332.661,274.782 -117.942,-83.94 -229.476,-176.781 -334.484,-276.39 -26.684,-0.024 -53.368,0.024 -80.076,-0.024 0.024,-26.564 0.048,-53.104 0,-79.668 -72.229,-73.021 -139.491,-150.937 -202.385,-232.092 -63.758,-82.619 -121.973,-169.51 -173.541,-260.264 131.932,-69.061 257.864,-149.521 375.926,-240.275 0.096,-26.444 -0.12,-52.888 0.096,-79.332 l 0.744,-0.984 c 20.109,-24.14 43.409,-45.233 65.126,-67.861 15.118,-15.382 30.571,-30.404 45.569,-45.881 17.565,-20.733 37.698,-39.042 56.607,-58.503 19.917,-20.781 41.25,-40.218 59.967,-62.151 29.156,-29.299 58.167,-58.815 87.515,-87.922 29.155,-33.043 61.502,-63.111 92.169,-94.738 13.726,-12.67 25.124,-27.571 38.634,-40.457 25.029,-25.365 50.129,-50.657 75.325,-75.853 -37.914,-51.208 -73.741,-103.952 -107.192,-158.183 -167.83,273.317 -397.235,507.305 -662.37,687.158 -81.875,55.335 -167.23,105.584 -255.681,149.641 -52.815,26.276 -106.831,50.248 -162.239,70.381 99.393,233.628 242.795,446.715 410.289,636.79 93.562,106.088 194.634,205.433 301.466,298.13 C -217.335,-155.808 -111.439,-73.789 0,0" style="fill:#062f4c;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path22" />
</g>
<g id="g24" transform="translate(1201.7948,1741.5303)">
<path d="M 0,0 C 105.008,99.609 216.543,192.45 334.485,276.39 451.659,192.81 562.833,100.76 667.146,1.608 c -34.987,8.83 -71.51,9.718 -107.264,6.431 -41.202,-4.296 -82.907,-19.077 -112.543,-48.953 -33.019,-32.155 -49.456,-77.604 -55.311,-122.501 -28.124,27.908 -56.104,55.983 -84.035,84.083 -2.976,2.976 -6.839,4.823 -10.391,6.911 -19.029,26.348 -45.953,46.673 -76.62,57.495 C 187.555,-2.472 151.513,-0.12 116.166,0 Z" style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path26" />
</g>
<g id="g28" transform="translate(919.3342,1429.7462)">
<path d="m 0,0 c 62.894,81.156 130.156,159.072 202.385,232.092 0.048,-244.21 0.024,-488.421 0,-732.631 C 84.323,-409.785 -41.61,-329.325 -173.541,-260.264 -121.973,-169.51 -63.758,-82.619 0,0" style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path30" />
</g>
<g id="g32" transform="translate(1649.134,1700.6166)">
<path d="m 0,0 c 29.635,29.875 71.341,44.657 112.543,48.952 35.754,3.288 72.277,2.4 107.263,-6.431 39.066,-10.174 75.037,-33.474 97.377,-67.501 11.879,-17.661 20.181,-37.411 26.42,-57.687 10.871,-38.802 11.95,-79.356 11.446,-119.358 -44.345,-0.072 -88.69,0.048 -133.035,-0.072 -1.032,30.907 3.263,63.686 -10.175,92.626 -9.526,20.325 -32.107,31.243 -53.751,32.131 -21.453,1.44 -45.065,-4.32 -59.175,-21.597 -12.79,-15.861 -15.382,-37.002 -16.558,-56.655 -1.295,-29.132 3.696,-59.031 17.518,-84.923 16.821,-30.619 39.378,-57.783 64.526,-81.9 31.387,-32.634 67.501,-60.374 97.857,-94.041 27.332,-28.988 51.256,-61.479 68.005,-97.785 20.541,-41.13 26.972,-87.827 25.82,-133.372 -0.912,-32.107 -5.231,-64.406 -16.149,-94.737 -11.59,-31.699 -31.123,-61.047 -58.335,-81.371 -25.124,-19.125 -55.696,-29.852 -86.651,-34.771 -49.552,-6.743 -101.888,-4.847 -148.465,14.854 -35.227,14.829 -64.238,42.689 -81.708,76.548 -20.996,40.242 -27.115,86.339 -27.259,131.212 0.048,17.829 0,35.658 0.048,53.463 44.345,0.048 88.69,-0.023 133.059,0.048 1.728,-35.538 -4.055,-72.06 5.663,-106.807 5.783,-22.173 26.204,-37.794 48.185,-41.754 20.733,-3.431 43.577,-2.015 61.622,9.791 15.502,9.43 23.949,26.78 26.78,44.225 5.903,35.922 1.872,74.293 -15.381,106.688 -16.918,30.595 -39.474,57.711 -64.55,81.899 -33.187,34.099 -71.173,63.254 -102.585,99.081 -26.756,28.867 -49.408,61.646 -65.486,97.641 -24.572,52.48 -26.731,112.422 -20.18,169.102 C -49.456,-77.604 -33.019,-32.155 0,0" style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path34" />
</g>
<g id="g36" transform="translate(1262.7214,1613.126)">
<path d="m 0,0 v -301.13 c 23.204,0.024 46.409,-0.048 69.613,0.024 18.525,0.288 38.202,6.575 50.153,21.429 12.43,17.277 13.917,39.522 14.613,60.111 0.024,43.985 -0.048,87.994 0.024,131.979 -0.48,23.637 -0.983,50.369 -17.277,69.23 C 104.864,-5.711 86.867,-0.24 69.589,0 46.385,0.048 23.204,0.024 0,0 m -141.002,128.38 c 26.708,0.048 53.392,0 80.075,0.024 H 55.24 c 35.346,-0.12 71.389,-2.471 104.815,-14.925 30.668,-10.823 57.592,-31.148 76.621,-57.496 26.852,-39.09 36.69,-87.202 38.058,-133.947 0.024,-48.833 0.096,-97.689 -0.024,-146.521 -1.728,-47.993 -11.974,-97.953 -41.514,-136.971 -22.748,-30.644 -57.495,-50.801 -94.281,-59.583 -45.377,-11.878 -92.578,-6.791 -138.891,-7.847 -0.072,-111.799 0,-223.574 -0.024,-335.373 -13.942,0 -27.86,0.024 -41.778,-0.024 -32.802,0.072 -65.605,0 -98.384,0.048 l -0.744,0.984 c -0.216,26.444 0,52.888 -0.096,79.332 0.024,244.211 0.048,488.421 0,732.632 0.048,26.563 0.024,53.103 0,79.667" style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path38" />
</g>
<g id="g40" transform="translate(1966.3174,1675.6364)">
<path d="m 0,0 c 7.031,-0.552 11.206,-6.839 15.885,-11.326 25.029,-26.9 52.768,-51.208 76.693,-79.164 27.667,-27.5 54.903,-55.456 82.571,-82.979 13.246,-13.942 27.764,-26.66 39.93,-41.658 18.813,-19.653 38.49,-38.514 57.519,-57.999 23.9,-24.812 49.337,-48.185 71.965,-74.197 36.427,-36.378 72.589,-73.02 108.943,-109.471 18.358,-21.524 39.234,-40.722 58.959,-60.974 22.605,-22.941 45.473,-45.665 68.03,-68.678 10.774,-13.294 23.78,-24.524 34.914,-37.506 -103.904,-41.97 -203.488,-94.114 -298.922,-152.761 -246.994,-152.28 -466.224,-350.298 -639.333,-583.398 -25.197,25.196 -50.297,50.488 -75.325,75.852 -13.51,12.886 -24.908,27.788 -38.634,40.458 -30.667,31.627 -63.014,61.695 -92.17,94.738 -29.347,29.107 -58.359,58.623 -87.514,87.922 -18.717,21.933 -40.05,41.37 -59.967,62.151 -18.909,19.461 -39.042,37.77 -56.607,58.503 -14.998,15.477 -30.452,30.499 -45.569,45.88 -21.717,22.629 -45.017,43.722 -65.126,67.862 32.779,-0.048 65.582,0.024 98.384,-0.048 114.391,-98.097 220.407,-205.984 315.384,-322.99 92.914,114.318 196.242,220.022 307.753,316.271 30.955,4.919 61.526,15.646 86.65,34.771 27.212,20.325 46.745,49.672 58.335,81.371 107.312,77.988 219.327,149.929 337.509,210.376 -35.299,64.67 -75.829,126.437 -118.254,186.643 C 176.253,-228.037 104.24,-140.115 26.42,-57.687 20.181,-37.41 11.878,-17.661 0,0" style="fill:#042338;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path42" />
</g>
<g id="g44" transform="translate(1499.3971,1669.1094)">
<path d="m 0,0 c 3.551,-2.088 7.415,-3.935 10.39,-6.911 27.932,-28.1 55.912,-56.175 84.036,-84.083 -6.551,-56.679 -4.392,-116.622 20.18,-169.102 16.078,-35.994 38.73,-68.774 65.486,-97.641 31.412,-35.826 69.398,-64.982 102.585,-99.081 25.076,-24.188 47.632,-51.304 64.55,-81.899 17.253,-32.395 21.284,-70.765 15.381,-106.688 -2.831,-17.445 -11.278,-34.794 -26.78,-44.225 -18.045,-11.806 -40.889,-13.222 -61.622,-9.79 -21.981,3.959 -42.402,19.58 -48.185,41.753 -9.718,34.747 -3.935,71.269 -5.663,106.808 -44.369,-0.072 -88.714,0 -133.059,-0.048 -0.048,-17.806 0,-35.635 -0.048,-53.464 0.144,-44.873 6.263,-90.97 27.259,-131.212 17.47,-33.859 46.481,-61.718 81.708,-76.548 46.577,-19.701 98.913,-21.597 148.465,-14.854 -111.511,-96.249 -214.839,-201.953 -307.753,-316.271 -94.977,117.006 -200.993,224.893 -315.383,322.99 13.918,0.048 27.836,0.024 41.777,0.024 0.024,111.799 -0.048,223.574 0.024,335.372 46.313,1.056 93.514,-4.031 138.891,7.847 36.786,8.783 71.533,28.94 94.282,59.583 29.539,39.018 39.785,88.978 41.513,136.971 0.12,48.833 0.048,97.689 0.024,146.522 C 36.69,-87.203 26.852,-39.09 0,0" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path46" />
</g>
<g id="g48" transform="translate(1748.0469,1601.6797)">
<path d="M 0,0 C 14.11,17.277 37.722,23.036 59.175,21.597 80.82,20.709 103.4,9.791 112.927,-10.534 c 13.438,-28.94 9.142,-61.719 10.174,-92.626 44.345,0.12 88.691,0 133.036,0.072 0.504,40.002 -0.576,80.556 -11.447,119.358 77.82,-82.428 149.833,-170.35 215.583,-262.664 42.426,-60.207 82.956,-121.973 118.254,-186.643 -118.182,-60.447 -230.196,-132.388 -337.508,-210.376 10.918,30.331 15.238,62.63 16.149,94.737 1.152,45.545 -5.279,92.242 -25.82,133.372 -16.749,36.306 -40.673,68.797 -68.005,97.785 -30.355,33.667 -66.47,61.406 -97.857,94.041 -25.148,24.117 -47.705,51.28 -64.526,81.9 -13.822,25.892 -18.813,55.791 -17.517,84.923 C -15.382,-37.002 -12.79,-15.862 0,0" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path50" />
</g>
<g id="g52" transform="translate(1262.7214,1613.126)">
<path d="m 0,0 c 23.204,0.024 46.385,0.048 69.589,0 17.278,-0.24 35.275,-5.711 47.537,-18.357 16.294,-18.861 16.797,-45.593 17.277,-69.23 -0.072,-43.985 0,-87.994 -0.024,-131.979 -0.696,-20.589 -2.183,-42.834 -14.613,-60.111 -11.951,-14.854 -31.628,-21.141 -50.153,-21.429 -23.204,-0.072 -46.409,0 -69.613,-0.024 z" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path54" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,4 +0,0 @@
jdkVersion = "17"
build = "gradle clean build -x test"
tools = ["findsecbugs", "ErrorProne", "Semgrep", "Detekt", "Infer"]
ignoreRules = ["CatchAndPrintStackTrace", "ReferenceEquality", "FallThrough", "FutureReturnValueIgnored", "MixedMutabilityReturnType", "EmptyCatch", "MissingCasesInEnumSwitch", "OperatorPrecedence", "StaticAssignmentInConstructor", "ReferenceEquality", "EqualsHashCode", "EqualsGetClass", "TypeParameterUnusedInFormals", "StringSplitter", "InlineMeSuggester", "NULL_DEREFERENCE"]

View File

@ -8,7 +8,7 @@ repositories {
maven { maven {
name = "PaperMC" name = "PaperMC"
url = uri("https://papermc.io/repo/repository/maven-public/") url = uri("https://repo.papermc.io/repository/maven-public/")
} }
maven { maven {
@ -21,20 +21,20 @@ dependencies {
api(projects.plotSquaredCore) api(projects.plotSquaredCore)
// Metrics // Metrics
implementation(libs.bstats) implementation("org.bstats:bstats-bukkit")
// Paper // Paper
compileOnly(libs.paper) compileOnly(libs.paper)
implementation(libs.paperlib) implementation("io.papermc:paperlib")
// Plugins // Plugins
compileOnly(libs.worldeditBukkit) { compileOnly(libs.worldeditBukkit) {
exclude(group = "org.bukkit") exclude(group = "org.bukkit")
exclude(group = "org.spigotmc") exclude(group = "org.spigotmc")
} }
compileOnly(libs.fastasyncworldeditBukkit) { isTransitive = false } compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false }
testImplementation(libs.fastasyncworldeditBukkit) { isTransitive = false } testImplementation("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false }
compileOnly(libs.vault) { compileOnly("com.github.MilkBowl:VaultAPI") {
exclude(group = "org.bukkit") exclude(group = "org.bukkit")
} }
compileOnly(libs.placeholderapi) compileOnly(libs.placeholderapi)
@ -44,15 +44,15 @@ dependencies {
// Other libraries // Other libraries
implementation(libs.squirrelid) { isTransitive = false } implementation(libs.squirrelid) { isTransitive = false }
implementation(libs.serverlib) implementation("dev.notmyfault.serverlib:ServerLib")
// Our libraries // Our libraries
implementation(libs.arkitektonika) implementation(libs.arkitektonika)
implementation(libs.http4j) implementation(libs.http4j)
implementation(libs.paster) implementation("com.intellectualsites.paster:Paster")
// Adventure // Adventure
implementation(libs.adventurePlatformBukkit) implementation("net.kyori:adventure-platform-bukkit")
} }
tasks.processResources { tasks.processResources {
@ -83,8 +83,10 @@ tasks.named<ShadowJar>("shadowJar") {
relocate("org.jetbrains", "com.plotsquared.core.annotations") relocate("org.jetbrains", "com.plotsquared.core.annotations")
relocate("org.intellij.lang", "com.plotsquared.core.intellij.annotations") relocate("org.intellij.lang", "com.plotsquared.core.intellij.annotations")
relocate("javax.annotation", "com.plotsquared.core.annotation") relocate("javax.annotation", "com.plotsquared.core.annotation")
relocate("com.google.code.findbugs", "com.plotsquared.core.findbugs") relocate("com.github.spotbugs", "com.plotsquared.core.spotbugs")
relocate("javax.inject", "com.plotsquared.core.annotation.inject") relocate("javax.inject", "com.plotsquared.core.annotation.inject")
relocate("net.jcip", "com.plotsquared.core.annotations.jcip")
relocate("edu.umd.cs.findbugs", "com.plotsquared.core.annotations.findbugs")
// Get rid of all the libs which are 100% unused. // Get rid of all the libs which are 100% unused.
minimize() minimize()
@ -95,7 +97,7 @@ tasks.named<ShadowJar>("shadowJar") {
tasks { tasks {
withType<Javadoc> { withType<Javadoc> {
val opt = options as StandardJavadocDocletOptions val opt = options as StandardJavadocDocletOptions
opt.links("https://papermc.io/javadocs/paper/1.18/") opt.links("https://jd.papermc.io/paper/1.18/")
opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-bukkit/" + libs.worldeditBukkit.get().versionConstraint.toString()) opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-bukkit/" + libs.worldeditBukkit.get().versionConstraint.toString())
opt.links("https://javadoc.io/doc/com.plotsquared/PlotSquared-Core/latest/") opt.links("https://javadoc.io/doc/com.plotsquared/PlotSquared-Core/latest/")
opt.links("https://jd.adventure.kyori.net/api/" + libs.adventure.get().versionConstraint.toString()) opt.links("https://jd.adventure.kyori.net/api/" + libs.adventure.get().versionConstraint.toString())

View File

@ -238,6 +238,16 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
return this.version; return this.version;
} }
@Override
public int versionMinHeight() {
return serverVersion()[1] >= 18 ? -64 : 0;
}
@Override
public int versionMaxHeight() {
return serverVersion()[1] >= 18 ? 319 : 255;
}
@Override @Override
public @NonNull String serverImplementation() { public @NonNull String serverImplementation() {
return Bukkit.getVersion(); return Bukkit.getVersion();
@ -503,8 +513,10 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
this.backgroundPipeline.registerService(essentialsUUIDService); this.backgroundPipeline.registerService(essentialsUUIDService);
} }
final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT); if (Settings.UUID.IMPROMPTU_SERVICE_MOJANG_API) {
this.impromptuPipeline.registerService(impromptuMojangService); final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT);
this.impromptuPipeline.registerService(impromptuMojangService);
}
final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT);
this.backgroundPipeline.registerService(backgroundMojangService); this.backgroundPipeline.registerService(backgroundMojangService);
} else { } else {

View File

@ -25,17 +25,18 @@
*/ */
package com.plotsquared.bukkit.generator; package com.plotsquared.bukkit.generator;
import com.plotsquared.core.PlotSquared; import com.plotsquared.bukkit.queue.LimitedRegionWrapperQueue;
import com.plotsquared.core.generator.HybridPlotWorld;
import com.plotsquared.core.generator.IndependentPlotGenerator; import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.UncheckedWorldLocation;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.LimitedRegion;
import org.bukkit.generator.WorldInfo;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Random; import java.util.Random;
@ -43,32 +44,51 @@ import java.util.Random;
final class BlockStatePopulator extends BlockPopulator { final class BlockStatePopulator extends BlockPopulator {
private final IndependentPlotGenerator plotGenerator; private final IndependentPlotGenerator plotGenerator;
private final PlotAreaManager plotAreaManager;
private QueueCoordinator queue; /**
* @since TODO
*/
public BlockStatePopulator(
final @NonNull IndependentPlotGenerator plotGenerator
) {
this.plotGenerator = plotGenerator;
}
/**
* @deprecated Use {@link BlockStatePopulator#BlockStatePopulator(IndependentPlotGenerator)} as plotAreManager is unused
*/
@Deprecated(forRemoval = true, since = "TODO")
public BlockStatePopulator( public BlockStatePopulator(
final @NonNull IndependentPlotGenerator plotGenerator, final @NonNull IndependentPlotGenerator plotGenerator,
final @NonNull PlotAreaManager plotAreaManager final @NonNull PlotAreaManager plotAreaManager
) { ) {
this.plotGenerator = plotGenerator; this.plotGenerator = plotGenerator;
this.plotAreaManager = plotAreaManager;
} }
@Override @Override
public void populate(final @NonNull World world, final @NonNull Random random, final @NonNull Chunk source) { public void populate(
if (this.queue == null) { @NonNull final WorldInfo worldInfo,
this.queue = PlotSquared.platform().globalBlockQueue().getNewQueue(new BukkitWorld(world)); @NonNull final Random random,
} final int chunkX,
final PlotArea area = this.plotAreaManager.getPlotArea(world.getName(), null); final int chunkZ,
if (area == null) { @NonNull final LimitedRegion limitedRegion
) {
PlotArea area = UncheckedWorldLocation.at(worldInfo.getName(), chunkX << 4, 0, chunkZ << 4).getPlotArea();
if (area == null || (area instanceof HybridPlotWorld hpw && !hpw.populationNeeded()) || area instanceof SinglePlotArea) {
return; return;
} }
final ChunkWrapper wrap = new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ()); LimitedRegionWrapperQueue wrapped = new LimitedRegionWrapperQueue(limitedRegion);
final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z); // It is possible for the region to be larger than the chunk, but there is no reason for P2 to need to populate
if (this.plotGenerator.populateChunk(chunk, area)) { // outside of the actual chunk area.
this.queue.enqueue(); Location min = UncheckedWorldLocation.at(worldInfo.getName(), chunkX << 4, worldInfo.getMinHeight(), chunkZ << 4);
} Location max = UncheckedWorldLocation.at(
worldInfo.getName(),
(chunkX << 4) + 15,
worldInfo.getMaxHeight(),
(chunkZ << 4) + 15
);
ScopedQueueCoordinator offsetChunkQueue = new ScopedQueueCoordinator(wrapped, min, max);
this.plotGenerator.populateChunk(offsetChunkQueue, area);
} }
} }

View File

@ -25,7 +25,11 @@
*/ */
package com.plotsquared.bukkit.generator; package com.plotsquared.bukkit.generator;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.AugmentedUtils;
import com.plotsquared.core.queue.QueueCoordinator;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.util.SideEffectSet;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
@ -52,7 +56,14 @@ public class BukkitAugmentedGenerator extends BlockPopulator {
@Override @Override
public void populate(@NonNull World world, @NonNull Random random, @NonNull Chunk source) { public void populate(@NonNull World world, @NonNull Random random, @NonNull Chunk source) {
AugmentedUtils.generate(source, world.getName(), source.getX(), source.getZ(), null); QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(BukkitAdapter.adapt(world));
// The chunk is already loaded and we do not want to load the chunk in "fully" by using any PaperLib methods.
queue.setForceSync(true);
queue.setSideEffectSet(SideEffectSet.none());
queue.setBiomesEnabled(false);
queue.setChunkObject(source);
AugmentedUtils.generateChunk(world.getName(), source.getX(), source.getZ(), queue);
queue.enqueue();
} }
} }

View File

@ -27,6 +27,7 @@ package com.plotsquared.bukkit.generator;
import com.plotsquared.bukkit.queue.GenChunk; import com.plotsquared.bukkit.queue.GenChunk;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.BukkitWorld;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.generator.GeneratorWrapper;
import com.plotsquared.core.generator.IndependentPlotGenerator; import com.plotsquared.core.generator.IndependentPlotGenerator;
@ -48,8 +49,7 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
public class BukkitPlotGenerator extends ChunkGenerator public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
implements GeneratorWrapper<ChunkGenerator> {
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final boolean PAPER_ASYNC_SAFE = true; public final boolean PAPER_ASYNC_SAFE = true;
@ -72,7 +72,12 @@ public class BukkitPlotGenerator extends ChunkGenerator
this.plotGenerator = generator; this.plotGenerator = generator;
this.platformGenerator = this; this.platformGenerator = this;
this.populators = new ArrayList<>(); this.populators = new ArrayList<>();
this.populators.add(new BlockStatePopulator(this.plotGenerator, this.plotAreaManager)); int minecraftMinorVersion = PlotSquared.platform().serverVersion()[1];
if (minecraftMinorVersion >= 17) {
this.populators.add(new BlockStatePopulator(this.plotGenerator));
} else {
this.populators.add(new LegacyBlockStatePopulator(this.plotGenerator));
}
this.full = true; this.full = true;
} }
@ -158,13 +163,14 @@ public class BukkitPlotGenerator extends ChunkGenerator
@NonNull World world, @NonNull Random random, int x, int z, @NonNull World world, @NonNull Random random, int x, int z,
@NonNull BiomeGrid biome @NonNull BiomeGrid biome
) { ) {
int minY = BukkitWorld.getMinWorldHeight(world);
GenChunk result = new GenChunk(); int maxY = BukkitWorld.getMaxWorldHeight(world);
GenChunk result = new GenChunk(minY, maxY);
if (this.getPlotGenerator() instanceof SingleWorldGenerator) { if (this.getPlotGenerator() instanceof SingleWorldGenerator) {
if (result.getChunkData() != null) { if (result.getChunkData() != null) {
for (int chunkX = 0; chunkX < 16; chunkX++) { for (int chunkX = 0; chunkX < 16; chunkX++) {
for (int chunkZ = 0; chunkZ < 16; chunkZ++) { for (int chunkZ = 0; chunkZ < 16; chunkZ++) {
for (int y = 0; y < world.getMaxHeight(); y++) { for (int y = minY; y < maxY; y++) {
biome.setBiome(chunkX, y, chunkZ, Biome.PLAINS); biome.setBiome(chunkX, y, chunkZ, Biome.PLAINS);
} }

View File

@ -80,7 +80,8 @@ final class DelegatePlotGenerator extends IndependentPlotGenerator {
result.setBiome(x, z, BukkitAdapter.adapt(biome)); result.setBiome(x, z, BukkitAdapter.adapt(biome));
} }
//do not annotate with Override until we discontinue support for 1.4.4 //do not annotate with Override until we discontinue support for 1.4.4 (we no longer support 1.4.4)
@Override
public void setBiome(int x, int y, int z, @NonNull Biome biome) { public void setBiome(int x, int y, int z, @NonNull Biome biome) {
result.setBiome(x, z, BukkitAdapter.adapt(biome)); result.setBiome(x, z, BukkitAdapter.adapt(biome));

View File

@ -0,0 +1,81 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2014 - 2022 IntellectualSites
*
* 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.plotsquared.bukkit.generator;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.generator.HybridPlotWorld;
import com.plotsquared.core.generator.IndependentPlotGenerator;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.location.UncheckedWorldLocation;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.util.SideEffectSet;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
final class LegacyBlockStatePopulator extends BlockPopulator {
private final IndependentPlotGenerator plotGenerator;
/**
* @since TODO
*/
public LegacyBlockStatePopulator(
final @NonNull IndependentPlotGenerator plotGenerator
) {
this.plotGenerator = plotGenerator;
}
@Override
public void populate(@NotNull final World world, @NotNull final Random random, @NotNull final Chunk source) {
int chunkMinX = source.getX() << 4;
int chunkMinZ = source.getZ() << 4;
PlotArea area = Location.at(world.getName(), chunkMinX, 0, chunkMinZ).getPlotArea();
if (area == null || (area instanceof HybridPlotWorld hpw && !hpw.populationNeeded()) || area instanceof SinglePlotArea) {
return;
}
QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(new BukkitWorld(world));
queue.setForceSync(true);
queue.setSideEffectSet(SideEffectSet.none());
queue.setBiomesEnabled(false);
queue.setChunkObject(source);
Location min = UncheckedWorldLocation.at(world.getName(), chunkMinX, world.getMinHeight(), chunkMinZ);
Location max = UncheckedWorldLocation.at(world.getName(), chunkMinX + 15, world.getMaxHeight(), chunkMinZ + 15);
ScopedQueueCoordinator offsetChunkQueue = new ScopedQueueCoordinator(queue, min, max);
this.plotGenerator.populateChunk(offsetChunkQueue, area);
queue.enqueue();
}
}

View File

@ -354,7 +354,8 @@ public class BlockEventListener implements Listener {
Plot plot = area.getPlot(location); Plot plot = area.getPlot(location);
if (plot != null) { if (plot != null) {
BukkitPlayer plotPlayer = BukkitUtil.adapt(player); BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
if (event.getBlock().getY() == 0) { // == rather than <= as we only care about the "ground level" not being destroyed
if (event.getBlock().getY() == area.getMinGenHeight()) {
if (!Permissions if (!Permissions
.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) {
plotPlayer.sendMessage( plotPlayer.sendMessage(
@ -550,6 +551,10 @@ public class BlockEventListener implements Listener {
if (plot == null) { if (plot == null) {
return; return;
} }
if (location.getY() >= area.getMaxBuildHeight() || location.getY() < area.getMinBuildHeight()) {
event.setCancelled(true);
return;
}
switch (event.getNewState().getType()) { switch (event.getNewState().getType()) {
case SNOW: case SNOW:
case SNOW_BLOCK: case SNOW_BLOCK:
@ -649,7 +654,8 @@ public class BlockEventListener implements Listener {
event.getBlock().breakNaturally(); event.getBlock().breakNaturally();
} }
} }
if (location.getY() == 0) { // == rather than <= as we only care about the "ground level" not being destroyed
if (location.getY() == area.getMinGenHeight()) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
@ -748,62 +754,66 @@ public class BlockEventListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onChange(BlockFromToEvent event) { public void onChange(BlockFromToEvent event) {
Block from = event.getBlock(); Block fromBlock = event.getBlock();
// Check liquid flow flag inside of origin plot too // Check liquid flow flag inside of origin plot too
final Location fLocation = BukkitUtil.adapt(from.getLocation()); final Location fromLocation = BukkitUtil.adapt(fromBlock.getLocation());
final PlotArea fromArea = fLocation.getPlotArea(); final PlotArea fromArea = fromLocation.getPlotArea();
if (fromArea != null) { if (fromArea != null) {
final Plot plot = fromArea.getOwnedPlot(fLocation); final Plot fromPlot = fromArea.getOwnedPlot(fromLocation);
if (plot != null && plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event if (fromPlot != null && fromPlot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event
.getBlock() .getBlock()
.isLiquid()) { .isLiquid()) {
plot.debug("Liquid could not flow because liquid-flow = disabled"); fromPlot.debug("Liquid could not flow because liquid-flow = disabled");
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
} }
Block to = event.getToBlock(); Block toBlock = event.getToBlock();
Location tLocation = BukkitUtil.adapt(to.getLocation()); Location toLocation = BukkitUtil.adapt(toBlock.getLocation());
PlotArea area = tLocation.getPlotArea(); PlotArea toArea = toLocation.getPlotArea();
if (area == null) { if (toArea == null) {
if (from.getType() == Material.DRAGON_EGG && fromArea != null) { if (fromBlock.getType() == Material.DRAGON_EGG && fromArea != null) {
event.setCancelled(true); event.setCancelled(true);
} }
return; return;
} }
Plot plot = area.getOwnedPlot(tLocation); if (toLocation.getY() >= toArea.getMaxBuildHeight() || toLocation.getY() < toArea.getMinBuildHeight()) {
event.setCancelled(true);
return;
}
Plot toPlot = toArea.getOwnedPlot(toLocation);
if (from.getType() == Material.DRAGON_EGG && fromArea != null) { if (fromBlock.getType() == Material.DRAGON_EGG && fromArea != null) {
final Plot fromPlot = fromArea.getOwnedPlot(fLocation); final Plot fromPlot = fromArea.getOwnedPlot(fromLocation);
if (fromPlot != null || plot != null) { if (fromPlot != null || toPlot != null) {
if ((fromPlot == null || !fromPlot.equals(plot)) && (plot == null || !plot.equals(fromPlot))) { if ((fromPlot == null || !fromPlot.equals(toPlot)) && (toPlot == null || !toPlot.equals(fromPlot))) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
} }
} }
if (plot != null) { if (toPlot != null) {
if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects.equals(plot, area.getOwnedPlot(fLocation))) { if (!toArea.contains(fromLocation.getX(), fromLocation.getZ()) || !Objects.equals(toPlot, toArea.getOwnedPlot(fromLocation))) {
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.ENABLED && event.getBlock().isLiquid()) { if (toPlot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.ENABLED && event.getBlock().isLiquid()) {
return; return;
} }
if (plot.getFlag(DisablePhysicsFlag.class)) { if (toPlot.getFlag(DisablePhysicsFlag.class)) {
plot.debug(event.getBlock().getType() + " could not update because disable-physics = true"); toPlot.debug(event.getBlock().getType() + " could not update because disable-physics = true");
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event.getBlock().isLiquid()) { if (toPlot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event.getBlock().isLiquid()) {
plot.debug("Liquid could not flow because liquid-flow = disabled"); toPlot.debug("Liquid could not flow because liquid-flow = disabled");
event.setCancelled(true); event.setCancelled(true);
} }
} else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects.equals(null, area.getOwnedPlot(fLocation))) { } else if (!toArea.contains(fromLocation.getX(), fromLocation.getZ()) || !Objects.equals(null, toArea.getOwnedPlot(fromLocation))) {
event.setCancelled(true); event.setCancelled(true);
} else if (event.getBlock().isLiquid()) { } else if (event.getBlock().isLiquid()) {
final org.bukkit.Location location = event.getBlock().getLocation(); final org.bukkit.Location location = event.getBlock().getLocation();

View File

@ -168,6 +168,7 @@ public class EntityEventListener implements Listener {
case "RAID": case "RAID":
case "SHEARED": case "SHEARED":
case "SILVERFISH_BLOCK": case "SILVERFISH_BLOCK":
case "ENDER_PEARL":
case "TRAP": case "TRAP":
case "VILLAGE_DEFENSE": case "VILLAGE_DEFENSE":
case "VILLAGE_INVASION": case "VILLAGE_INVASION":

View File

@ -44,6 +44,7 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.DoneFlag;
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.Template;
@ -195,6 +196,7 @@ public class PaperListener implements Listener {
case "RAID": case "RAID":
case "SHEARED": case "SHEARED":
case "SILVERFISH_BLOCK": case "SILVERFISH_BLOCK":
case "ENDER_PEARL":
case "TRAP": case "TRAP":
case "VILLAGE_DEFENSE": case "VILLAGE_DEFENSE":
case "VILLAGE_INVASION": case "VILLAGE_INVASION":
@ -352,13 +354,15 @@ public class PaperListener implements Listener {
event.setCancelled(true); event.setCancelled(true);
} }
} else if (!plot.isAdded(pp.getUUID())) { } else if (!plot.isAdded(pp.getUUID())) {
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) { if (!plot.getFlag(ProjectilesFlag.class)) {
pp.sendMessage( if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
TranslatableCaption.of("permission.no_permission_event"), pp.sendMessage(
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) TranslatableCaption.of("permission.no_permission_event"),
); Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
entity.remove(); );
event.setCancelled(true); entity.remove();
event.setCancelled(true);
}
} }
} }
} }

View File

@ -76,7 +76,6 @@ import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.PremiumVerification;
import com.plotsquared.core.util.RegExUtil;
import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
import com.plotsquared.core.util.task.TaskTime; import com.plotsquared.core.util.task.TaskTime;
@ -223,10 +222,9 @@ public class PlayerEventListener extends PlotListener implements Listener {
} }
} }
@SuppressWarnings("StringSplitter")
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void playerCommand(PlayerCommandPreprocessEvent event) { public void playerCommand(PlayerCommandPreprocessEvent event) {
String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim(); String msg = event.getMessage().replace("/", "").toLowerCase(Locale.ROOT).trim();
if (msg.isEmpty()) { if (msg.isEmpty()) {
return; return;
} }
@ -240,11 +238,9 @@ public class PlayerEventListener extends PlotListener implements Listener {
String[] parts = msg.split(" "); String[] parts = msg.split(" ");
Plot plot = plotPlayer.getCurrentPlot(); Plot plot = plotPlayer.getCurrentPlot();
// Check WorldEdit // Check WorldEdit
switch (parts[0].toLowerCase()) { switch (parts[0]) {
case "up": case "up":
case "/up":
case "worldedit:up": case "worldedit:up":
case "worldedit:/up":
if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !Permissions if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !Permissions
.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER, true))) { .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER, true))) {
event.setCancelled(true); event.setCancelled(true);
@ -258,63 +254,67 @@ public class PlayerEventListener extends PlotListener implements Listener {
List<String> blockedCommands = plot != null ? List<String> blockedCommands = plot != null ?
plot.getFlag(BlockedCmdsFlag.class) : plot.getFlag(BlockedCmdsFlag.class) :
area.getFlag(BlockedCmdsFlag.class); area.getFlag(BlockedCmdsFlag.class);
if (!blockedCommands.isEmpty() && !Permissions if (blockedCommands.isEmpty()) {
.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { return;
String part = parts[0]; }
if (parts[0].contains(":")) { if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) {
part = parts[0].split(":")[1]; return;
msg = msg.replace(parts[0].split(":")[0] + ':', ""); }
} // When using namespaced commands, we're not interested in the namespace
String s1 = part; String part = parts[0];
List<String> aliases = new ArrayList<>(); if (part.contains(":")) {
for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) { String[] namespaced = part.split(":");
if (part.equals(cmdLabel.getName())) { part = namespaced[1];
break; msg = msg.substring(namespaced[0].length() + 1);
} }
String label = cmdLabel.getName().replaceFirst("/", ""); msg = replaceAliases(msg, part);
if (aliases.contains(label)) { for (String blocked : blockedCommands) {
continue; if (blocked.equalsIgnoreCase(msg)) {
} String perm;
PluginCommand p; if (plot != null && plot.isAdded(plotPlayer.getUUID())) {
if ((p = Bukkit.getPluginCommand(label)) != null) { perm = "plots.admin.command.blocked-cmds.shared";
for (String a : p.getAliases()) {
if (aliases.contains(a)) {
continue;
}
aliases.add(a);
a = a.replaceFirst("/", "");
if (!a.equals(label) && a.equals(part)) {
part = label;
break;
}
}
}
}
if (!s1.equals(part)) {
msg = msg.replace(s1, part);
}
for (String s : blockedCommands) {
Pattern pattern;
if (!RegExUtil.compiledPatterns.containsKey(s)) {
RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s));
} else { } else {
pattern = RegExUtil.compiledPatterns.get(s); perm = "plots.admin.command.blocked-cmds.road";
} }
if (pattern.matcher(msg).matches()) { if (!Permissions.hasPermission(plotPlayer, perm)) {
String perm; plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked"));
if (plot != null && plot.isAdded(plotPlayer.getUUID())) { event.setCancelled(true);
perm = "plots.admin.command.blocked-cmds.shared"; }
} else { return;
perm = "plots.admin.command.blocked-cmds.road"; }
}
}
private String replaceAliases(String msg, String part) {
String s1 = part;
Set<String> aliases = new HashSet<>();
for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) {
if (part.equals(cmdLabel.getName())) {
break;
}
String label = cmdLabel.getName().replaceFirst("/", "");
if (aliases.contains(label)) {
continue;
}
PluginCommand p = Bukkit.getPluginCommand(label);
if (p != null) {
for (String a : p.getAliases()) {
if (aliases.contains(a)) {
continue;
} }
if (!Permissions.hasPermission(plotPlayer, perm)) { aliases.add(a);
plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked")); a = a.replaceFirst("/", "");
event.setCancelled(true); if (!a.equals(label) && a.equals(part)) {
part = label;
break;
} }
return;
} }
} }
} }
if (!s1.equals(part)) {
msg = msg.replace(s1, part);
}
return msg;
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

View File

@ -35,6 +35,7 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotHandler; import com.plotsquared.core.plot.PlotHandler;
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.Template;
@ -128,13 +129,15 @@ public class ProjectileEventListener implements Listener {
event.setCancelled(true); event.setCancelled(true);
} }
} else if (!plot.isAdded(pp.getUUID())) { } else if (!plot.isAdded(pp.getUUID())) {
if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) { if (!plot.getFlag(ProjectilesFlag.class)) {
pp.sendMessage( if (!Permissions.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) {
TranslatableCaption.of("permission.no_permission_event"), pp.sendMessage(
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) TranslatableCaption.of("permission.no_permission_event"),
); Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER))
entity.remove(); );
event.setCancelled(true); entity.remove();
event.setCancelled(true);
}
} }
} }
} }
@ -162,7 +165,7 @@ public class ProjectileEventListener implements Listener {
return; return;
} }
if (plot.isAdded(pp.getUUID()) || Permissions if (plot.isAdded(pp.getUUID()) || Permissions
.hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) { .hasPermission(pp, Permission.PERMISSION_ADMIN_PROJECTILE_OTHER) || plot.getFlag(ProjectilesFlag.class)) {
return; return;
} }
entity.remove(); entity.remove();

View File

@ -46,7 +46,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass;
public class SingleWorldListener implements Listener { public class SingleWorldListener implements Listener {
private final Method methodGetHandleChunk; private final Method methodGetHandleChunk;
private Field shouldSave; private Field shouldSave = null;
public SingleWorldListener() throws Exception { public SingleWorldListener() throws Exception {
ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
@ -59,9 +59,12 @@ public class SingleWorldListener implements Listener {
} else { } else {
this.shouldSave = classChunk.getField("s").getRealField(); this.shouldSave = classChunk.getField("s").getRealField();
} }
} else { } else if (PlotSquared.platform().serverVersion()[1] == 17) {
ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk"); ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk");
this.shouldSave = classChunk.getField("r").getRealField(); this.shouldSave = classChunk.getField("r").getRealField();
} else if (PlotSquared.platform().serverVersion()[1] == 18) {
ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.IChunkAccess");
this.shouldSave = classChunk.getField("b").getRealField();
} }
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -74,11 +74,13 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
private final Consumer<Throwable> throwableConsumer; private final Consumer<Throwable> throwableConsumer;
private final boolean unloadAfter; private final boolean unloadAfter;
private final int totalSize; private final int totalSize;
private final AtomicInteger expectedSize; private final AtomicInteger expectedSize;
private final AtomicInteger loadingChunks = new AtomicInteger();
private final boolean forceSync;
private int batchSize; private int batchSize;
private PlotSquaredTask task; private PlotSquaredTask task;
private boolean shouldCancel; private volatile boolean shouldCancel;
private boolean finished; private boolean finished;
@Inject @Inject
@ -91,7 +93,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
@Assisted final @NonNull Runnable whenDone, @Assisted final @NonNull Runnable whenDone,
@Assisted final @NonNull Consumer<Throwable> throwableConsumer, @Assisted final @NonNull Consumer<Throwable> throwableConsumer,
@Assisted final boolean unloadAfter, @Assisted final boolean unloadAfter,
@Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers @Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers,
@Assisted final boolean forceSync
) { ) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks); this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>(); this.availableChunks = new LinkedBlockingQueue<>();
@ -106,14 +109,27 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class); this.plugin = JavaPlugin.getPlugin(BukkitPlatform.class);
this.bukkitWorld = Bukkit.getWorld(world.getName()); this.bukkitWorld = Bukkit.getWorld(world.getName());
this.progressSubscribers.addAll(progressSubscribers); this.progressSubscribers.addAll(progressSubscribers);
this.forceSync = forceSync;
} }
@Override @Override
public void start() { public void start() {
// Request initial batch if (!forceSync) {
this.requestBatch(); // Request initial batch
// Wait until next tick to give the chunks a chance to be loaded this.requestBatch();
TaskManager.runTaskLater(() -> task = TaskManager.runTaskRepeat(this, TaskTime.ticks(1)), TaskTime.ticks(1)); // Wait until next tick to give the chunks a chance to be loaded
TaskManager.runTaskLater(() -> task = TaskManager.runTaskRepeat(this, TaskTime.ticks(1)), TaskTime.ticks(1));
} else {
try {
while (!shouldCancel && !requestedChunks.isEmpty()) {
chunkConsumer.accept(requestedChunks.poll());
}
} catch (Throwable t) {
throwableConsumer.accept(t);
} finally {
finish();
}
}
} }
@Override @Override
@ -130,7 +146,9 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
for (final ProgressSubscriber subscriber : this.progressSubscribers) { for (final ProgressSubscriber subscriber : this.progressSubscribers) {
subscriber.notifyEnd(); subscriber.notifyEnd();
} }
task.cancel(); if (task != null) {
task.cancel();
}
finished = true; finished = true;
} }
} }
@ -150,6 +168,13 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
Chunk chunk = this.availableChunks.poll(); Chunk chunk = this.availableChunks.poll();
if (chunk == null) { if (chunk == null) {
if (this.availableChunks.isEmpty()) {
if (this.requestedChunks.isEmpty() && loadingChunks.get() == 0) {
finish();
} else {
requestBatch();
}
}
return; return;
} }
long[] iterationTime = new long[2]; long[] iterationTime = new long[2];
@ -197,9 +222,11 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
BlockVector2 chunk; BlockVector2 chunk;
for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) { for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
// This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent // This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent
loadingChunks.incrementAndGet();
PaperLib PaperLib
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true) .getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true)
.whenComplete((chunkObject, throwable) -> { .whenComplete((chunkObject, throwable) -> {
loadingChunks.decrementAndGet();
if (throwable != null) { if (throwable != null) {
throwable.printStackTrace(); throwable.printStackTrace();
// We want one less because this couldn't be processed // We want one less because this couldn't be processed

View File

@ -51,6 +51,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Container; import org.bukkit.block.Container;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -62,10 +63,27 @@ import java.util.function.Consumer;
public class BukkitQueueCoordinator extends BasicQueueCoordinator { public class BukkitQueueCoordinator extends BasicQueueCoordinator {
private final SideEffectSet noSideEffectSet; private static final SideEffectSet NO_SIDE_EFFECT_SET;
private final SideEffectSet lightingSideEffectSet; private static final SideEffectSet EDGE_SIDE_EFFECT_SET;
private final SideEffectSet edgeSideEffectSet; private static final SideEffectSet LIGHTING_SIDE_EFFECT_SET;
private final SideEffectSet edgeLightingSideEffectSet; private static final SideEffectSet EDGE_LIGHTING_SIDE_EFFECT_SET;
static {
NO_SIDE_EFFECT_SET = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF).with(
SideEffect.NEIGHBORS,
SideEffect.State.OFF
);
EDGE_SIDE_EFFECT_SET = SideEffectSet.none().with(SideEffect.UPDATE, SideEffect.State.ON).with(
SideEffect.NEIGHBORS,
SideEffect.State.ON
);
LIGHTING_SIDE_EFFECT_SET = SideEffectSet.none().with(SideEffect.NEIGHBORS, SideEffect.State.OFF);
EDGE_LIGHTING_SIDE_EFFECT_SET = SideEffectSet.none().with(SideEffect.UPDATE, SideEffect.State.ON).with(
SideEffect.NEIGHBORS,
SideEffect.State.ON
);
}
private org.bukkit.World bukkitWorld; private org.bukkit.World bukkitWorld;
@Inject @Inject
private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory; private ChunkCoordinatorBuilderFactory chunkCoordinatorBuilderFactory;
@ -76,19 +94,6 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
@Inject @Inject
public BukkitQueueCoordinator(@NonNull World world) { public BukkitQueueCoordinator(@NonNull World world) {
super(world); super(world);
noSideEffectSet = SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.OFF).with(
SideEffect.NEIGHBORS,
SideEffect.State.OFF
);
lightingSideEffectSet = SideEffectSet.none().with(SideEffect.NEIGHBORS, SideEffect.State.OFF);
edgeSideEffectSet = noSideEffectSet.with(SideEffect.UPDATE, SideEffect.State.ON).with(
SideEffect.NEIGHBORS,
SideEffect.State.ON
);
edgeLightingSideEffectSet = noSideEffectSet.with(SideEffect.UPDATE, SideEffect.State.ON).with(
SideEffect.NEIGHBORS,
SideEffect.State.ON
);
} }
@Override @Override
@ -111,8 +116,8 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
public boolean enqueue() { public boolean enqueue() {
final Clipboard regenClipboard; final Clipboard regenClipboard;
if (isRegen()) { if (isRegen()) {
BlockVector3 start = BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4); BlockVector3 start = BlockVector3.at(getRegenStart()[0] << 4, getMinY(), getRegenStart()[1] << 4);
BlockVector3 end = BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15); BlockVector3 end = BlockVector3.at((getRegenEnd()[0] << 4) + 15, getMaxY(), (getRegenEnd()[1] << 4) + 15);
Region region = new CuboidRegion(start, end); Region region = new CuboidRegion(start, end);
regenClipboard = new BlockArrayClipboard(region); regenClipboard = new BlockArrayClipboard(region);
regenClipboard.setOrigin(start); regenClipboard.setOrigin(start);
@ -134,7 +139,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
int sx = blockVector2.getX() << 4; int sx = blockVector2.getX() << 4;
int sz = blockVector2.getZ() << 4; int sz = blockVector2.getZ() << 4;
if (isRegenChunk) { if (isRegenChunk) {
for (int layer = 0; layer < 16; layer++) { for (int layer = getMinLayer(); layer <= getMaxLayer(); layer++) {
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
@ -170,7 +175,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
int lx = ChunkUtil.getX(j); int lx = ChunkUtil.getX(j);
int lz = ChunkUtil.getZ(j); int lz = ChunkUtil.getZ(j);
int x = sx + lx; int x = sx + lx;
int y = ChunkUtil.getY(layer, j); int y = ChunkUtil.getY(layer + localChunk.getMinSection(), j);
int z = sz + lz; int z = sz + lz;
boolean edge = Settings.QUEUE.UPDATE_EDGES && isEdge(y >> 4, lx, y & 15, lz, blockVector2, boolean edge = Settings.QUEUE.UPDATE_EDGES && isEdge(y >> 4, lx, y & 15, lz, blockVector2,
localChunk localChunk
@ -179,7 +184,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
} }
} }
} }
for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) { for (int layer = 0; layer < localChunk.getBiomes().length; layer++) {
BiomeType[] biomesLayer = localChunk.getBiomes()[layer]; BiomeType[] biomesLayer = localChunk.getBiomes()[layer];
if (biomesLayer == null) { if (biomesLayer == null) {
continue; continue;
@ -201,7 +206,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
localChunk.getTiles().forEach((blockVector3, tag) -> { localChunk.getTiles().forEach((blockVector3, tag) -> {
try { try {
BaseBlock block = getWorld().getBlock(blockVector3).toBaseBlock(tag); BaseBlock block = getWorld().getBlock(blockVector3).toBaseBlock(tag);
getWorld().setBlock(blockVector3, block, noSideEffectSet); getWorld().setBlock(blockVector3, block, getSideEffectSet(SideEffectState.NONE));
} catch (WorldEditException ignored) { } catch (WorldEditException ignored) {
StateWrapper sw = new StateWrapper(tag); StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(getWorld().getName(), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ()); sw.restoreTag(getWorld().getName(), blockVector3.getX(), blockVector3.getY(), blockVector3.getZ());
@ -258,15 +263,21 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
} }
SideEffectSet sideEffectSet; SideEffectSet sideEffectSet;
if (lighting) { if (lighting) {
sideEffectSet = edge ? edgeLightingSideEffectSet : lightingSideEffectSet; sideEffectSet = getSideEffectSet(edge ? SideEffectState.EDGE_LIGHTING : SideEffectState.LIGHTING);
} else { } else {
sideEffectSet = edge ? edgeSideEffectSet : noSideEffectSet; sideEffectSet = getSideEffectSet(edge ? SideEffectState.EDGE : SideEffectState.NONE);
} }
getWorld().setBlock(loc, block, sideEffectSet); getWorld().setBlock(loc, block, sideEffectSet);
} catch (WorldEditException ignored) { } catch (WorldEditException ignored) {
// Fallback to not so nice method // Fallback to not so nice method
BlockData blockData = BukkitAdapter.adapt(block); BlockData blockData = BukkitAdapter.adapt(block);
Block existing = getBukkitWorld().getBlockAt(x, y, z); Block existing;
// Assume a chunk object has been given only when it should have been.
if (getChunkObject() instanceof Chunk chunkObject) {
existing = chunkObject.getBlock(x & 15, y, z & 15);
} else {
existing = getBukkitWorld().getBlockAt(x, y, z);
}
final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData()); final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData());
if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) { if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) {
return; return;
@ -282,7 +293,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
CompoundTag tag = block.getNbtData(); CompoundTag tag = block.getNbtData();
StateWrapper sw = new StateWrapper(tag); StateWrapper sw = new StateWrapper(tag);
sw.restoreTag(getWorld().getName(), existing.getX(), existing.getY(), existing.getZ()); sw.restoreTag(existing);
} }
} }
} }
@ -295,47 +306,48 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
} }
private boolean isEdge(int layer, int x, int y, int z, BlockVector2 blockVector2, LocalChunk localChunk) { private boolean isEdge(int layer, int x, int y, int z, BlockVector2 blockVector2, LocalChunk localChunk) {
if (layer == 0 || layer == localChunk.getBaseblocks().length - 1) { int layerIndex = (layer - localChunk.getMinSection());
if (layer == localChunk.getMinSection() || layerIndex == localChunk.getBaseblocks().length - 1) {
return false; return false;
} }
if (x == 0) { if (x == 0) {
LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() - 1)); LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() - 1));
if (localChunkX == null || localChunkX.getBaseblocks()[layer] == null || if (localChunkX == null || localChunkX.getBaseblocks()[layerIndex] == null ||
localChunkX.getBaseblocks()[layer][ChunkUtil.getJ(15, y, z)] != null) { localChunkX.getBaseblocks()[layerIndex][ChunkUtil.getJ(15, y, z)] != null) {
return true; return true;
} }
} else if (x == 15) { } else if (x == 15) {
LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() + 1)); LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() + 1));
if (localChunkX == null || localChunkX.getBaseblocks()[layer] == null || if (localChunkX == null || localChunkX.getBaseblocks()[layerIndex] == null ||
localChunkX.getBaseblocks()[layer][ChunkUtil.getJ(0, y, z)] != null) { localChunkX.getBaseblocks()[layerIndex][ChunkUtil.getJ(0, y, z)] != null) {
return true; return true;
} }
} }
if (z == 0) { if (z == 0) {
LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() - 1)); LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() - 1));
if (localChunkZ == null || localChunkZ.getBaseblocks()[layer] == null || if (localChunkZ == null || localChunkZ.getBaseblocks()[layerIndex] == null ||
localChunkZ.getBaseblocks()[layer][ChunkUtil.getJ(x, y, 15)] != null) { localChunkZ.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, y, 15)] != null) {
return true; return true;
} }
} else if (z == 15) { } else if (z == 15) {
LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() + 1)); LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() + 1));
if (localChunkZ == null || localChunkZ.getBaseblocks()[layer] == null || if (localChunkZ == null || localChunkZ.getBaseblocks()[layerIndex] == null ||
localChunkZ.getBaseblocks()[layer][ChunkUtil.getJ(x, y, 0)] != null) { localChunkZ.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, y, 0)] != null) {
return true; return true;
} }
} }
if (y == 0) { if (y == 0) {
if (localChunk.getBaseblocks()[layer - 1] == null || if (localChunk.getBaseblocks()[layerIndex - 1] == null ||
localChunk.getBaseblocks()[layer][ChunkUtil.getJ(x, 15, z)] != null) { localChunk.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, 15, z)] != null) {
return true; return true;
} }
} else if (y == 15) { } else if (y == 15) {
if (localChunk.getBaseblocks()[layer + 1] == null || if (localChunk.getBaseblocks()[layerIndex + 1] == null ||
localChunk.getBaseblocks()[layer][ChunkUtil.getJ(x, 0, z)] != null) { localChunk.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, 0, z)] != null) {
return true; return true;
} }
} }
BaseBlock[] baseBlocks = localChunk.getBaseblocks()[layer]; BaseBlock[] baseBlocks = localChunk.getBaseblocks()[layerIndex];
if (x > 0 && baseBlocks[ChunkUtil.getJ(x - 1, y, z)] == null) { if (x > 0 && baseBlocks[ChunkUtil.getJ(x - 1, y, z)] == null) {
return true; return true;
} }
@ -374,4 +386,23 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
return false; return false;
} }
private SideEffectSet getSideEffectSet(SideEffectState state) {
if (getSideEffectSet() != null) {
return getSideEffectSet();
}
return switch (state) {
case NONE -> NO_SIDE_EFFECT_SET;
case EDGE -> EDGE_SIDE_EFFECT_SET;
case LIGHTING -> LIGHTING_SIDE_EFFECT_SET;
case EDGE_LIGHTING -> EDGE_LIGHTING_SIDE_EFFECT_SET;
};
}
private enum SideEffectState {
NONE,
EDGE,
LIGHTING,
EDGE_LIGHTING
}
} }

View File

@ -31,6 +31,7 @@ import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.AnnotationHelper;
import com.plotsquared.core.util.ChunkUtil; import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
@ -50,6 +51,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Arrays; import java.util.Arrays;
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public class GenChunk extends ScopedQueueCoordinator { public class GenChunk extends ScopedQueueCoordinator {
public final Biome[] biomes; public final Biome[] biomes;
@ -61,8 +63,14 @@ public class GenChunk extends ScopedQueueCoordinator {
public int chunkZ; public int chunkZ;
private ChunkData chunkData = null; private ChunkData chunkData = null;
public GenChunk() { /**
super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); * @param minY minimum world Y, inclusive
* @param maxY maximum world Y, inclusive
*
* @since 6.6.0
*/
public GenChunk(int minY, int maxY) {
super(null, Location.at("", 0, minY, 0), Location.at("", 15, maxY, 15));
this.biomes = Biome.values(); this.biomes = Biome.values();
} }
@ -117,7 +125,7 @@ public class GenChunk extends ScopedQueueCoordinator {
return; return;
} }
Biome biome = BukkitAdapter.adapt(biomeType); Biome biome = BukkitAdapter.adapt(biomeType);
for (int y = 0; y < 256; y++) { for (int y = getMin().getY(); y <= getMax().getY(); y++) {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
this.biomeGrid.setBiome(x, y, z, biome); this.biomeGrid.setBiome(x, y, z, biome);
@ -130,7 +138,7 @@ public class GenChunk extends ScopedQueueCoordinator {
public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) { public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) {
if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) { if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) {
for (int y = pos1.getY(); y <= pos2.getY(); y++) { for (int y = pos1.getY(); y <= pos2.getY(); y++) {
int layer = y >> 4; int layer = getLayerIndex(y);
BlockState[] data = result[layer]; BlockState[] data = result[layer];
if (data == null) { if (data == null) {
result[layer] = data = new BlockState[4096]; result[layer] = data = new BlockState[4096];
@ -164,7 +172,7 @@ public class GenChunk extends ScopedQueueCoordinator {
*/ */
public boolean setBiome(int x, int z, @NonNull Biome biome) { public boolean setBiome(int x, int z, @NonNull Biome biome) {
if (this.biomeGrid != null) { if (this.biomeGrid != null) {
for (int y = 0; y < 256; y++) { for (int y = getMin().getY(); y <= getMax().getY(); y++) {
this.setBiome(x, y, z, biome); this.setBiome(x, y, z, biome);
} }
return true; return true;
@ -197,7 +205,7 @@ public class GenChunk extends ScopedQueueCoordinator {
} }
private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) { private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) {
int i = y >> 4; int i = getLayerIndex(y);
BlockState[] v = this.result[i]; BlockState[] v = this.result[i];
if (v == null) { if (v == null) {
this.result[i] = v = new BlockState[4096]; this.result[i] = v = new BlockState[4096];
@ -219,7 +227,7 @@ public class GenChunk extends ScopedQueueCoordinator {
@Override @Override
public @Nullable BlockState getBlock(int x, int y, int z) { public @Nullable BlockState getBlock(int x, int y, int z) {
int i = y >> 4; int i = getLayerIndex(y);
if (result == null) { if (result == null) {
return BukkitBlockUtil.get(chunkData.getType(x, y, z)); return BukkitBlockUtil.get(chunkData.getType(x, y, z));
} }
@ -246,16 +254,16 @@ public class GenChunk extends ScopedQueueCoordinator {
@Override @Override
public @NonNull Location getMax() { public @NonNull Location getMax() {
return Location.at(getWorld().getName(), 15 + (getX() << 4), 255, 15 + (getZ() << 4)); return Location.at(getWorld().getName(), 15 + (getX() << 4), super.getMax().getY(), 15 + (getZ() << 4));
} }
@Override @Override
public @NonNull Location getMin() { public @NonNull Location getMin() {
return Location.at(getWorld().getName(), getX() << 4, 0, getZ() << 4); return Location.at(getWorld().getName(), getX() << 4, super.getMin().getY(), getZ() << 4);
} }
public @NonNull GenChunk clone() { public @NonNull GenChunk clone() {
GenChunk toReturn = new GenChunk(); GenChunk toReturn = new GenChunk(getMin().getY(), getMax().getY());
if (this.result != null) { if (this.result != null) {
for (int i = 0; i < this.result.length; i++) { for (int i = 0; i < this.result.length; i++) {
BlockState[] matrix = this.result[i]; BlockState[] matrix = this.result[i];
@ -269,4 +277,8 @@ public class GenChunk extends ScopedQueueCoordinator {
return toReturn; return toReturn;
} }
private int getLayerIndex(int y) {
return (y - getMin().getY()) >> 4;
}
} }

View File

@ -0,0 +1,128 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2014 - 2022 IntellectualSites
*
* 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.plotsquared.bukkit.queue;
import com.plotsquared.bukkit.schematic.StateWrapper;
import com.plotsquared.core.queue.DelegateQueueCoordinator;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.generator.LimitedRegion;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Wraps a {@link LimitedRegion} inside a {@link com.plotsquared.core.queue.QueueCoordinator} so it can be written to.
*
* @since TODO
*/
public class LimitedRegionWrapperQueue extends DelegateQueueCoordinator {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + LimitedRegionWrapperQueue.class.getSimpleName());
private final LimitedRegion limitedRegion;
/**
* @since TODO
*/
public LimitedRegionWrapperQueue(LimitedRegion limitedRegion) {
super(null);
this.limitedRegion = limitedRegion;
}
@Override
public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) {
return setBlock(x, y, z, pattern.applyBlock(BlockVector3.at(x, y, z)));
}
@Override
public boolean setBlock(final int x, final int y, final int z, @NonNull final BaseBlock id) {
boolean result = setBlock(x, y, z, id.toImmutableState());
if (result && id.hasNbtData()) {
CompoundTag tag = id.getNbtData();
StateWrapper sw = new StateWrapper(tag);
try {
sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock());
} catch (IllegalArgumentException e) {
LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e);
return false;
}
}
return result;
}
@Override
public boolean setBlock(final int x, final int y, final int z, @NonNull final BlockState id) {
try {
limitedRegion.setType(x, y, z, BukkitAdapter.adapt(id.getBlockType()));
limitedRegion.setBlockData(x, y, z, BukkitAdapter.adapt(id));
} catch (IllegalArgumentException e) {
LOGGER.error("Error attempting to populate block into the world at location {},{},{}", x, y, z, e);
return false;
}
return true;
}
@Override
public boolean setEntity(@NonNull final Entity entity) {
EntityType type = BukkitAdapter.adapt(entity.getState().getType());
double x = entity.getLocation().getX();
double y = entity.getLocation().getY();
double z = entity.getLocation().getZ();
Location location = new Location(limitedRegion.getWorld(), x, y, z);
try {
limitedRegion.spawnEntity(location, type);
} catch (IllegalArgumentException e) {
LOGGER.error("Error attempting to populate entity into the world at location {},{},{}", (int) x, (int) y, (int) z, e);
return false;
}
return true;
}
@Override
public boolean setTile(final int x, final int y, final int z, @NonNull final CompoundTag tag) {
StateWrapper sw = new StateWrapper(tag);
try {
return sw.restoreTag(limitedRegion.getBlockState(x, y, z).getBlock());
} catch (IllegalArgumentException e) {
LOGGER.error("Error attempting to populate tile entity into the world at location {},{},{}", x, y, z, e);
return false;
}
}
@Override
public boolean isSettingTiles() {
return true;
}
}

View File

@ -35,15 +35,18 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Container; import org.bukkit.block.Container;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.block.Skull;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -56,6 +59,11 @@ public class StateWrapper {
public org.bukkit.block.BlockState state = null; public org.bukkit.block.BlockState state = null;
public CompoundTag tag = null; public CompoundTag tag = null;
/**
* @deprecated in favour of using WE methods for obtaining NBT, specifically by obtaining a
* {@link com.sk89q.worldedit.world.block.BaseBlock} and then using {@link com.sk89q.worldedit.world.block.BaseBlock#getNbtData()}
*/
@Deprecated(forRemoval = true, since = "TODO")
public StateWrapper(org.bukkit.block.BlockState state) { public StateWrapper(org.bukkit.block.BlockState state) {
this.state = state; this.state = state;
} }
@ -166,14 +174,32 @@ public class StateWrapper {
return str; return str;
} }
@SuppressWarnings("deprecation") // #setLine is needed for Spigot compatibility /**
* Restore the TileEntity data to the given world at the given coordinates.
*
* @param worldName World name
* @param x x position
* @param y y position
* @param z z position
* @return true if successful
*/
public boolean restoreTag(String worldName, int x, int y, int z) { public boolean restoreTag(String worldName, int x, int y, int z) {
if (this.tag == null) { World world = BukkitUtil.getWorld(worldName);
if (world == null) {
return false; return false;
} }
World world = BukkitUtil.getWorld(worldName); return restoreTag(world.getBlockAt(x, y, z));
Block block = world.getBlockAt(x, y, z); }
if (block == null) {
/**
* Restore the TileEntity data to the given block
*
* @param block Block to restore to
* @return true if successful
*/
@SuppressWarnings("deprecation") // #setLine is needed for Spigot compatibility
public boolean restoreTag(@NonNull Block block) {
if (this.tag == null) {
return false; return false;
} }
org.bukkit.block.BlockState state = block.getState(); org.bukkit.block.BlockState state = block.getState();
@ -211,10 +237,37 @@ public class StateWrapper {
} }
return false; return false;
} }
case "skull" -> {
if (state instanceof Skull skull) {
CompoundTag skullOwner = ((CompoundTag) this.tag.getValue().get("SkullOwner"));
if (skullOwner == null) {
return true;
}
String player = skullOwner.getString("Name");
if (player == null || player.isEmpty()) {
return false;
}
try {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(player));
skull.update(true);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
return false;
}
} }
return false; return false;
} }
/**
* Get a CompoundTag of the contents of a block's inventory (chest, furnace, etc.).
*
* @deprecated in favour of using WorldEdit methods for obtaining NBT, specifically by obtaining a
* {@link com.sk89q.worldedit.world.block.BaseBlock} and then using {@link com.sk89q.worldedit.world.block.BaseBlock#getNbtData()}
*/
@Deprecated(forRemoval = true, since = "TODO")
public CompoundTag getTag() { public CompoundTag getTag() {
if (this.tag != null) { if (this.tag != null) {
return this.tag; return this.tag;

View File

@ -40,7 +40,6 @@ import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.RegionUtil;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.entity.EntityCategories;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
@ -261,7 +260,7 @@ public class BukkitRegionManager extends RegionManager {
if (checkX2 && checkZ2) { if (checkX2 && checkZ2) {
map.saveRegion(world, xxt2, xxt, zzt2, zzt); // map.saveRegion(world, xxt2, xxt, zzt2, zzt); //
} }
CuboidRegion currentPlotClear = RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); CuboidRegion currentPlotClear = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3());
map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), currentPlotClear); map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), currentPlotClear);
AugmentedUtils.bypass( AugmentedUtils.bypass(
ignoreAugment, ignoreAugment,
@ -276,20 +275,16 @@ public class BukkitRegionManager extends RegionManager {
PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1);
BaseBlock[] ids = map.allBlocks.get(plotLoc); BaseBlock[] ids = map.allBlocks.get(plotLoc);
if (ids != null) { if (ids != null) {
for (int y = 0; y < Math.min(128, ids.length); y++) { int minY = value.getMin().getY();
BaseBlock id = ids[y]; for (int yIndex = 0; yIndex < ids.length; yIndex++) {
int y = yIndex + minY;
BaseBlock id = ids[yIndex];
if (id != null) { if (id != null) {
value.setBlock(x1, y, z1, id); value.setBlock(x1, y, z1, id);
} else { } else {
value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState()); value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState());
} }
} }
for (int y = Math.min(128, ids.length); y < ids.length; y++) {
BaseBlock id = ids[y];
if (id != null) {
value.setBlock(x1, y, z1, id);
}
}
} }
} }
} }
@ -297,7 +292,7 @@ public class BukkitRegionManager extends RegionManager {
}, world.getName(), chunk) }, world.getName(), chunk)
); );
//map.restoreBlocks(worldObj, 0, 0); //map.restoreBlocks(worldObj, 0, 0);
map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0); map.restoreEntities(Bukkit.getWorld(world.getName()));
}); });
regenQueue.setCompleteTask(whenDone); regenQueue.setCompleteTask(whenDone);
queue.setCompleteTask(regenQueue::enqueue); queue.setCompleteTask(regenQueue::enqueue);

View File

@ -76,7 +76,7 @@ public class BukkitSetupUtils extends SetupUtils {
@Override @Override
public void updateGenerators(final boolean force) { public void updateGenerators(final boolean force) {
if (!SetupUtils.generators.isEmpty() && !force) { if (loaded && !SetupUtils.generators.isEmpty() && !force) {
return; return;
} }
String testWorld = "CheckingPlotSquaredGenerator"; String testWorld = "CheckingPlotSquaredGenerator";
@ -100,6 +100,7 @@ public class BukkitSetupUtils extends SetupUtils {
e.printStackTrace(); e.printStackTrace();
} }
} }
loaded = true;
} }
@Override @Override

View File

@ -44,7 +44,6 @@ import com.plotsquared.core.util.task.TaskManager;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
@ -61,7 +60,6 @@ import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
@ -246,7 +244,9 @@ public class BukkitUtil extends WorldUtil {
final World bukkitWorld = Objects.requireNonNull(getWorld(world)); final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block // Skip top and bottom block
int air = 1; int air = 1;
for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) { int maxY = com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(bukkitWorld);
int minY = com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(bukkitWorld);
for (int y = maxY - 1; y >= minY; y--) {
Block block = bukkitWorld.getBlockAt(x, y, z); Block block = bukkitWorld.getBlockAt(x, y, z);
Material type = block.getType(); Material type = block.getType();
if (type.isSolid()) { if (type.isSolid()) {
@ -273,7 +273,9 @@ public class BukkitUtil extends WorldUtil {
final World bukkitWorld = Objects.requireNonNull(getWorld(world)); final World bukkitWorld = Objects.requireNonNull(getWorld(world));
// Skip top and bottom block // Skip top and bottom block
int air = 1; int air = 1;
for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) { int maxY = com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(bukkitWorld);
int minY = com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(bukkitWorld);
for (int y = maxY - 1; y >= minY; y--) {
Block block = bukkitWorld.getBlockAt(x, y, z); Block block = bukkitWorld.getBlockAt(x, y, z);
Material type = block.getType(); Material type = block.getType();
if (type.isSolid()) { if (type.isSolid()) {
@ -345,13 +347,15 @@ public class BukkitUtil extends WorldUtil {
final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ());
final Material type = block.getType(); final Material type = block.getType();
if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) { if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) {
BlockFace facing = BlockFace.EAST; BlockFace facing = BlockFace.NORTH;
if (world.getBlockAt(location.getX(), location.getY(), location.getZ() + 1).getType().isSolid()) { if (!world.getBlockAt(location.getX(), location.getY(), location.getZ() + 1).getType().isSolid()) {
facing = BlockFace.NORTH; if (world.getBlockAt(location.getX() - 1, location.getY(), location.getZ()).getType().isSolid()) {
} else if (world.getBlockAt(location.getX() + 1, location.getY(), location.getZ()).getType().isSolid()) { facing = BlockFace.EAST;
facing = BlockFace.WEST; } else if (world.getBlockAt(location.getX() + 1, location.getY(), location.getZ()).getType().isSolid()) {
} else if (world.getBlockAt(location.getX(), location.getY(), location.getZ() - 1).getType().isSolid()) { facing = BlockFace.WEST;
facing = BlockFace.SOUTH; } else if (world.getBlockAt(location.getX(), location.getY(), location.getZ() - 1).getType().isSolid()) {
facing = BlockFace.SOUTH;
}
} }
if (PlotSquared.platform().serverVersion()[1] == 13) { if (PlotSquared.platform().serverVersion()[1] == 13) {
block.setType(Material.valueOf(area.legacySignMaterial()), false); block.setType(Material.valueOf(area.legacySignMaterial()), false);
@ -371,7 +375,7 @@ public class BukkitUtil extends WorldUtil {
sign.setLine(i, LEGACY_COMPONENT_SERIALIZER sign.setLine(i, LEGACY_COMPONENT_SERIALIZER
.serialize(MINI_MESSAGE.parse(lines[i].getComponent(LocaleHolder.console()), replacements))); .serialize(MINI_MESSAGE.parse(lines[i].getComponent(LocaleHolder.console()), replacements)));
} }
sign.update(true); sign.update(true, false);
} }
}); });
} }
@ -382,27 +386,6 @@ public class BukkitUtil extends WorldUtil {
return new StringComparison<BlockState>().new ComparisonResult(1, state); return new StringComparison<BlockState>().new ComparisonResult(1, state);
} }
@Override
public void setBiomes(
final @NonNull String worldName,
final @NonNull CuboidRegion region,
final @NonNull BiomeType biomeType
) {
final World world = getWorld(worldName);
if (world == null) {
LOGGER.warn("An error occurred while setting the biome because the world was null", new RuntimeException());
return;
}
final Biome biome = BukkitAdapter.adapt(biomeType);
for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) {
for (int z = region.getMinimumPoint().getZ(); z <= region.getMaximumPoint().getZ(); z++) {
if (world.getBiome(x, z) != biome) {
world.setBiome(x, z, biome);
}
}
}
}
@Override @Override
public com.sk89q.worldedit.world.@NonNull World getWeWorld(final @NonNull String world) { public com.sk89q.worldedit.world.@NonNull World getWeWorld(final @NonNull String world) {
return new BukkitWorld(Bukkit.getWorld(world)); return new BukkitWorld(Bukkit.getWorld(world));

View File

@ -36,6 +36,18 @@ import java.util.Objects;
public class BukkitWorld implements World<org.bukkit.World> { public class BukkitWorld implements World<org.bukkit.World> {
private static final Map<String, BukkitWorld> worldMap = Maps.newHashMap(); private static final Map<String, BukkitWorld> worldMap = Maps.newHashMap();
private static final boolean HAS_MIN_Y;
static {
boolean temp;
try {
org.bukkit.World.class.getMethod("getMinHeight");
temp = true;
} catch (NoSuchMethodException e) {
temp = false;
}
HAS_MIN_Y = temp;
}
private final org.bukkit.World world; private final org.bukkit.World world;
@ -73,6 +85,24 @@ public class BukkitWorld implements World<org.bukkit.World> {
return bukkitWorld; return bukkitWorld;
} }
/**
* Get the min world height from a Bukkit {@link org.bukkit.World}. Inclusive
*
* @since 6.6.0
*/
public static int getMinWorldHeight(org.bukkit.World world) {
return HAS_MIN_Y ? world.getMinHeight() : 0;
}
/**
* Get the max world height from a Bukkit {@link org.bukkit.World}. Exclusive
*
* @since 6.6.0
*/
public static int getMaxWorldHeight(org.bukkit.World world) {
return HAS_MIN_Y ? world.getMaxHeight() : 256;
}
@Override @Override
public org.bukkit.World getPlatformWorld() { public org.bukkit.World getPlatformWorld() {
return this.world; return this.world;
@ -83,6 +113,16 @@ public class BukkitWorld implements World<org.bukkit.World> {
return this.world.getName(); return this.world.getName();
} }
@Override
public int getMinHeight() {
return getMinWorldHeight(world);
}
@Override
public int getMaxHeight() {
return getMaxWorldHeight(world) - 1;
}
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
if (this == o) { if (this == o) {
@ -103,7 +143,7 @@ public class BukkitWorld implements World<org.bukkit.World> {
/** /**
* @deprecated This method is not meant to be invoked or overridden, with no replacement. * @deprecated This method is not meant to be invoked or overridden, with no replacement.
*/ */
@Deprecated(forRemoval = true, since = "TODO") @Deprecated(forRemoval = true, since = "6.6.0")
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof BukkitWorld; return other instanceof BukkitWorld;
} }

View File

@ -70,7 +70,7 @@ public class ContentMap {
} }
for (int x = x1; x <= x2; x++) { for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) { for (int z = z1; z <= z2; z++) {
saveBlocks(world, 256, x, z, 0, 0); saveBlocks(world, x, z);
} }
} }
} }
@ -92,14 +92,7 @@ public class ContentMap {
} }
} }
void saveEntitiesIn(Chunk chunk, CuboidRegion region) { void saveEntitiesIn(Chunk chunk, CuboidRegion region, boolean delete) {
saveEntitiesIn(chunk, region, 0, 0, false);
}
void saveEntitiesIn(
Chunk chunk, CuboidRegion region, int offsetX, int offsetZ,
boolean delete
) {
for (Entity entity : chunk.getEntities()) { for (Entity entity : chunk.getEntities()) {
Location location = BukkitUtil.adapt(entity.getLocation()); Location location = BukkitUtil.adapt(entity.getLocation());
int x = location.getX(); int x = location.getX();
@ -111,8 +104,6 @@ public class ContentMap {
continue; continue;
} }
EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2); EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2);
wrap.x += offsetX;
wrap.z += offsetZ;
wrap.saveEntity(); wrap.saveEntity();
this.entities.add(wrap); this.entities.add(wrap);
if (delete) { if (delete) {
@ -123,10 +114,10 @@ public class ContentMap {
} }
} }
void restoreEntities(World world, int xOffset, int zOffset) { void restoreEntities(World world) {
for (EntityWrapper entity : this.entities) { for (EntityWrapper entity : this.entities) {
try { try {
entity.spawn(world, xOffset, zOffset); entity.spawn(world, 0, 0);
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("Failed to restore entity", e); LOGGER.error("Failed to restore entity", e);
} }
@ -134,15 +125,13 @@ public class ContentMap {
this.entities.clear(); this.entities.clear();
} }
//todo optimize maxY private void saveBlocks(BukkitWorld world, int x, int z) {
void saveBlocks(BukkitWorld world, int maxY, int x, int z, int offsetX, int offsetZ) { BaseBlock[] ids = new BaseBlock[world.getMaxY() - world.getMinY() + 1];
maxY = Math.min(255, maxY); for (short yIndex = 0; yIndex <= world.getMaxY() - world.getMinY(); yIndex++) {
BaseBlock[] ids = new BaseBlock[maxY + 1]; BaseBlock block = world.getFullBlock(BlockVector3.at(x, yIndex + world.getMinY(), z));
for (short y = 0; y <= maxY; y++) { ids[yIndex] = block;
BaseBlock block = world.getFullBlock(BlockVector3.at(x, y, z));
ids[y] = block;
} }
PlotLoc loc = new PlotLoc(x + offsetX, z + offsetZ); PlotLoc loc = new PlotLoc(x, z);
this.allBlocks.put(loc, ids); this.allBlocks.put(loc, ids);
} }

View File

@ -110,6 +110,11 @@ public class FaweRegionManager extends BukkitRegionManager {
delegate.setBiome(region, extendBiome, biome, world, whenDone); delegate.setBiome(region, extendBiome, biome, world, whenDone);
} }
@Override
public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, PlotArea area, Runnable whenDone) {
delegate.setBiome(region, extendBiome, biome, area.getWorldName(), whenDone);
}
@Override @Override
public boolean copyRegion( public boolean copyRegion(
final @NonNull Location pos1, final @NonNull Location pos1,

View File

@ -67,7 +67,7 @@ public class FaweSchematicHandler extends SchematicHandler {
final PlotPlayer<?> actor, final PlotPlayer<?> actor,
final RunnableVal<Boolean> whenDone final RunnableVal<Boolean> whenDone
) { ) {
delegate.paste(schematic, plot, xOffset, yOffset, zOffset, autoHeight, whenDone); delegate.paste(schematic, plot, xOffset, yOffset, zOffset, autoHeight, actor, whenDone);
} }
@Override @Override

View File

@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at contact@alexander-soderberg.com. All reported by contacting the project team at contact@intellectualsites.com. All
complaints will be reviewed and investigated and will result in a response that complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident. obligated to maintain confidentiality with regard to the reporter of an incident.

View File

@ -2,18 +2,18 @@ import java.time.format.DateTimeFormatter
dependencies { dependencies {
// Expected everywhere. // Expected everywhere.
compileOnlyApi(libs.checkerqual) compileOnlyApi("org.checkerframework:checker-qual")
// Minecraft expectations // Minecraft expectations
compileOnlyApi(libs.gson) compileOnlyApi("com.google.code.gson:gson")
compileOnly(libs.guava) compileOnly("com.google.guava:guava")
// Platform expectations // Platform expectations
compileOnlyApi(libs.snakeyaml) compileOnlyApi("org.yaml:snakeyaml")
// Adventure // Adventure
api(libs.adventure) api("net.kyori:adventure-api")
api(libs.minimessage) api("net.kyori:adventure-text-minimessage")
// Guice // Guice
api(libs.guice) { api(libs.guice) {
@ -22,7 +22,7 @@ dependencies {
api(libs.guiceassistedinject) { api(libs.guiceassistedinject) {
exclude("com.google.inject", "guice") exclude("com.google.inject", "guice")
} }
api(libs.findbugs) api(libs.spotbugs)
// Plugins // Plugins
compileOnly(libs.worldeditCore) { compileOnly(libs.worldeditCore) {
@ -31,18 +31,18 @@ dependencies {
exclude(group = "dummypermscompat") exclude(group = "dummypermscompat")
} }
testImplementation(libs.worldeditCore) testImplementation(libs.worldeditCore)
compileOnly(libs.fastasyncworldeditCore) { isTransitive = false } compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core") { isTransitive = false }
testImplementation(libs.fastasyncworldeditCore) { isTransitive = false } testImplementation("com.fastasyncworldedit:FastAsyncWorldEdit-Core") { isTransitive = false }
// Logging // Logging
compileOnlyApi(libs.log4j) compileOnlyApi("org.apache.logging.log4j:log4j-api")
// Other libraries // Other libraries
api(libs.prtree) api(libs.prtree)
api(libs.aopalliance) api(libs.aopalliance)
api(libs.cloudServices) api(libs.cloudServices)
api(libs.arkitektonika) api(libs.arkitektonika)
api(libs.paster) api("com.intellectualsites.paster:Paster")
} }
tasks.processResources { tasks.processResources {

View File

@ -98,6 +98,22 @@ public interface PlotPlatform<P> extends LocaleHolder {
*/ */
int[] serverVersion(); int[] serverVersion();
/**
* Gets the default minimum world height for the version of Minecraft that the server is running.
*
* @return minimum world height
* @since 6.6.0
*/
int versionMinHeight();
/**
* Gets the default maximum world height for the version of Minecraft that the server is running.
*
* @return maximum world height (inclusive)
* @since 6.6.0
*/
int versionMaxHeight();
/** /**
* Gets the server implementation name and version * Gets the server implementation name and version
* *

View File

@ -889,8 +889,8 @@ public class PlotSquared {
e.printStackTrace(); e.printStackTrace();
} }
LOGGER.info("| generator: {}>{}", baseGenerator, areaGen); LOGGER.info("| generator: {}>{}", baseGenerator, areaGen);
LOGGER.info("| plot world: {}", pa); LOGGER.info("| plot world: {}", pa.getClass().getCanonicalName());
LOGGER.info("| manager: {}", pa); LOGGER.info("| manager: {}", pa.getPlotManager().getClass().getCanonicalName());
LOGGER.info("Note: Area created for cluster '{}' (invalid or old configuration?)", name); LOGGER.info("Note: Area created for cluster '{}' (invalid or old configuration?)", name);
areaGen.getPlotGenerator().initialize(pa); areaGen.getPlotGenerator().initialize(pa);
areaGen.augment(pa); areaGen.augment(pa);
@ -906,6 +906,13 @@ public class PlotSquared {
throw new IllegalArgumentException("Invalid Generator: " + gen_string); throw new IllegalArgumentException("Invalid Generator: " + gen_string);
} }
PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null); PlotArea pa = areaGen.getPlotGenerator().getNewPlotArea(world, null, null, null);
LOGGER.info("- generator: {}>{}", baseGenerator, areaGen);
LOGGER.info("- plot world: {}", pa.getClass().getCanonicalName());
LOGGER.info("- plot area manager: {}", pa.getPlotManager().getClass().getCanonicalName());
if (!this.worldConfiguration.contains(path)) {
this.worldConfiguration.createSection(path);
worldSection = this.worldConfiguration.getConfigurationSection(path);
}
pa.saveConfiguration(worldSection); pa.saveConfiguration(worldSection);
pa.loadDefaultConfiguration(worldSection); pa.loadDefaultConfiguration(worldSection);
try { try {
@ -913,9 +920,6 @@ public class PlotSquared {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
LOGGER.info("- generator: {}>{}", baseGenerator, areaGen);
LOGGER.info("- plot world: {}", pa);
LOGGER.info("- plot area manager: {}", pa.getPlotManager());
areaGen.getPlotGenerator().initialize(pa); areaGen.getPlotGenerator().initialize(pa);
areaGen.augment(pa); areaGen.augment(pa);
addPlotArea(pa); addPlotArea(pa);
@ -1020,8 +1024,8 @@ public class PlotSquared {
// save configuration // save configuration
final List<String> validArguments = Arrays final List<String> validArguments = Arrays
.asList("s=", "size=", "g=", "gap=", "h=", "height=", "f=", "floor=", "m=", "main=", .asList("s=", "size=", "g=", "gap=", "h=", "height=", "minh=", "minheight=", "maxh=", "maxheight=",
"w=", "wall=", "b=", "border=" "f=", "floor=", "m=", "main=", "w=", "wall=", "b=", "border="
); );
// Calculate the number of expected arguments // Calculate the number of expected arguments
@ -1100,6 +1104,14 @@ public class PlotSquared {
ConfigurationUtil.INTEGER.parseString(value).shortValue() ConfigurationUtil.INTEGER.parseString(value).shortValue()
); );
} }
case "minh", "minheight" -> this.worldConfiguration.set(
base + "world.min_gen_height",
ConfigurationUtil.INTEGER.parseString(value).shortValue()
);
case "maxh", "maxheight" -> this.worldConfiguration.set(
base + "world.max_gen_height",
ConfigurationUtil.INTEGER.parseString(value).shortValue()
);
case "f", "floor" -> this.worldConfiguration.set( case "f", "floor" -> this.worldConfiguration.set(
base + "plot.floor", base + "plot.floor",
ConfigurationUtil.BLOCK_BUCKET.parseString(value).toString() ConfigurationUtil.BLOCK_BUCKET.parseString(value).toString()

View File

@ -75,6 +75,7 @@ import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.Template;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -191,11 +192,12 @@ public class Area extends SubCommand {
final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint(); final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint();
final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint(); final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint();
// Create a new selection that spans the entire vertical range of the world // Create a new selection that spans the entire vertical range of the world
World world = playerSelectedRegion.getWorld();
final CuboidRegion selectedRegion = final CuboidRegion selectedRegion =
new CuboidRegion( new CuboidRegion(
playerSelectedRegion.getWorld(), playerSelectedRegion.getWorld(),
BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()), BlockVector3.at(playerSelectionMin.getX(), world.getMinY(), playerSelectionMin.getZ()),
BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ()) BlockVector3.at(playerSelectionMax.getX(), world.getMaxY(), playerSelectionMax.getZ())
); );
// There's only one plot in the area... // There's only one plot in the area...
final PlotId plotId = PlotId.of(1, 1); final PlotId plotId = PlotId.of(1, 1);
@ -278,9 +280,9 @@ public class Area extends SubCommand {
if (offsetZ != 0) { if (offsetZ != 0) {
this.worldConfiguration.set(path + ".road.offset.z", offsetZ); this.worldConfiguration.set(path + ".road.offset.z", offsetZ);
} }
final String world = this.setupUtils.setupWorld(singleBuilder); final String worldName = this.setupUtils.setupWorld(singleBuilder);
if (this.worldUtil.isWorld(world)) { if (this.worldUtil.isWorld(worldName)) {
PlotSquared.get().loadWorld(world, null); PlotSquared.get().loadWorld(worldName, null);
player.sendMessage(TranslatableCaption.of("single.single_area_created")); player.sendMessage(TranslatableCaption.of("single.single_area_created"));
} else { } else {
player.sendMessage( player.sendMessage(
@ -369,7 +371,8 @@ public class Area extends SubCommand {
int lower = (area.ROAD_WIDTH & 1) == 0 ? area.ROAD_WIDTH / 2 - 1 : area.ROAD_WIDTH / 2; int lower = (area.ROAD_WIDTH & 1) == 0 ? area.ROAD_WIDTH / 2 - 1 : area.ROAD_WIDTH / 2;
final int offsetX = bx - (area.ROAD_WIDTH == 0 ? 0 : lower); final int offsetX = bx - (area.ROAD_WIDTH == 0 ? 0 : lower);
final int offsetZ = bz - (area.ROAD_WIDTH == 0 ? 0 : lower); final int offsetZ = bz - (area.ROAD_WIDTH == 0 ? 0 : lower);
final CuboidRegion region = RegionUtil.createRegion(bx, tx, bz, tz); // Height doesn't matter for this region
final CuboidRegion region = RegionUtil.createRegion(bx, tx, 0, 0, bz, tz);
final Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(area.getWorldName(), region); final Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(area.getWorldName(), region);
if (!areas.isEmpty()) { if (!areas.isEmpty()) {
player.sendMessage( player.sendMessage(

View File

@ -48,7 +48,7 @@ public class Confirm extends SubCommand {
player.sendMessage(TranslatableCaption.of("confirm.expired_confirm")); player.sendMessage(TranslatableCaption.of("confirm.expired_confirm"));
return false; return false;
} }
TaskManager.runTaskAsync(command.command); TaskManager.runTask(command.command);
return true; return true;
} }

View File

@ -49,6 +49,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -207,7 +208,7 @@ public class DebugExec extends SubCommand {
} }
boolean result; boolean result;
if (HybridUtils.regions != null) { if (HybridUtils.regions != null) {
result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new HashSet<>()); result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new LinkedHashSet<>());
} else { } else {
result = this.hybridUtils.scheduleRoadUpdate(area, 0); result = this.hybridUtils.scheduleRoadUpdate(area, 0);
} }

View File

@ -161,6 +161,7 @@ public class Deny extends SubCommand {
} }
private void handleKick(PlotPlayer<?> player, Plot plot) { private void handleKick(PlotPlayer<?> player, Plot plot) {
plot = plot.getBasePlot(false);
if (player == null) { if (player == null) {
return; return;
} }

View File

@ -32,6 +32,7 @@ import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.configuration.caption.CaptionHolder; import com.plotsquared.core.configuration.caption.CaptionHolder;
import com.plotsquared.core.configuration.caption.Templates; import com.plotsquared.core.configuration.caption.Templates;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.permissions.Permission; import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
@ -39,6 +40,7 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.expiration.ExpireManager; import com.plotsquared.core.plot.expiration.ExpireManager;
import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.DoneFlag;
import com.plotsquared.core.plot.flag.implementations.PriceFlag; import com.plotsquared.core.plot.flag.implementations.PriceFlag;
import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
@ -418,7 +420,7 @@ public class ListCmd extends SubCommand {
Caption color; Caption color;
if (plot.getOwner() == null) { if (plot.getOwner() == null) {
color = TranslatableCaption.of("info.plot_list_no_owner"); color = TranslatableCaption.of("info.plot_list_no_owner");
} else if (plot.isOwner(player.getUUID())) { } else if (plot.isOwner(player.getUUID()) || plot.getOwner().equals(DBFunc.EVERYONE)) {
color = TranslatableCaption.of("info.plot_list_owned_by"); color = TranslatableCaption.of("info.plot_list_owned_by");
} else if (plot.isAdded(player.getUUID())) { } else if (plot.isAdded(player.getUUID())) {
color = TranslatableCaption.of("info.plot_list_added_to"); color = TranslatableCaption.of("info.plot_list_added_to");
@ -456,37 +458,60 @@ public class ListCmd extends SubCommand {
String prefix = ""; String prefix = "";
String online = TranslatableCaption.of("info.plot_list_player_online").getComponent(player); String online = TranslatableCaption.of("info.plot_list_player_online").getComponent(player);
String offline = TranslatableCaption.of("info.plot_list_player_offline").getComponent(player); String offline = TranslatableCaption.of("info.plot_list_player_offline").getComponent(player);
String unknown = TranslatableCaption.of("info.plot_list_player_unknown").getComponent(player);
String server = TranslatableCaption.of("info.plot_list_player_server").getComponent(player);
String everyone = TranslatableCaption.of("info.plot_list_player_everyone").getComponent(player);
TextComponent.Builder builder = Component.text(); TextComponent.Builder builder = Component.text();
try { if (plot.getFlag(ServerPlotFlag.class)) {
final List<UUIDMapping> names = PlotSquared.get().getImpromptuUUIDPipeline().getNames(plot.getOwners()) Template serverTemplate = Template.of(
.get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS); "info.server",
for (final UUIDMapping uuidMapping : names) { TranslatableCaption.of("info.server").getComponent(player)
PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.getUuid());
Template prefixTemplate = Template.of("prefix", prefix);
Template playerTemplate = Template.of("player", uuidMapping.getUsername());
if (pp != null) {
builder.append(MINI_MESSAGE.parse(online, prefixTemplate, playerTemplate));
} else {
builder.append(MINI_MESSAGE.parse(offline, prefixTemplate, playerTemplate));
}
prefix = ", ";
}
} catch (InterruptedException | ExecutionException e) {
final StringBuilder playerBuilder = new StringBuilder();
final Iterator<UUID> uuidIterator = plot.getOwners().iterator();
while (uuidIterator.hasNext()) {
final UUID uuid = uuidIterator.next();
playerBuilder.append(uuid);
if (uuidIterator.hasNext()) {
playerBuilder.append(", ");
}
}
player.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
Templates.of("value", playerBuilder.toString())
); );
} catch (TimeoutException e) { builder.append(MINI_MESSAGE.parse(server, serverTemplate));
player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); } else {
try {
final List<UUIDMapping> names = PlotSquared.get().getImpromptuUUIDPipeline().getNames(plot.getOwners())
.get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS);
for (final UUIDMapping uuidMapping : names) {
PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.getUuid());
Template prefixTemplate = Template.of("prefix", prefix);
Template playerTemplate = Template.of("player", uuidMapping.getUsername());
if (pp != null) {
builder.append(MINI_MESSAGE.parse(online, prefixTemplate, playerTemplate));
} else if (uuidMapping.getUsername().equalsIgnoreCase("unknown")) {
Template unknownTemplate = Template.of(
"info.unknown",
TranslatableCaption.of("info.unknown").getComponent(player)
);
builder.append(MINI_MESSAGE.parse(unknown, unknownTemplate));
} else if (uuidMapping.getUuid().equals(DBFunc.EVERYONE)) {
Template everyoneTemplate = Template.of(
"info.everyone",
TranslatableCaption.of("info.everyone").getComponent(player)
);
builder.append(MINI_MESSAGE.parse(everyone, everyoneTemplate));
} else {
builder.append(MINI_MESSAGE.parse(offline, prefixTemplate, playerTemplate));
}
prefix = ", ";
}
} catch (InterruptedException | ExecutionException e) {
final StringBuilder playerBuilder = new StringBuilder();
final Iterator<UUID> uuidIterator = plot.getOwners().iterator();
while (uuidIterator.hasNext()) {
final UUID uuid = uuidIterator.next();
playerBuilder.append(uuid);
if (uuidIterator.hasNext()) {
playerBuilder.append(", ");
}
}
player.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
Templates.of("value", playerBuilder.toString())
);
} catch (TimeoutException e) {
player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
}
} }
Template players = Template.of("players", builder.asComponent()); Template players = Template.of("players", builder.asComponent());
caption.set(TranslatableCaption.of("info.plot_list_item")); caption.set(TranslatableCaption.of("info.plot_list_item"));

View File

@ -40,6 +40,7 @@ import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.TimeUtil;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
import net.kyori.adventure.text.minimessage.Template; import net.kyori.adventure.text.minimessage.Template;
@ -205,7 +206,7 @@ public class Load extends SubCommand {
if (split.length < 5) { if (split.length < 5) {
continue; continue;
} }
String time = secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0])); String time = TimeUtil.secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0]));
String world = split[1]; String world = split[1];
PlotId id = PlotId.fromString(split[2] + ';' + split[3]); PlotId id = PlotId.fromString(split[2] + ';' + split[3]);
String size = split[4]; String size = split[4];
@ -223,6 +224,10 @@ public class Load extends SubCommand {
} }
} }
/**
* @deprecated Use {@link TimeUtil#secToTime(long)}
*/
@Deprecated(forRemoval = true, since = "6.6.2")
public String secToTime(long time) { public String secToTime(long time) {
StringBuilder toreturn = new StringBuilder(); StringBuilder toreturn = new StringBuilder();
if (time >= 33868800) { if (time >= 33868800) {

View File

@ -104,8 +104,8 @@ public class Save extends SubCommand {
TaskManager.runTaskAsync(() -> { TaskManager.runTaskAsync(() -> {
String time = (System.currentTimeMillis() / 1000) + ""; String time = (System.currentTimeMillis() / 1000) + "";
Location[] corners = plot.getCorners(); Location[] corners = plot.getCorners();
corners[0] = corners[0].withY(0); corners[0] = corners[0].withY(plot.getArea().getMinBuildHeight());
corners[1] = corners[1].withY(255); corners[1] = corners[1].withY(plot.getArea().getMaxBuildHeight());
int size = (corners[1].getX() - corners[0].getX()) + 1; int size = (corners[1].getX() - corners[0].getX()) + 1;
PlotId id = plot.getId(); PlotId id = plot.getId();
String world1 = plot.getArea().toString().replaceAll(";", "-") String world1 = plot.getArea().toString().replaceAll(";", "-")

View File

@ -57,8 +57,12 @@ public class SetHome extends SetCommand {
Plot base = plot.getBasePlot(false); Plot base = plot.getBasePlot(false);
Location bottom = base.getBottomAbs(); Location bottom = base.getBottomAbs();
Location location = player.getLocationFull(); Location location = player.getLocationFull();
BlockLoc rel = new BlockLoc(location.getX() - bottom.getX(), location.getY(), BlockLoc rel = new BlockLoc(
location.getZ() - bottom.getZ(), location.getYaw(), location.getPitch() location.getX() - bottom.getX(),
location.getY(), // y is absolute
location.getZ() - bottom.getZ(),
location.getYaw(),
location.getPitch()
); );
base.setHome(rel); base.setHome(rel);
player.sendMessage(TranslatableCaption.of("position.position_set")); player.sendMessage(TranslatableCaption.of("position.position_set"));

View File

@ -180,12 +180,12 @@ public class Trim extends SubCommand {
int bx = cbx << 4; int bx = cbx << 4;
int bz = cbz << 4; int bz = cbz << 4;
CuboidRegion region = CuboidRegion region =
RegionUtil.createRegion(bx, bx + 511, bz, bz + 511); RegionUtil.createRegion(bx, bx + 511, 0, 0, bz, bz + 511);
for (Plot plot : PlotQuery.newQuery().inWorld(world)) { for (Plot plot : PlotQuery.newQuery().inWorld(world)) {
Location bot = plot.getBottomAbs(); Location bot = plot.getBottomAbs();
Location top = plot.getExtendedTopAbs(); Location top = plot.getExtendedTopAbs();
CuboidRegion plotReg = RegionUtil CuboidRegion plotReg = RegionUtil
.createRegion(bot.getX(), top.getX(), bot.getZ(), top.getZ()); .createRegion(bot.getX(), top.getX(), 0, 0, bot.getZ(), top.getZ());
if (!RegionUtil.intersects(region, plotReg)) { if (!RegionUtil.intersects(region, plotReg)) {
continue; continue;
} }

View File

@ -249,6 +249,9 @@ public class Settings extends Config {
public static int UUID_CACHE_SIZE = 100000; public static int UUID_CACHE_SIZE = 100000;
@Comment("Rate limit (per 10 minutes) for background UUID fetching from the Mojang API") @Comment("Rate limit (per 10 minutes) for background UUID fetching from the Mojang API")
public static int BACKGROUND_LIMIT = 200; public static int BACKGROUND_LIMIT = 200;
@Comment("Whether the Mojang API service is enabled for impromptu api calls. If false only the Background task will use" +
" http requests to fill the UUID cache (requires restart)")
public static boolean IMPROMPTU_SERVICE_MOJANG_API = true;
@Comment("Rate limit (per 10 minutes) for random UUID fetching from the Mojang API") @Comment("Rate limit (per 10 minutes) for random UUID fetching from the Mojang API")
public static int IMPROMPTU_LIMIT = 300; public static int IMPROMPTU_LIMIT = 300;
@Comment("Timeout (in milliseconds) for non-blocking UUID requests (mostly commands)") @Comment("Timeout (in milliseconds) for non-blocking UUID requests (mostly commands)")
@ -691,6 +694,7 @@ public class Settings extends Config {
@Comment({"If blocks at the edges of queued operations should be set causing updates", @Comment({"If blocks at the edges of queued operations should be set causing updates",
" - Slightly slower, but prevents issues such as fences left connected to nothing"}) " - Slightly slower, but prevents issues such as fences left connected to nothing"})
public static boolean UPDATE_EDGES = true; public static boolean UPDATE_EDGES = true;
} }
@Comment("Settings related to tab completion") @Comment("Settings related to tab completion")

View File

@ -54,12 +54,23 @@ public class AugmentedUtils {
enabled = true; enabled = true;
} }
public static boolean generate( /**
@Nullable Object chunkObject, * Generate an augmented world chunk at the given location. If a queue is given, the data will be written to it, else a new
* queue will be created and written to world. Returns true if generation occurred.
*
* @param world World name to generate data for. Must be a PlotSquared world containing one or more areas else nothing will
* happen.
* @param chunkX Chunk X position
* @param chunkZ Chunk Z position
* @param queue Queue to write to, if desired.
* @return true if generation occurred.
* @since 6.8.0
*/
public static boolean generateChunk(
final @NonNull String world, final @NonNull String world,
final int chunkX, final int chunkX,
final int chunkZ, final int chunkZ,
QueueCoordinator queue @Nullable QueueCoordinator queue
) { ) {
if (!enabled) { if (!enabled) {
return false; return false;
@ -70,7 +81,7 @@ public class AugmentedUtils {
final int blockZ = chunkZ << 4; final int blockZ = chunkZ << 4;
// Create a region that contains the // Create a region that contains the
// entire chunk // entire chunk
CuboidRegion region = RegionUtil.createRegion(blockX, blockX + 15, blockZ, blockZ + 15); CuboidRegion region = RegionUtil.createRegion(blockX, blockX + 15, 0, 0, blockZ, blockZ + 15);
// Query for plot areas in the chunk // Query for plot areas in the chunk
final Set<PlotArea> areas = PlotSquared.get().getPlotAreaManager().getPlotAreasSet(world, region); final Set<PlotArea> areas = PlotSquared.get().getPlotAreaManager().getPlotAreasSet(world, region);
if (areas.isEmpty()) { if (areas.isEmpty()) {
@ -97,9 +108,6 @@ public class AugmentedUtils {
.platform() .platform()
.worldUtil() .worldUtil()
.getWeWorld(world)); .getWeWorld(world));
if (chunkObject != null) {
queue.setChunkObject(chunkObject);
}
} }
QueueCoordinator primaryMask; QueueCoordinator primaryMask;
// coordinates // coordinates
@ -122,6 +130,7 @@ public class AugmentedUtils {
} }
QueueCoordinator secondaryMask; QueueCoordinator secondaryMask;
BlockState air = BlockTypes.AIR.getDefaultState(); BlockState air = BlockTypes.AIR.getDefaultState();
int startYOffset = !(area instanceof ClassicPlotWorld) || ((ClassicPlotWorld) area).PLOT_BEDROCK ? 1 : 0;
if (area.getTerrain() == PlotAreaTerrainType.ROAD) { if (area.getTerrain() == PlotAreaTerrainType.ROAD) {
PlotManager manager = area.getPlotManager(); PlotManager manager = area.getPlotManager();
final boolean[][] canPlace = new boolean[16][16]; final boolean[][] canPlace = new boolean[16][16];
@ -132,7 +141,7 @@ public class AugmentedUtils {
int worldZ = z + blockZ; int worldZ = z + blockZ;
boolean can = manager.getPlotId(worldX, 0, worldZ) == null; boolean can = manager.getPlotId(worldX, 0, worldZ) == null;
if (can) { if (can) {
for (int y = 1; y < 128; y++) { for (int y = area.getMinGenHeight() + startYOffset; y <= area.getMaxGenHeight(); y++) {
queue.setBlock(worldX, y, worldZ, air); queue.setBlock(worldX, y, worldZ, air);
} }
canPlace[x][z] = true; canPlace[x][z] = true;
@ -149,30 +158,24 @@ public class AugmentedUtils {
secondaryMask = primaryMask; secondaryMask = primaryMask;
for (int x = relativeBottomX; x <= relativeTopX; x++) { for (int x = relativeBottomX; x <= relativeTopX; x++) {
for (int z = relativeBottomZ; z <= relativeTopZ; z++) { for (int z = relativeBottomZ; z <= relativeTopZ; z++) {
for (int y = 1; y < 128; y++) { for (int y = area.getMinGenHeight() + startYOffset; y <= area.getMaxGenHeight(); y++) {
queue.setBlock(blockX + x, y, blockZ + z, air); queue.setBlock(blockX + x, y, blockZ + z, air);
} }
} }
} }
generationResult = true; generationResult = true;
} }
if (chunkObject != null) {
primaryMask.setChunkObject(chunkObject);
}
if (chunkObject != null) {
secondaryMask.setChunkObject(chunkObject);
}
// This queue should not be enqueued as it is simply used to restrict block setting, and then delegate to the
// actual queue
ScopedQueueCoordinator scoped = ScopedQueueCoordinator scoped =
new ScopedQueueCoordinator( new ScopedQueueCoordinator(
secondaryMask, secondaryMask,
Location.at(world, blockX, 0, blockZ), Location.at(world, blockX, area.getMinGenHeight(), blockZ),
Location.at(world, blockX + 15, 255, blockZ + 15) Location.at(world, blockX + 15, area.getMaxGenHeight(), blockZ + 15)
); );
generator.generateChunk(scoped, area); generator.generateChunk(scoped, area);
generator.populateChunk(scoped, area); generator.populateChunk(scoped, area);
scoped.setForceSync(true);
scoped.enqueue();
} }
if (enqueue) { if (enqueue) {
queue.enqueue(); queue.enqueue();
@ -180,4 +183,19 @@ public class AugmentedUtils {
return generationResult; return generationResult;
} }
/**
* @deprecated Use {@link AugmentedUtils#generateChunk(String, int, int, QueueCoordinator)} as chunkObject is not required
* in the above method
*/
@Deprecated(forRemoval = true, since = "6.8.0")
public static boolean generate(
@Nullable Object chunkObject,
final @NonNull String world,
final int chunkX,
final int chunkZ,
QueueCoordinator queue
) {
return generateChunk(world, chunkX, chunkZ, queue);
}
} }

View File

@ -37,7 +37,6 @@ import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaTerrainType;
import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.BlockUtil;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskManager;
@ -147,7 +146,15 @@ public class ClassicPlotManager extends SquarePlotManager {
) { ) {
Plot plot = classicPlotWorld.getPlotAbs(plotId); Plot plot = classicPlotWorld.getPlotAbs(plotId);
if (plot != null && plot.isBasePlot()) { if (plot != null && plot.isBasePlot()) {
return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight(), actor, queue); return this.regionManager.setCuboids(
classicPlotWorld,
plot.getRegions(),
blocks,
classicPlotWorld.getMinBuildHeight(),
classicPlotWorld.getMaxBuildHeight(),
actor,
queue
);
} }
return false; return false;
} }
@ -175,7 +182,7 @@ public class ClassicPlotManager extends SquarePlotManager {
plot.getRegions(), plot.getRegions(),
blocks, blocks,
classicPlotWorld.PLOT_HEIGHT + 1, classicPlotWorld.PLOT_HEIGHT + 1,
getWorldHeight(), classicPlotWorld.getMaxBuildHeight(),
actor, actor,
queue queue
); );
@ -204,7 +211,7 @@ public class ClassicPlotManager extends SquarePlotManager {
classicPlotWorld, classicPlotWorld,
plot.getRegions(), plot.getRegions(),
blocks, blocks,
1, classicPlotWorld.getMinBuildHeight(),
classicPlotWorld.PLOT_HEIGHT - 1, classicPlotWorld.PLOT_HEIGHT - 1,
actor, actor,
queue queue
@ -281,7 +288,7 @@ public class ClassicPlotManager extends SquarePlotManager {
} }
} }
int maxY = classicPlotWorld.getPlotManager().getWorldHeight(); int maxY = classicPlotWorld.getMaxBuildHeight();
if (!plot.isMerged(Direction.NORTH)) { if (!plot.isMerged(Direction.NORTH)) {
int z = bottom.getZ(); int z = bottom.getZ();
for (int x = bottom.getX(); x <= top.getX(); x++) { for (int x = bottom.getX(); x <= top.getX(); x++) {
@ -382,7 +389,7 @@ public class ClassicPlotManager extends SquarePlotManager {
if (!plot.isMerged(Direction.NORTH)) { if (!plot.isMerged(Direction.NORTH)) {
int z = bot.getZ(); int z = bot.getZ();
for (int x = bot.getX(); x < top.getX(); x++) { for (int x = bot.getX(); x < top.getX(); x++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -390,7 +397,7 @@ public class ClassicPlotManager extends SquarePlotManager {
if (!plot.isMerged(Direction.WEST)) { if (!plot.isMerged(Direction.WEST)) {
int x = bot.getX(); int x = bot.getX();
for (int z = bot.getZ(); z < top.getZ(); z++) { for (int z = bot.getZ(); z < top.getZ(); z++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -398,7 +405,7 @@ public class ClassicPlotManager extends SquarePlotManager {
if (!plot.isMerged(Direction.SOUTH)) { if (!plot.isMerged(Direction.SOUTH)) {
int z = top.getZ(); int z = top.getZ();
for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) { for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -406,7 +413,7 @@ public class ClassicPlotManager extends SquarePlotManager {
if (!plot.isMerged(Direction.EAST)) { if (!plot.isMerged(Direction.EAST)) {
int x = top.getX(); int x = top.getX();
for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) { for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) {
for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -501,7 +508,7 @@ public class ClassicPlotManager extends SquarePlotManager {
enqueue = true; enqueue = true;
} }
int maxY = getWorldHeight(); int maxY = classicPlotWorld.getMaxGenHeight();
queue.setCuboid( queue.setCuboid(
Location.at( Location.at(
classicPlotWorld.getWorldName(), classicPlotWorld.getWorldName(),
@ -513,27 +520,27 @@ public class ClassicPlotManager extends SquarePlotManager {
); );
if (classicPlotWorld.PLOT_BEDROCK) { if (classicPlotWorld.PLOT_BEDROCK) {
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1), Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight(), sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, 0, ez - 1), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight(), ez - 1),
BlockTypes.BEDROCK.getDefaultState() BlockTypes.BEDROCK.getDefaultState()
); );
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern()
);
} else {
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern()
);
} }
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern()
);
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern() classicPlotWorld.WALL_FILLING.toPattern()
); );
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1),
classicPlotWorld.ROAD_BLOCK.toPattern()
);
if (classicPlotWorld.PLACE_TOP_BLOCK) { if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid( queue.setCuboid(
@ -541,24 +548,12 @@ public class ClassicPlotManager extends SquarePlotManager {
Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, ez - 1),
classicPlotWorld.WALL_BLOCK.toPattern() classicPlotWorld.WALL_BLOCK.toPattern()
); );
}
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), ex, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1),
classicPlotWorld.WALL_FILLING.toPattern()
);
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, sz + 1), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, ez - 1),
classicPlotWorld.WALL_BLOCK.toPattern() classicPlotWorld.WALL_BLOCK.toPattern()
); );
} }
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1),
classicPlotWorld.ROAD_BLOCK.toPattern()
);
return !enqueue || queue.enqueue(); return !enqueue || queue.enqueue();
} }
@ -584,19 +579,32 @@ public class ClassicPlotManager extends SquarePlotManager {
classicPlotWorld.schematicStartHeight() + 1, classicPlotWorld.schematicStartHeight() + 1,
sz sz
), ),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez),
BlockTypes.AIR.getDefaultState() BlockTypes.AIR.getDefaultState()
); );
if (classicPlotWorld.PLOT_BEDROCK) {
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez),
BlockTypes.BEDROCK.getDefaultState()
);
}
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz), Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez),
BlockUtil.get((short) 7, (byte) 0)
);
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz),
classicPlotWorld.WALL_FILLING.toPattern() classicPlotWorld.WALL_FILLING.toPattern()
); );
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez),
classicPlotWorld.WALL_FILLING.toPattern()
);
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1),
classicPlotWorld.ROAD_BLOCK.toPattern()
);
if (classicPlotWorld.PLACE_TOP_BLOCK) { if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid( queue.setCuboid(
@ -604,24 +612,12 @@ public class ClassicPlotManager extends SquarePlotManager {
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, sz), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, sz),
classicPlotWorld.WALL_BLOCK.toPattern() classicPlotWorld.WALL_BLOCK.toPattern()
); );
}
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez),
classicPlotWorld.WALL_FILLING.toPattern()
);
if (classicPlotWorld.PLACE_TOP_BLOCK) {
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, ez), Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, ez),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, ez), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, ez),
classicPlotWorld.WALL_BLOCK.toPattern() classicPlotWorld.WALL_BLOCK.toPattern()
); );
} }
queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1),
classicPlotWorld.ROAD_BLOCK.toPattern()
);
return !enqueue || queue.enqueue(); return !enqueue || queue.enqueue();
} }
@ -642,14 +638,19 @@ public class ClassicPlotManager extends SquarePlotManager {
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1, sz + 1), Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez - 1), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez - 1),
BlockTypes.AIR.getDefaultState() BlockTypes.AIR.getDefaultState()
); );
queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz + 1), if (classicPlotWorld.PLOT_BEDROCK) {
Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez - 1), BlockUtil.get((short) 7, (byte) 0) queue.setCuboid(
); Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez - 1),
BlockTypes.BEDROCK.getDefaultState()
);
}
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1), Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1),
classicPlotWorld.ROAD_BLOCK.toPattern() classicPlotWorld.ROAD_BLOCK.toPattern()
); );
@ -679,11 +680,12 @@ public class ClassicPlotManager extends SquarePlotManager {
classicPlotWorld.schematicStartHeight() + 1, classicPlotWorld.schematicStartHeight() + 1,
sz sz
), ),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez),
BlockTypes.AIR.getDefaultState() BlockTypes.AIR.getDefaultState()
); );
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1), Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez - 1), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez - 1),
classicPlotWorld.MAIN_BLOCK.toPattern() classicPlotWorld.MAIN_BLOCK.toPattern()
); );
@ -719,11 +721,12 @@ public class ClassicPlotManager extends SquarePlotManager {
classicPlotWorld.schematicStartHeight() + 1, classicPlotWorld.schematicStartHeight() + 1,
sz sz
), ),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez),
BlockTypes.AIR.getDefaultState() BlockTypes.AIR.getDefaultState()
); );
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz), Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz),
Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1, ez), Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1, ez),
classicPlotWorld.MAIN_BLOCK.toPattern() classicPlotWorld.MAIN_BLOCK.toPattern()
); );
@ -758,11 +761,12 @@ public class ClassicPlotManager extends SquarePlotManager {
classicPlotWorld.schematicStartHeight() + 1, classicPlotWorld.schematicStartHeight() + 1,
sz sz
), ),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez),
BlockTypes.AIR.getDefaultState() BlockTypes.AIR.getDefaultState()
); );
int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0;
queue.setCuboid( queue.setCuboid(
Location.at(classicPlotWorld.getWorldName(), sx, 1, sz), Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz),
Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez), Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez),
classicPlotWorld.MAIN_BLOCK.toPattern() classicPlotWorld.MAIN_BLOCK.toPattern()
); );

View File

@ -127,16 +127,16 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld {
public void loadConfiguration(ConfigurationSection config) { public void loadConfiguration(ConfigurationSection config) {
super.loadConfiguration(config); super.loadConfiguration(config);
this.PLOT_BEDROCK = config.getBoolean("plot.bedrock"); this.PLOT_BEDROCK = config.getBoolean("plot.bedrock");
this.PLOT_HEIGHT = Math.min(255, config.getInt("plot.height")); this.PLOT_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("plot.height"));
this.MAIN_BLOCK = new BlockBucket(config.getString("plot.filling")); this.MAIN_BLOCK = new BlockBucket(config.getString("plot.filling"));
this.TOP_BLOCK = new BlockBucket(config.getString("plot.floor")); this.TOP_BLOCK = new BlockBucket(config.getString("plot.floor"));
this.WALL_BLOCK = new BlockBucket(config.getString("wall.block")); this.WALL_BLOCK = new BlockBucket(config.getString("wall.block"));
this.ROAD_HEIGHT = Math.min(255, config.getInt("road.height")); this.ROAD_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("road.height"));
this.ROAD_BLOCK = new BlockBucket(config.getString("road.block")); this.ROAD_BLOCK = new BlockBucket(config.getString("road.block"));
this.WALL_FILLING = new BlockBucket(config.getString("wall.filling")); this.WALL_FILLING = new BlockBucket(config.getString("wall.filling"));
this.WALL_HEIGHT = Math.min(254, config.getInt("wall.height"));
this.CLAIMED_WALL_BLOCK = new BlockBucket(config.getString("wall.block_claimed"));
this.PLACE_TOP_BLOCK = config.getBoolean("wall.place_top_block"); this.PLACE_TOP_BLOCK = config.getBoolean("wall.place_top_block");
this.WALL_HEIGHT = Math.min(getMaxGenHeight() - (PLACE_TOP_BLOCK ? 1 : 0), config.getInt("wall.height"));
this.CLAIMED_WALL_BLOCK = new BlockBucket(config.getString("wall.block_claimed"));
} }
int schematicStartHeight() { int schematicStartHeight() {

View File

@ -35,13 +35,23 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public class HybridGen extends IndependentPlotGenerator { public class HybridGen extends IndependentPlotGenerator {
private static final CuboidRegion CHUNK = new CuboidRegion(BlockVector3.ZERO, BlockVector3.at(15, 396, 15));
private final HybridPlotWorldFactory hybridPlotWorldFactory; private final HybridPlotWorldFactory hybridPlotWorldFactory;
@Inject @Inject
@ -55,12 +65,17 @@ public class HybridGen extends IndependentPlotGenerator {
} }
private void placeSchem( private void placeSchem(
HybridPlotWorld world, ScopedQueueCoordinator result, short relativeX, HybridPlotWorld world,
short relativeZ, int x, int z, boolean isRoad ScopedQueueCoordinator result,
short relativeX,
short relativeZ,
int x,
int z,
boolean isRoad,
boolean isPopulating
) { ) {
int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT); int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT);
if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) {
&& Settings.Schematics.PASTE_ON_TOP)) {
minY = world.SCHEM_Y; minY = world.SCHEM_Y;
} else { } else {
minY = world.getMinBuildHeight(); minY = world.getMinBuildHeight();
@ -69,7 +84,9 @@ public class HybridGen extends IndependentPlotGenerator {
if (blocks != null) { if (blocks != null) {
for (int y = 0; y < blocks.length; y++) { for (int y = 0; y < blocks.length; y++) {
if (blocks[y] != null) { if (blocks[y] != null) {
result.setBlock(x, minY + y, z, blocks[y]); if (!isPopulating || blocks[y].hasNbtData()) {
result.setBlock(x, minY + y, z, blocks[y]);
}
} }
} }
} }
@ -91,7 +108,7 @@ public class HybridGen extends IndependentPlotGenerator {
if (hybridPlotWorld.PLOT_BEDROCK) { if (hybridPlotWorld.PLOT_BEDROCK) {
for (short x = 0; x < 16; x++) { for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) { for (short z = 0; z < 16; z++) {
result.setBlock(x, 0, z, BlockTypes.BEDROCK.getDefaultState()); result.setBlock(x, hybridPlotWorld.getMinGenHeight(), z, BlockTypes.BEDROCK.getDefaultState());
} }
} }
} }
@ -121,42 +138,38 @@ public class HybridGen extends IndependentPlotGenerator {
short[] relativeX = new short[16]; short[] relativeX = new short[16];
boolean[] insideRoadX = new boolean[16]; boolean[] insideRoadX = new boolean[16];
boolean[] insideWallX = new boolean[16]; boolean[] insideWallX = new boolean[16];
short offsetX = relativeOffsetX;
for (short i = 0; i < 16; i++) { for (short i = 0; i < 16; i++) {
short v = (short) (relativeOffsetX + i); if (offsetX >= hybridPlotWorld.SIZE) {
while (v >= hybridPlotWorld.SIZE) { offsetX -= hybridPlotWorld.SIZE;
v -= hybridPlotWorld.SIZE;
} }
relativeX[i] = v; relativeX[i] = offsetX;
if (hybridPlotWorld.ROAD_WIDTH != 0) { if (hybridPlotWorld.ROAD_WIDTH != 0) {
insideRoadX[i] = insideRoadX[i] = offsetX < hybridPlotWorld.PATH_WIDTH_LOWER || offsetX > hybridPlotWorld.PATH_WIDTH_UPPER;
v < hybridPlotWorld.PATH_WIDTH_LOWER || v > hybridPlotWorld.PATH_WIDTH_UPPER; insideWallX[i] = offsetX == hybridPlotWorld.PATH_WIDTH_LOWER || offsetX == hybridPlotWorld.PATH_WIDTH_UPPER;
insideWallX[i] =
v == hybridPlotWorld.PATH_WIDTH_LOWER || v == hybridPlotWorld.PATH_WIDTH_UPPER;
} }
offsetX++;
} }
// The Z-coordinate of a given Z coordinate, relative to the // The Z-coordinate of a given Z coordinate, relative to the
// plot (Counting from the corner with the least positive // plot (Counting from the corner with the least positive
// coordinates) // coordinates)
short[] relativeZ = new short[16]; short[] relativeZ = new short[16];
// Whether or not the given Z coordinate belongs to the road
boolean[] insideRoadZ = new boolean[16]; boolean[] insideRoadZ = new boolean[16];
// Whether or not the given Z coordinate belongs to the wall
boolean[] insideWallZ = new boolean[16]; boolean[] insideWallZ = new boolean[16];
short offsetZ = relativeOffsetZ;
for (short i = 0; i < 16; i++) { for (short i = 0; i < 16; i++) {
short v = (short) (relativeOffsetZ + i); if (offsetZ >= hybridPlotWorld.SIZE) {
while (v >= hybridPlotWorld.SIZE) { offsetZ -= hybridPlotWorld.SIZE;
v -= hybridPlotWorld.SIZE;
} }
relativeZ[i] = v; relativeZ[i] = offsetZ;
if (hybridPlotWorld.ROAD_WIDTH != 0) { if (hybridPlotWorld.ROAD_WIDTH != 0) {
insideRoadZ[i] = insideRoadZ[i] = offsetZ < hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ > hybridPlotWorld.PATH_WIDTH_UPPER;
v < hybridPlotWorld.PATH_WIDTH_LOWER || v > hybridPlotWorld.PATH_WIDTH_UPPER; insideWallZ[i] = offsetZ == hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ == hybridPlotWorld.PATH_WIDTH_UPPER;
insideWallZ[i] =
v == hybridPlotWorld.PATH_WIDTH_LOWER || v == hybridPlotWorld.PATH_WIDTH_UPPER;
} }
offsetZ++;
} }
// generation // generation
int startY = hybridPlotWorld.PLOT_BEDROCK ? 1 : 0; int startY = hybridPlotWorld.getMinGenHeight() + (hybridPlotWorld.PLOT_BEDROCK ? 1 : 0);
for (short x = 0; x < 16; x++) { for (short x = 0; x < 16; x++) {
if (insideRoadX[x]) { if (insideRoadX[x]) {
for (short z = 0; z < 16; z++) { for (short z = 0; z < 16; z++) {
@ -165,7 +178,7 @@ public class HybridGen extends IndependentPlotGenerator {
result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern());
} }
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true); placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false);
} }
} }
} else if (insideWallX[x]) { } else if (insideWallX[x]) {
@ -176,9 +189,7 @@ public class HybridGen extends IndependentPlotGenerator {
result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern());
} }
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false);
true
);
} }
} else { } else {
// wall // wall
@ -187,14 +198,10 @@ public class HybridGen extends IndependentPlotGenerator {
} }
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
if (hybridPlotWorld.PLACE_TOP_BLOCK) { if (hybridPlotWorld.PLACE_TOP_BLOCK) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, hybridPlotWorld.WALL_BLOCK.toPattern());
hybridPlotWorld.WALL_BLOCK.toPattern()
);
} }
} else { } else {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false);
true
);
} }
} }
} }
@ -206,9 +213,7 @@ public class HybridGen extends IndependentPlotGenerator {
result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); result.setBlock(x, y, z, hybridPlotWorld.ROAD_BLOCK.toPattern());
} }
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false);
true
);
} }
} else if (insideWallZ[z]) { } else if (insideWallZ[z]) {
// wall // wall
@ -217,27 +222,19 @@ public class HybridGen extends IndependentPlotGenerator {
} }
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
if (hybridPlotWorld.PLACE_TOP_BLOCK) { if (hybridPlotWorld.PLACE_TOP_BLOCK) {
result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, result.setBlock(x, hybridPlotWorld.WALL_HEIGHT + 1, z, hybridPlotWorld.WALL_BLOCK.toPattern());
hybridPlotWorld.WALL_BLOCK.toPattern()
);
} }
} else { } else {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, false);
true
);
} }
} else { } else {
// plot // plot
for (int y = startY; y < hybridPlotWorld.PLOT_HEIGHT; y++) { for (int y = startY; y < hybridPlotWorld.PLOT_HEIGHT; y++) {
result.setBlock(x, y, z, hybridPlotWorld.MAIN_BLOCK.toPattern()); result.setBlock(x, y, z, hybridPlotWorld.MAIN_BLOCK.toPattern());
} }
result.setBlock(x, hybridPlotWorld.PLOT_HEIGHT, z, result.setBlock(x, hybridPlotWorld.PLOT_HEIGHT, z, hybridPlotWorld.TOP_BLOCK.toPattern());
hybridPlotWorld.TOP_BLOCK.toPattern()
);
if (hybridPlotWorld.PLOT_SCHEMATIC) { if (hybridPlotWorld.PLOT_SCHEMATIC) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, false, false);
false
);
} }
} }
} }
@ -245,6 +242,138 @@ public class HybridGen extends IndependentPlotGenerator {
} }
} }
@Override
public boolean populateChunk(final ScopedQueueCoordinator result, final PlotArea settings) {
HybridPlotWorld hybridPlotWorld = (HybridPlotWorld) settings;
if (!hybridPlotWorld.populationNeeded()) {
return false;
}
// Coords
Location min = result.getMin();
int bx = min.getX() - hybridPlotWorld.ROAD_OFFSET_X;
int bz = min.getZ() - hybridPlotWorld.ROAD_OFFSET_Z;
// The relative X-coordinate (within the plot) of the minimum X coordinate
// contained in the scoped queue
short relativeOffsetX;
if (bx < 0) {
relativeOffsetX = (short) (hybridPlotWorld.SIZE + (bx % hybridPlotWorld.SIZE));
} else {
relativeOffsetX = (short) (bx % hybridPlotWorld.SIZE);
}
// The relative Z-coordinate (within the plot) of the minimum Z coordinate
// contained in the scoped queue
short relativeOffsetZ;
if (bz < 0) {
relativeOffsetZ = (short) (hybridPlotWorld.SIZE + (bz % hybridPlotWorld.SIZE));
} else {
relativeOffsetZ = (short) (bz % hybridPlotWorld.SIZE);
}
boolean allRoad = true;
boolean overlap = false;
// The X-coordinate of a given X coordinate, relative to the
// plot (Counting from the corner with the least positive
// coordinates)
short[] relativeX = new short[16];
boolean[] insideRoadX = new boolean[16];
boolean[] insideWallX = new boolean[16];
short offsetX = relativeOffsetX;
for (short i = 0; i < 16; i++) {
if (offsetX >= hybridPlotWorld.SIZE) {
offsetX -= hybridPlotWorld.SIZE;
overlap = true;
}
relativeX[i] = offsetX;
if (hybridPlotWorld.ROAD_WIDTH != 0) {
boolean insideRoad = offsetX < hybridPlotWorld.PATH_WIDTH_LOWER || offsetX > hybridPlotWorld.PATH_WIDTH_UPPER;
boolean insideWall = offsetX == hybridPlotWorld.PATH_WIDTH_LOWER || offsetX == hybridPlotWorld.PATH_WIDTH_UPPER;
insideRoadX[i] = insideRoad;
insideWallX[i] = insideWall;
allRoad &= insideRoad && insideWall;
}
offsetX++;
}
// The Z-coordinate of a given Z coordinate, relative to the
// plot (Counting from the corner with the least positive
// coordinates)
short[] relativeZ = new short[16];
boolean[] insideRoadZ = new boolean[16];
boolean[] insideWallZ = new boolean[16];
short offsetZ = relativeOffsetZ;
for (short i = 0; i < 16; i++) {
if (offsetZ >= hybridPlotWorld.SIZE) {
offsetZ -= hybridPlotWorld.SIZE;
overlap = true;
}
relativeZ[i] = offsetZ;
if (hybridPlotWorld.ROAD_WIDTH != 0) {
boolean insideRoad = offsetZ < hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ > hybridPlotWorld.PATH_WIDTH_UPPER;
boolean insideWall = offsetZ == hybridPlotWorld.PATH_WIDTH_LOWER || offsetZ == hybridPlotWorld.PATH_WIDTH_UPPER;
insideRoadZ[i] = insideRoad;
insideWallZ[i] = insideWall;
allRoad &= insideRoad && insideWall;
}
offsetZ++;
}
for (short x = 0; x < 16; x++) {
if (insideRoadX[x] || insideWallX[x]) {
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
for (short z = 0; z < 16; z++) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, true);
}
}
} else {
for (short z = 0; z < 16; z++) {
if (insideRoadZ[z] || insideWallZ[z]) {
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, true, true);
}
} else if (hybridPlotWorld.PLOT_SCHEMATIC) {
placeSchem(hybridPlotWorld, result, relativeX[x], relativeZ[z], x, z, false, true);
}
}
}
}
if (!allRoad && hybridPlotWorld.getPlotSchematicEntities() != null && !hybridPlotWorld
.getPlotSchematicEntities()
.isEmpty()) {
CuboidRegion region = CHUNK.clone();
try {
region.shift(hybridPlotWorld
.getPlotSchematicMinPoint()
.add(relativeOffsetX, 0, relativeOffsetZ)
.subtract(hybridPlotWorld.PATH_WIDTH_LOWER + 1, 0, hybridPlotWorld.PATH_WIDTH_LOWER + 1));
for (Entity entity : hybridPlotWorld.getPlotSchematicEntities()) {
if (region.contains(entity.getLocation().toVector().toBlockPoint())) {
Vector3 pos = (entity.getLocation().toVector()
.subtract(region.getMinimumPoint().withY(hybridPlotWorld.getPlotSchematicMinPoint().getY()).toVector3()))
.add(min.getBlockVector3().withY(hybridPlotWorld.SCHEM_Y).toVector3());
result.setEntity(new PopulatingEntity(
entity,
new com.sk89q.worldedit.util.Location(NullWorld.getInstance(), pos)
));
}
}
} catch (RegionOperationException e) {
throw new RuntimeException(e);
}
if (overlap) {
try {
region.shift(BlockVector3.at(-hybridPlotWorld.SIZE, 0, -hybridPlotWorld.SIZE));
for (Entity entity : hybridPlotWorld.getPlotSchematicEntities()) {
if (region.contains(entity.getLocation().toVector().toBlockPoint())) {
result.setEntity(entity);
}
}
} catch (RegionOperationException e) {
throw new RuntimeException(e);
}
}
}
return true;
}
@Override @Override
public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) { public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) {
return this.hybridPlotWorldFactory.create(world, id, this, min, max); return this.hybridPlotWorldFactory.create(world, id, this, min, max);
@ -255,4 +384,58 @@ public class HybridGen extends IndependentPlotGenerator {
// All initialization is done in the PlotArea class // All initialization is done in the PlotArea class
} }
/**
* Wrapper to allow a WorldEdit {@link Entity} to effectively have a mutable location as the location in its NBT should be changed
* when set to the world.
*
* @since TODO
*/
private static final class PopulatingEntity implements Entity {
private final Entity parent;
private com.sk89q.worldedit.util.Location location;
/**
* @since TODO
*/
private PopulatingEntity(Entity parent, com.sk89q.worldedit.util.Location location) {
this.parent = parent;
this.location = location;
}
@Nullable
@Override
public BaseEntity getState() {
return parent.getState();
}
@Override
public boolean remove() {
return parent.remove();
}
@Override
public com.sk89q.worldedit.util.Location getLocation() {
return location;
}
@Override
public boolean setLocation(final com.sk89q.worldedit.util.Location location) {
this.location = location;
return true;
}
@Override
public Extent getExtent() {
return parent.getExtent();
}
@Nullable
@Override
public <T> T getFacet(final Class<? extends T> cls) {
return parent.getFacet(cls);
}
}
} }

View File

@ -46,7 +46,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -107,22 +106,32 @@ public class HybridPlotManager extends ClassicPlotManager {
@Override @Override
public boolean createRoadEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { public boolean createRoadEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) {
boolean enqueue = false;
if (queue == null) {
queue = hybridPlotWorld.getQueue();
enqueue = true;
}
super.createRoadEast(plot, queue); super.createRoadEast(plot, queue);
PlotId id = plot.getId(); PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX() + 1, id.getY()); PlotId id2 = PlotId.of(id.getX() + 1, id.getY());
Location bot = getPlotBottomLocAbs(id2); Location bot = getPlotBottomLocAbs(id2);
Location top = getPlotTopLocAbs(id); Location top = getPlotTopLocAbs(id);
Location pos1 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, 0, bot.getZ() - 1); Location pos1 = Location.at(
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), bot.getX(), Math.min(getWorldHeight(), 255), top.getZ() + 1); hybridPlotWorld.getWorldName(),
top.getX() + 1,
hybridPlotWorld.getMinGenHeight(),
bot.getZ() - 1
);
Location pos2 = Location.at(
hybridPlotWorld.getWorldName(),
bot.getX(),
hybridPlotWorld.getMaxGenHeight(),
top.getZ() + 1
);
this.resetBiome(hybridPlotWorld, pos1, pos2); this.resetBiome(hybridPlotWorld, pos1, pos2);
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
return true; return true;
} }
boolean enqueue = false;
if (queue == null) {
queue = hybridPlotWorld.getQueue();
enqueue = true;
}
createSchemAbs(queue, pos1, pos2, true); createSchemAbs(queue, pos1, pos2, true);
return !enqueue || queue.enqueue(); return !enqueue || queue.enqueue();
} }
@ -139,7 +148,7 @@ public class HybridPlotManager extends ClassicPlotManager {
(pos1.getX() + pos2.getX()) / 2, (pos1.getX() + pos2.getX()) / 2,
(pos1.getZ() + pos2.getZ()) / 2 (pos1.getZ() + pos2.getZ()) / 2
), biome)) { ), biome)) {
WorldUtil.setBiome(hybridPlotWorld.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome); WorldUtil.setBiome(hybridPlotWorld.getWorldName(), new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), biome);
} }
} }
@ -190,38 +199,38 @@ public class HybridPlotManager extends ClassicPlotManager {
@Override @Override
public boolean createRoadSouth(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { public boolean createRoadSouth(final @NonNull Plot plot, @Nullable QueueCoordinator queue) {
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = hybridPlotWorld.getQueue();
}
super.createRoadSouth(plot, queue); super.createRoadSouth(plot, queue);
PlotId id = plot.getId(); PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX(), id.getY() + 1); PlotId id2 = PlotId.of(id.getX(), id.getY() + 1);
Location bot = getPlotBottomLocAbs(id2); Location bot = getPlotBottomLocAbs(id2);
Location top = getPlotTopLocAbs(id); Location top = getPlotTopLocAbs(id);
Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, 0, top.getZ() + 1); Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, hybridPlotWorld.getMinGenHeight(), top.getZ() + 1);
Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, Math.min(getWorldHeight(), 255), bot.getZ()); Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, hybridPlotWorld.getMaxGenHeight(), bot.getZ());
this.resetBiome(hybridPlotWorld, pos1, pos2); this.resetBiome(hybridPlotWorld, pos1, pos2);
if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
return true; return true;
} }
boolean enqueue = false;
if (queue == null) {
enqueue = true;
queue = hybridPlotWorld.getQueue();
}
createSchemAbs(queue, pos1, pos2, true); createSchemAbs(queue, pos1, pos2, true);
return !enqueue || queue.enqueue(); return !enqueue || queue.enqueue();
} }
@Override @Override
public boolean createRoadSouthEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { public boolean createRoadSouthEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) {
super.createRoadSouthEast(plot, queue);
PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX() + 1, id.getY() + 1);
Location pos1 = getPlotTopLocAbs(id).add(1, 0, 1).withY(0);
Location pos2 = getPlotBottomLocAbs(id2).withY(Math.min(getWorldHeight(), 255));
boolean enqueue = false; boolean enqueue = false;
if (queue == null) { if (queue == null) {
enqueue = true; enqueue = true;
queue = hybridPlotWorld.getQueue(); queue = hybridPlotWorld.getQueue();
} }
super.createRoadSouthEast(plot, queue);
PlotId id = plot.getId();
PlotId id2 = PlotId.of(id.getX() + 1, id.getY() + 1);
Location pos1 = getPlotTopLocAbs(id).add(1, 0, 1);
Location pos2 = getPlotBottomLocAbs(id2);
createSchemAbs(queue, pos1, pos2, true); createSchemAbs(queue, pos1, pos2, true);
if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) {
createSchemAbs(queue, pos1, pos2, true); createSchemAbs(queue, pos1, pos2, true);
@ -271,11 +280,23 @@ public class HybridPlotManager extends ClassicPlotManager {
queue.setCompleteTask(whenDone); queue.setCompleteTask(whenDone);
} }
if (!canRegen) { if (!canRegen) {
queue.setCuboid(pos1.withY(0), pos2.withY(0), bedrock); queue.setCuboid(
pos1.withY(hybridPlotWorld.getMinGenHeight()),
pos2.withY(hybridPlotWorld.getMinGenHeight()),
hybridPlotWorld.PLOT_BEDROCK ? bedrock : filling
);
// Each component has a different layer // Each component has a different layer
queue.setCuboid(pos1.withY(1), pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1), filling); queue.setCuboid(
pos1.withY(hybridPlotWorld.getMinGenHeight() + 1),
pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1),
filling
);
queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT), pos2.withY(hybridPlotWorld.PLOT_HEIGHT), plotfloor); queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT), pos2.withY(hybridPlotWorld.PLOT_HEIGHT), plotfloor);
queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1), pos2.withY(getWorldHeight()), BlockTypes.AIR.getDefaultState()); queue.setCuboid(
pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1),
pos2.withY(hybridPlotWorld.getMaxGenHeight()),
BlockTypes.AIR.getDefaultState()
);
queue.setBiomeCuboid(pos1, pos2, biome); queue.setBiomeCuboid(pos1, pos2, biome);
} else { } else {
queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3())); queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()));

View File

@ -40,11 +40,13 @@ import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.plot.PlotManager;
import com.plotsquared.core.plot.schematic.Schematic; import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.util.AnnotationHelper;
import com.plotsquared.core.util.FileUtils; import com.plotsquared.core.util.FileUtils;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SchematicHandler;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompoundTagBuilder; import com.sk89q.jnbt.CompoundTagBuilder;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.internal.helper.MCDirections; import com.sk89q.worldedit.internal.helper.MCDirections;
@ -58,11 +60,13 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.annotation.Nullable;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
public class HybridPlotWorld extends ClassicPlotWorld { public class HybridPlotWorld extends ClassicPlotWorld {
@ -71,6 +75,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
private static final AffineTransform transform = new AffineTransform().rotateY(90); private static final AffineTransform transform = new AffineTransform().rotateY(90);
public boolean ROAD_SCHEMATIC_ENABLED; public boolean ROAD_SCHEMATIC_ENABLED;
public boolean PLOT_SCHEMATIC = false; public boolean PLOT_SCHEMATIC = false;
@Deprecated(forRemoval = true, since = "TODO")
public int PLOT_SCHEMATIC_HEIGHT = -1; public int PLOT_SCHEMATIC_HEIGHT = -1;
public short PATH_WIDTH_LOWER; public short PATH_WIDTH_LOWER;
public short PATH_WIDTH_UPPER; public short PATH_WIDTH_UPPER;
@ -79,6 +84,12 @@ public class HybridPlotWorld extends ClassicPlotWorld {
public int SCHEM_Y; public int SCHEM_Y;
private Location SIGN_LOCATION; private Location SIGN_LOCATION;
private File root = null; private File root = null;
private int lastOverlayHeightError = Integer.MIN_VALUE;
private List<Entity> schem3Entities = null;
private BlockVector3 schem3MinPoint = null;
private boolean schem1PopulationNeeded = false;
private boolean schem2PopulationNeeded = false;
private boolean schem3PopulationNeeded = false;
@Inject @Inject
private SchematicHandler schematicHandler; private SchematicHandler schematicHandler;
@ -97,6 +108,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
PlotSquared.platform().injector().injectMembers(this); PlotSquared.platform().injector().injectMembers(this);
} }
@Deprecated(forRemoval = true, since = "TODO")
public static byte wrap(byte data, int start) { public static byte wrap(byte data, int start) {
if ((data >= start) && (data < (start + 4))) { if ((data >= start) && (data < (start + 4))) {
data = (byte) ((((data - start) + 2) & 3) + start); data = (byte) ((((data - start) + 2) & 3) + start);
@ -104,6 +116,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
return data; return data;
} }
@Deprecated(forRemoval = true, since = "TODO")
public static byte wrap2(byte data, int start) { public static byte wrap2(byte data, int start) {
if ((data >= start) && (data < (start + 2))) { if ((data >= start) && (data < (start + 2))) {
data = (byte) ((((data - start) + 1) & 1) + start); data = (byte) ((((data - start) + 1) & 1) + start);
@ -111,8 +124,6 @@ public class HybridPlotWorld extends ClassicPlotWorld {
return data; return data;
} }
// FIXME depends on block ids
// Possibly make abstract?
public static BaseBlock rotate(BaseBlock id) { public static BaseBlock rotate(BaseBlock id) {
CompoundTag tag = id.getNbtData(); CompoundTag tag = id.getNbtData();
@ -171,9 +182,9 @@ public class HybridPlotWorld extends ClassicPlotWorld {
public void loadConfiguration(ConfigurationSection config) { public void loadConfiguration(ConfigurationSection config) {
super.loadConfiguration(config); super.loadConfiguration(config);
if ((this.ROAD_WIDTH & 1) == 0) { if ((this.ROAD_WIDTH & 1) == 0) {
this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2) - 1); this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2f) - 1);
} else { } else {
this.PATH_WIDTH_LOWER = (short) Math.floor(this.ROAD_WIDTH / 2); this.PATH_WIDTH_LOWER = (short) Math.floor(this.ROAD_WIDTH / 2f);
} }
if (this.ROAD_WIDTH == 0) { if (this.ROAD_WIDTH == 0) {
this.PATH_WIDTH_UPPER = (short) (this.SIZE + 1); this.PATH_WIDTH_UPPER = (short) (this.SIZE + 1);
@ -250,32 +261,43 @@ public class HybridPlotWorld extends ClassicPlotWorld {
Schematic schematic1 = this.schematicHandler.getSchematic(schematic1File); Schematic schematic1 = this.schematicHandler.getSchematic(schematic1File);
Schematic schematic2 = this.schematicHandler.getSchematic(schematic2File); Schematic schematic2 = this.schematicHandler.getSchematic(schematic2File);
Schematic schematic3 = this.schematicHandler.getSchematic(schematic3File); Schematic schematic3 = this.schematicHandler.getSchematic(schematic3File);
// If the plot schematic contains entities, then they need to be populated upon generation.
if (schematic3 != null && !schematic3.getClipboard().getEntities().isEmpty()) {
this.schem3Entities = new ArrayList<>(schematic3.getClipboard().getEntities());
this.schem3MinPoint = schematic3.getClipboard().getMinimumPoint();
this.schem3PopulationNeeded = true;
}
int shift = this.ROAD_WIDTH / 2; int shift = this.ROAD_WIDTH / 2;
int oddshift = (this.ROAD_WIDTH & 1) == 0 ? 0 : 1; int oddshift = (this.ROAD_WIDTH & 1);
SCHEM_Y = schematicStartHeight(); SCHEM_Y = schematicStartHeight();
int plotY = PLOT_HEIGHT - SCHEM_Y; int plotY = PLOT_HEIGHT - SCHEM_Y;
int minRoadWall = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? Math.min(ROAD_HEIGHT, WALL_HEIGHT) : ROAD_HEIGHT; int minRoadWall = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? Math.min(ROAD_HEIGHT, WALL_HEIGHT) : ROAD_HEIGHT;
int roadY = minRoadWall - SCHEM_Y; int roadY = minRoadWall - SCHEM_Y;
int worldHeight = getMaxGenHeight() - getMinGenHeight() + 1;
// SCHEM_Y should be normalised to the plot "start" height
if (schematic3 != null) { if (schematic3 != null) {
if (schematic3.getClipboard().getDimensions().getY() == 256) { if (schematic3.getClipboard().getDimensions().getY() == worldHeight) {
SCHEM_Y = plotY = 0; SCHEM_Y = plotY = 0;
} else if (!Settings.Schematics.PASTE_ON_TOP) { } else if (!Settings.Schematics.PASTE_ON_TOP) {
SCHEM_Y = plotY = getMinBuildHeight(); SCHEM_Y = plotY = getMinBuildHeight() - getMinGenHeight();
} }
} }
if (schematic1 != null) { if (schematic1 != null) {
if (schematic1.getClipboard().getDimensions().getY() == 256) { if (schematic1.getClipboard().getDimensions().getY() == worldHeight) {
SCHEM_Y = roadY = 0; SCHEM_Y = roadY = getMinGenHeight();
if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != 256 if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldHeight
&& !Settings.Schematics.PASTE_ON_TOP) { && !Settings.Schematics.PASTE_ON_TOP) {
plotY = PLOT_HEIGHT; plotY = PLOT_HEIGHT;
} }
} else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) { } else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) {
SCHEM_Y = roadY = getMinBuildHeight(); SCHEM_Y = roadY = getMinBuildHeight();
if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != 256 if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldHeight
&& !Settings.Schematics.PASTE_ON_TOP) { && !Settings.Schematics.PASTE_ON_TOP) {
plotY = PLOT_HEIGHT; plotY = PLOT_HEIGHT;
} }
@ -310,24 +332,34 @@ public class HybridPlotWorld extends ClassicPlotWorld {
for (short x = 0; x < w3; x++) { for (short x = 0; x < w3; x++) {
for (short z = 0; z < l3; z++) { for (short z = 0; z < l3; z++) {
for (short y = 0; y < h3; y++) { for (short y = 0; y < h3; y++) {
BaseBlock id = BaseBlock id = blockArrayClipboard3.getFullBlock(BlockVector3.at(
blockArrayClipboard3.getFullBlock(BlockVector3.at( x + min.getBlockX(),
x + min.getBlockX(), y + min.getBlockY(),
y + min.getBlockY(), z + min.getBlockZ()
z + min.getBlockZ() ));
));
if (!id.getBlockType().getMaterial().isAir()) { if (!id.getBlockType().getMaterial().isAir()) {
addOverlayBlock((short) (x + shift + oddshift + centerShiftX), (short) (y + plotY), schem3PopulationNeeded |= id.hasNbtData();
(short) (z + shift + oddshift + centerShiftZ), id, false, h3 addOverlayBlock(
(short) (x + shift + oddshift + centerShiftX),
(short) (y + plotY),
(short) (z + shift + oddshift + centerShiftZ),
id,
false,
h3
); );
} }
} }
BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); if (blockArrayClipboard3.hasBiomes()) {
addOverlayBiome( BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at(
(short) (x + shift + oddshift + centerShiftX), x + min.getBlockX(),
(short) (z + shift + oddshift + centerShiftZ), z + min.getBlockZ()
biome ));
); addOverlayBiome(
(short) (x + shift + oddshift + centerShiftX),
(short) (z + shift + oddshift + centerShiftZ),
biome
);
}
} }
} }
@ -335,7 +367,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
LOGGER.info("- plot schematic: {}", schematic3File.getPath()); LOGGER.info("- plot schematic: {}", schematic3File.getPath());
} }
} }
if ((schematic1 == null&& schematic2 == null) || this.ROAD_WIDTH == 0) { if ((schematic1 == null && schematic2 == null) || this.ROAD_WIDTH == 0) {
if (Settings.DEBUG) { if (Settings.DEBUG) {
LOGGER.info("- schematic: false"); LOGGER.info("- schematic: false");
} }
@ -366,6 +398,7 @@ public class HybridPlotWorld extends ClassicPlotWorld {
z + min.getBlockZ() z + min.getBlockZ()
)); ));
if (!id.getBlockType().getMaterial().isAir()) { if (!id.getBlockType().getMaterial().isAir()) {
schem1PopulationNeeded |= id.hasNbtData();
addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z + shift + oddshift), id, false, h1); addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z + shift + oddshift), id, false, h1);
addOverlayBlock( addOverlayBlock(
(short) (z + shift + oddshift), (short) (z + shift + oddshift),
@ -377,9 +410,11 @@ public class HybridPlotWorld extends ClassicPlotWorld {
); );
} }
} }
BiomeType biome = blockArrayClipboard1.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); if (blockArrayClipboard1.hasBiomes()) {
addOverlayBiome((short) (x - shift), (short) (z + shift + oddshift), biome); BiomeType biome = blockArrayClipboard1.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (z + shift + oddshift), (short) (shift - x + (oddshift - 1)), biome); addOverlayBiome((short) (x - shift), (short) (z + shift + oddshift), biome);
addOverlayBiome((short) (z + shift + oddshift), (short) (shift - x + (oddshift - 1)), biome);
}
} }
} }
@ -402,11 +437,14 @@ public class HybridPlotWorld extends ClassicPlotWorld {
z + min.getBlockZ() z + min.getBlockZ()
)); ));
if (!id.getBlockType().getMaterial().isAir()) { if (!id.getBlockType().getMaterial().isAir()) {
schem2PopulationNeeded |= id.hasNbtData();
addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z - shift), id, false, h2); addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z - shift), id, false, h2);
} }
} }
BiomeType biome = blockArrayClipboard2.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); if (blockArrayClipboard2.hasBiomes()) {
addOverlayBiome((short) (x - shift), (short) (z - shift), biome); BiomeType biome = blockArrayClipboard2.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ()));
addOverlayBiome((short) (x - shift), (short) (z - shift), biome);
}
} }
} }
} }
@ -428,7 +466,10 @@ public class HybridPlotWorld extends ClassicPlotWorld {
int pair = MathMan.pair(x, z); int pair = MathMan.pair(x, z);
BaseBlock[] existing = this.G_SCH.computeIfAbsent(pair, k -> new BaseBlock[height]); BaseBlock[] existing = this.G_SCH.computeIfAbsent(pair, k -> new BaseBlock[height]);
if (y >= height) { if (y >= height) {
LOGGER.error("Error adding overlay block. `y > height`"); if (y != lastOverlayHeightError) {
lastOverlayHeightError = y;
LOGGER.error(String.format("Error adding overlay block. `y > height`. y=%s, height=%s", y, height));
}
return; return;
} }
existing[y] = id; existing[y] = id;
@ -449,8 +490,52 @@ public class HybridPlotWorld extends ClassicPlotWorld {
this.G_SCH_B.put(pair, id); this.G_SCH_B.put(pair, id);
} }
/**
* Get the entities contained within the plot schematic for generation. Intended for internal use only.
*
* @since TODO
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public @Nullable List<Entity> getPlotSchematicEntities() {
return schem3Entities;
}
/**
* Get the minimum point of the plot schematic for generation. Intended for internal use only.
*
* @since TODO
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public @Nullable BlockVector3 getPlotSchematicMinPoint() {
return schem3MinPoint;
}
/**
* Get if post-generation population of chunks with tiles/entities is needed for this world. Not for public API use.
*
* @since TODO
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public boolean populationNeeded() {
return schem1PopulationNeeded || schem2PopulationNeeded || schem3PopulationNeeded;
}
/**
* @deprecated in favour of {@link HybridPlotWorld#getSchematicRoot()}
*/
@Deprecated(forRemoval = true, since = "TODO")
public File getRoot() { public File getRoot() {
return this.root; return this.root;
} }
/**
* Get the root folder for this world's generation schematics. May be null if schematics not initialised via
* {@link HybridPlotWorld#setupSchematics()}
*
* @since TODO
*/
public @Nullable File getSchematicRoot() {
return this.root;
}
} }

View File

@ -41,7 +41,7 @@ import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.AnalysisFlag; import com.plotsquared.core.plot.flag.implementations.AnalysisFlag;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.ChunkQueueCoordinator; import com.plotsquared.core.queue.BlockArrayCacheScopedQueueCoordinator;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
@ -65,6 +65,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.File; import java.io.File;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -73,6 +74,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -81,11 +83,14 @@ import java.util.concurrent.atomic.AtomicInteger;
public class HybridUtils { public class HybridUtils {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + HybridUtils.class.getSimpleName()); private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + HybridUtils.class.getSimpleName());
private static final BlockState AIR = BlockTypes.AIR.getDefaultState();
public static HybridUtils manager; public static HybridUtils manager;
public static Set<BlockVector2> regions; public static Set<BlockVector2> regions;
public static int height; public static int height;
public static Set<BlockVector2> chunks = new HashSet<>(); // Use ordered for reasonable chunk loading order to reduce paper unloading neighbour chunks and then us attempting to load
// them again, causing errors
public static Set<BlockVector2> chunks = new LinkedHashSet<>();
public static PlotArea area; public static PlotArea area;
public static boolean UPDATE = false; public static boolean UPDATE = false;
@ -132,6 +137,11 @@ public class HybridUtils {
* *
*/ */
TaskManager.runTaskAsync(() -> { TaskManager.runTaskAsync(() -> {
final PlotArea area = this.plotAreaManager.getPlotArea(world, null);
if (!(area instanceof HybridPlotWorld hpw)) {
return;
}
final BlockVector3 bot = region.getMinimumPoint(); final BlockVector3 bot = region.getMinimumPoint();
final BlockVector3 top = region.getMaximumPoint(); final BlockVector3 top = region.getMaximumPoint();
@ -145,38 +155,31 @@ public class HybridUtils {
final int ctz = tz >> 4; final int ctz = tz >> 4;
final int width = tx - bx + 1; final int width = tx - bx + 1;
final int length = tz - bz + 1; final int length = tz - bz + 1;
final int height = area.getMaxGenHeight() - area.getMinGenHeight() + 1;
final int minHeight = area.getMinGenHeight();
final PlotArea area = this.plotAreaManager.getPlotArea(world, null); final BlockState[][][] newBlocks = new BlockState[height][width][length];
if (!(area instanceof HybridPlotWorld hpw)) { BlockArrayCacheScopedQueueCoordinator oldBlockQueue = new BlockArrayCacheScopedQueueCoordinator(
return; Location.at("", region.getMinimumPoint().withY(hpw.getMinGenHeight())),
} Location.at("", region.getMaximumPoint().withY(hpw.getMaxGenHeight()))
);
ChunkQueueCoordinator chunk = new ChunkQueueCoordinator(worldUtil.getWeWorld(world), bot, top, false); region.getChunks().forEach(chunkPos -> {
hpw.getGenerator().generateChunk(chunk, hpw); int relChunkX = chunkPos.getX() - cbx;
int relChunkZ = chunkPos.getZ() - cbz;
oldBlockQueue.setOffsetX(relChunkX << 4);
oldBlockQueue.setOffsetZ(relChunkZ << 4);
hpw.getGenerator().generateChunk(oldBlockQueue, hpw);
});
final BlockState airBlock = BlockTypes.AIR.getDefaultState(); final BlockState[][][] oldBlocks = oldBlockQueue.getBlockStates();
final BlockState[][][] oldBlocks = chunk.getBlocks();
final BlockState[][][] newBlocks = new BlockState[256][width][length];
for (final BlockState[][] newBlock : newBlocks) {
for (final BlockState[] blockStates : newBlock) {
Arrays.fill(blockStates, airBlock);
}
}
for (final BlockState[][] oldBlock : oldBlocks) {
for (final BlockState[] blockStates : oldBlock) {
Arrays.fill(blockStates, airBlock);
}
}
System.gc();
System.gc();
QueueCoordinator queue = area.getQueue(); QueueCoordinator queue = area.getQueue();
queue.addReadChunks(region.getChunks()); queue.addReadChunks(region.getChunks());
queue.setChunkConsumer(blockVector2 -> { queue.setChunkConsumer(chunkPos -> {
int X = blockVector2.getX(); int X = chunkPos.getX();
int Z = blockVector2.getZ(); int Z = chunkPos.getZ();
int minX; int minX;
if (X == cbx) { if (X == cbx) {
minX = bx & 15; minX = bx & 15;
@ -211,11 +214,15 @@ public class HybridUtils {
int xx = chunkBlockX + x; int xx = chunkBlockX + x;
for (int z = minZ; z <= maxZ; z++) { for (int z = minZ; z <= maxZ; z++) {
int zz = chunkBlockZ + z; int zz = chunkBlockZ + z;
for (int y = 0; y < 256; y++) { for (int yIndex = 0; yIndex < height; yIndex++) {
int y = yIndex + minHeight;
BlockState block = queue.getBlock(xx, y, zz); BlockState block = queue.getBlock(xx, y, zz);
if (block == null) {
block = AIR;
}
int xr = xb + x; int xr = xb + x;
int zr = zb + z; int zr = zb + z;
newBlocks[y][xr][zr] = block; newBlocks[yIndex][xr][zr] = block;
} }
} }
} }
@ -232,11 +239,11 @@ public class HybridUtils {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
Set<BlockType> types = new HashSet<>(); Set<BlockType> types = new HashSet<>();
for (int y = 0; y < 256; y++) { for (int yIndex = 0; yIndex < height; yIndex++) {
BlockState old = oldBlocks[y][x][z]; BlockState old = oldBlocks[yIndex][x][z]; // Nullable
try { try {
BlockState now = newBlocks[y][x][z]; BlockState now = newBlocks[yIndex][x][z]; // Not null
if (!old.equals(now)) { if (!now.equals(old) && !(old == null && now.getBlockType().equals(BlockTypes.AIR))) {
changes[i]++; changes[i]++;
} }
if (now.getBlockType().getMaterial().isAir()) { if (now.getBlockType().getMaterial().isAir()) {
@ -244,23 +251,23 @@ public class HybridUtils {
} else { } else {
// check vertices // check vertices
// modifications_adjacent // modifications_adjacent
if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1 && y < 255) { if (x > 0 && z > 0 && yIndex > 0 && x < width - 1 && z < length - 1 && yIndex < (height - 1)) {
if (newBlocks[y - 1][x][z].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex - 1][x][z].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
if (newBlocks[y][x - 1][z].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex][x - 1][z].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
if (newBlocks[y][x][z - 1].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex][x][z - 1].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
if (newBlocks[y + 1][x][z].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex + 1][x][z].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
if (newBlocks[y][x + 1][z].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex][x + 1][z].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
if (newBlocks[y][x][z + 1].getBlockType().getMaterial().isAir()) { if (newBlocks[yIndex][x][z + 1].getBlockType().getMaterial().isAir()) {
faces[i]++; faces[i]++;
} }
} }
@ -294,8 +301,6 @@ public class HybridUtils {
analysis.data_sd = (int) (MathMan.getSD(data, analysis.data) * 100); analysis.data_sd = (int) (MathMan.getSD(data, analysis.data) * 100);
analysis.air_sd = (int) (MathMan.getSD(air, analysis.air) * 100); analysis.air_sd = (int) (MathMan.getSD(air, analysis.air) * 100);
analysis.variety_sd = (int) (MathMan.getSD(variety, analysis.variety) * 100); analysis.variety_sd = (int) (MathMan.getSD(variety, analysis.variety) * 100);
System.gc();
System.gc();
whenDone.value = analysis; whenDone.value = analysis;
whenDone.run(); whenDone.run();
}); });
@ -408,7 +413,7 @@ public class HybridUtils {
} }
HybridUtils.UPDATE = true; HybridUtils.UPDATE = true;
Set<BlockVector2> regions = this.worldUtil.getChunkChunks(area.getWorldName()); Set<BlockVector2> regions = this.worldUtil.getChunkChunks(area.getWorldName());
return scheduleRoadUpdate(area, regions, extend, new HashSet<>()); return scheduleRoadUpdate(area, regions, extend, new LinkedHashSet<>());
} }
public boolean scheduleSingleRegionRoadUpdate(Plot plot, int extend) { public boolean scheduleSingleRegionRoadUpdate(Plot plot, int extend) {
@ -418,7 +423,7 @@ public class HybridUtils {
HybridUtils.UPDATE = true; HybridUtils.UPDATE = true;
Set<BlockVector2> regions = new HashSet<>(); Set<BlockVector2> regions = new HashSet<>();
regions.add(RegionManager.getRegion(plot.getCenterSynchronous())); regions.add(RegionManager.getRegion(plot.getCenterSynchronous()));
return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>()); return scheduleRoadUpdate(plot.getArea(), regions, extend, new LinkedHashSet<>());
} }
public boolean scheduleRoadUpdate( public boolean scheduleRoadUpdate(
@ -431,26 +436,29 @@ public class HybridUtils {
HybridUtils.area = area; HybridUtils.area = area;
HybridUtils.height = extend; HybridUtils.height = extend;
HybridUtils.chunks = chunks; HybridUtils.chunks = chunks;
final int initial = 1024 * regions.size() + chunks.size();
final AtomicInteger count = new AtomicInteger(0); final AtomicInteger count = new AtomicInteger(0);
TaskManager.runTask(new Runnable() { TaskManager.runTask(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!UPDATE) { if (!UPDATE) {
Iterator<BlockVector2> iter = chunks.iterator(); Iterator<BlockVector2> iter = chunks.iterator();
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
while (iter.hasNext()) { while (iter.hasNext()) {
BlockVector2 chunk = iter.next(); BlockVector2 chunk = iter.next();
iter.remove(); iter.remove();
boolean regenedRoad = regenerateRoad(area, chunk, extend); boolean regenedRoad = regenerateRoad(area, chunk, extend, queue);
if (!regenedRoad) { if (!regenedRoad) {
LOGGER.info("Failed to regenerate roads"); LOGGER.info("Failed to regenerate roads in chunk {}", chunk);
} }
} }
queue.enqueue();
LOGGER.info("Cancelled road task"); LOGGER.info("Cancelled road task");
return; return;
} }
count.incrementAndGet(); count.incrementAndGet();
if (count.intValue() % 20 == 0) { if (count.intValue() % 10 == 0) {
LOGGER.info("Progress: {}%", 100 * (2048 - chunks.size()) / 2048); LOGGER.info("Progress: {}%", 100 * (initial - (chunks.size() + 1024 * regions.size())) / initial);
} }
if (HybridUtils.regions.isEmpty() && chunks.isEmpty()) { if (HybridUtils.regions.isEmpty() && chunks.isEmpty()) {
regeneratePlotWalls(area); regeneratePlotWalls(area);
@ -462,7 +470,7 @@ public class HybridUtils {
final Runnable task = this; final Runnable task = this;
TaskManager.runTaskAsync(() -> { TaskManager.runTaskAsync(() -> {
try { try {
if (chunks.size() < 1024) { if (chunks.size() < 64) {
if (!HybridUtils.regions.isEmpty()) { if (!HybridUtils.regions.isEmpty()) {
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator(); Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
BlockVector2 loc = iterator.next(); BlockVector2 loc = iterator.next();
@ -475,18 +483,35 @@ public class HybridUtils {
} }
if (!chunks.isEmpty()) { if (!chunks.isEmpty()) {
TaskManager.getPlatformImplementation().sync(() -> { TaskManager.getPlatformImplementation().sync(() -> {
long start = System.currentTimeMillis();
Iterator<BlockVector2> iterator = chunks.iterator(); Iterator<BlockVector2> iterator = chunks.iterator();
while (System.currentTimeMillis() - start < 20 && !chunks.isEmpty()) { if (chunks.size() >= 32) {
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
for (int i = 0; i < 32; i++) {
final BlockVector2 chunk = iterator.next();
iterator.remove();
boolean regenedRoads = regenerateRoad(area, chunk, extend, queue);
if (!regenedRoads) {
LOGGER.info("Failed to regenerate the road in chunk {}", chunk);
}
}
queue.setCompleteTask(task);
queue.enqueue();
return null;
}
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
while (!chunks.isEmpty()) {
final BlockVector2 chunk = iterator.next(); final BlockVector2 chunk = iterator.next();
iterator.remove(); iterator.remove();
boolean regenedRoads = regenerateRoad(area, chunk, extend); boolean regenedRoads = regenerateRoad(area, chunk, extend, queue);
if (!regenedRoads) { if (!regenedRoads) {
LOGGER.info("Failed to regenerate road"); LOGGER.info("Failed to regenerate road in chunk {}", chunk);
} }
} }
queue.setCompleteTask(task);
queue.enqueue();
return null; return null;
}); });
return;
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -514,7 +539,6 @@ public class HybridUtils {
Location bot = plot.getBottomAbs().subtract(1, 0, 1); Location bot = plot.getBottomAbs().subtract(1, 0, 1);
Location top = plot.getTopAbs(); Location top = plot.getTopAbs();
final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea(); final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea();
PlotManager plotManager = plotworld.getPlotManager();
// Do not use plotworld#schematicStartHeight() here as we want to restore the pre 6.1.4 way of doing it if // Do not use plotworld#schematicStartHeight() here as we want to restore the pre 6.1.4 way of doing it if
// USE_WALL_IN_ROAD_SCHEM_HEIGHT is false // USE_WALL_IN_ROAD_SCHEM_HEIGHT is false
int schemY = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? int schemY = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ?
@ -524,10 +548,10 @@ public class HybridUtils {
int sy = Settings.Schematics.PASTE_ROAD_ON_TOP ? schemY : plot.getArea().getMinBuildHeight(); int sy = Settings.Schematics.PASTE_ROAD_ON_TOP ? schemY : plot.getArea().getMinBuildHeight();
int ex = bot.getX(); int ex = bot.getX();
int ez = top.getZ(); int ez = top.getZ();
int ey = get_ey(plotManager, queue, sx, ex, sz, ez, sy); int ey = get_ey(plotworld, queue, sx, ex, sz, ez, sy);
int bz = sz - plotworld.ROAD_WIDTH; int bz = sz - plotworld.ROAD_WIDTH;
int tz = sz - 1; int tz = sz - 1;
int ty = get_ey(plotManager, queue, sx, ex, bz, tz, sy); int ty = get_ey(plotworld, queue, sx, ex, bz, tz, sy);
final Set<CuboidRegion> sideRoad = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)); final Set<CuboidRegion> sideRoad = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez));
final Set<CuboidRegion> intersection = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz)); final Set<CuboidRegion> intersection = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz));
@ -553,11 +577,11 @@ public class HybridUtils {
return true; return true;
} }
public int get_ey(final PlotManager pm, QueueCoordinator queue, int sx, int ex, int sz, int ez, int sy) { private int get_ey(final HybridPlotWorld hpw, QueueCoordinator queue, int sx, int ex, int sz, int ez, int sy) {
int ey = sy; int ey = sy;
for (int x = sx; x <= ex; x++) { for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) { for (int z = sz; z <= ez; z++) {
for (int y = sy; y <= pm.getWorldHeight(); y++) { for (int y = sy; y <= hpw.getMaxGenHeight(); y++) {
if (y > ey) { if (y > ey) {
BlockState block = queue.getBlock(x, y, z); BlockState block = queue.getBlock(x, y, z);
if (!block.getBlockType().getMaterial().isAir()) { if (!block.getBlockType().getMaterial().isAir()) {
@ -570,7 +594,36 @@ public class HybridUtils {
return ey; return ey;
} }
/**
* Regenerate the road in a chunk in a plot area.
*
* @param area Plot area to regenerate road for
* @param chunk Chunk location to regenerate
* @param extend How far to extend setting air above the road
* @return if successful
* @deprecated use {@link HybridUtils#regenerateRoad(PlotArea, BlockVector2, int, QueueCoordinator)}
*/
@Deprecated(forRemoval = true, since = "6.6.0")
public boolean regenerateRoad(final PlotArea area, final BlockVector2 chunk, int extend) { public boolean regenerateRoad(final PlotArea area, final BlockVector2 chunk, int extend) {
return regenerateRoad(area, chunk, extend, null);
}
/**
* Regenerate the road in a chunk in a plot area.
*
* @param area Plot area to regenerate road for
* @param chunk Chunk location to regenerate
* @param extend How far to extend setting air above the road
* @param queueCoordinator {@link QueueCoordinator} to use to set the blocks. Null if one should be created and enqueued
* @return if successful
* @since 6.6.0
*/
public boolean regenerateRoad(
final PlotArea area,
final BlockVector2 chunk,
int extend,
@Nullable QueueCoordinator queueCoordinator
) {
int x = chunk.getX() << 4; int x = chunk.getX() << 4;
int z = chunk.getZ() << 4; int z = chunk.getZ() << 4;
int ex = x + 15; int ex = x + 15;
@ -596,92 +649,100 @@ public class HybridUtils {
z -= plotWorld.ROAD_OFFSET_Z; z -= plotWorld.ROAD_OFFSET_Z;
final int finalX = x; final int finalX = x;
final int finalZ = z; final int finalZ = z;
QueueCoordinator queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(plotWorld.getWorldName())); final boolean enqueue;
final QueueCoordinator queue;
if (queueCoordinator == null) {
queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(plotWorld.getWorldName()));
enqueue = true;
} else {
queue = queueCoordinator;
enqueue = false;
}
if (id1 == null || id2 == null || id1 != id2) { if (id1 == null || id2 == null || id1 != id2) {
this.chunkManager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { if (id1 != null) {
if (id1 != null) { Plot p1 = area.getPlotAbs(id1);
Plot p1 = area.getPlotAbs(id1); if (p1 != null && p1.hasOwner() && p1.isMerged()) {
if (p1 != null && p1.hasOwner() && p1.isMerged()) { toCheck.set(true);
toCheck.set(true);
}
} }
if (id2 != null && !toCheck.get()) { }
Plot p2 = area.getPlotAbs(id2); if (id2 != null && !toCheck.get()) {
if (p2 != null && p2.hasOwner() && p2.isMerged()) { Plot p2 = area.getPlotAbs(id2);
toCheck.set(true); if (p2 != null && p2.hasOwner() && p2.isMerged()) {
} toCheck.set(true);
} }
int size = plotWorld.SIZE; }
for (int X = 0; X < 16; X++) { short size = plotWorld.SIZE;
short absX = (short) ((finalX + X) % size); for (int X = 0; X < 16; X++) {
for (int Z = 0; Z < 16; Z++) { short absX = (short) ((finalX + X) % size);
short absZ = (short) ((finalZ + Z) % size); for (int Z = 0; Z < 16; Z++) {
if (absX < 0) { short absZ = (short) ((finalZ + Z) % size);
absX += size; if (absX < 0) {
} absX += size;
if (absZ < 0) { }
absZ += size; if (absZ < 0) {
} absZ += size;
boolean condition; }
if (toCheck.get()) { boolean condition;
condition = manager.getPlotId( if (toCheck.get()) {
finalX + X + plotWorld.ROAD_OFFSET_X, condition = manager.getPlotId(
1, finalX + X + plotWorld.ROAD_OFFSET_X,
finalZ + Z + plotWorld.ROAD_OFFSET_Z 1,
) == null; finalZ + Z + plotWorld.ROAD_OFFSET_Z
} else { ) == null;
boolean gx = absX > plotWorld.PATH_WIDTH_LOWER; } else {
boolean gz = absZ > plotWorld.PATH_WIDTH_LOWER; boolean gx = absX > plotWorld.PATH_WIDTH_LOWER;
boolean lx = absX < plotWorld.PATH_WIDTH_UPPER; boolean gz = absZ > plotWorld.PATH_WIDTH_LOWER;
boolean lz = absZ < plotWorld.PATH_WIDTH_UPPER; boolean lx = absX < plotWorld.PATH_WIDTH_UPPER;
condition = !gx || !gz || !lx || !lz; boolean lz = absZ < plotWorld.PATH_WIDTH_UPPER;
} condition = !gx || !gz || !lx || !lz;
if (condition) { }
BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ)); if (condition) {
int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : 1; BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ));
int maxY = Math.max(extend, blocks.length); int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : area.getMinGenHeight() + 1;
for (int y = 0; y < maxY; y++) { int maxDy = Math.max(extend, blocks.length);
if (y > blocks.length - 1) { for (int dy = 0; dy < maxDy; dy++) {
if (dy > blocks.length - 1) {
queue.setBlock(
finalX + X + plotWorld.ROAD_OFFSET_X,
minY + dy,
finalZ + Z + plotWorld.ROAD_OFFSET_Z,
WEExtent.AIRBASE
);
} else {
BaseBlock block = blocks[dy];
if (block != null) {
queue.setBlock( queue.setBlock(
finalX + X + plotWorld.ROAD_OFFSET_X, finalX + X + plotWorld.ROAD_OFFSET_X,
minY + y, minY + dy,
finalZ + Z + plotWorld.ROAD_OFFSET_Z,
block
);
} else {
queue.setBlock(
finalX + X + plotWorld.ROAD_OFFSET_X,
minY + dy,
finalZ + Z + plotWorld.ROAD_OFFSET_Z, finalZ + Z + plotWorld.ROAD_OFFSET_Z,
WEExtent.AIRBASE WEExtent.AIRBASE
); );
} else {
BaseBlock block = blocks[y];
if (block != null) {
queue.setBlock(
finalX + X + plotWorld.ROAD_OFFSET_X,
minY + y,
finalZ + Z + plotWorld.ROAD_OFFSET_Z,
block
);
} else {
queue.setBlock(
finalX + X + plotWorld.ROAD_OFFSET_X,
minY + y,
finalZ + Z + plotWorld.ROAD_OFFSET_Z,
WEExtent.AIRBASE
);
}
} }
} }
BiomeType biome = plotWorld.G_SCH_B.get(MathMan.pair(absX, absZ)); }
if (biome != null) { BiomeType biome = plotWorld.G_SCH_B.get(MathMan.pair(absX, absZ));
queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X, finalZ + Z + plotWorld.ROAD_OFFSET_Z, biome); if (biome != null) {
} else { queue.setBiome(finalX + X + plotWorld.ROAD_OFFSET_X, finalZ + Z + plotWorld.ROAD_OFFSET_Z, biome);
queue.setBiome( } else {
finalX + X + plotWorld.ROAD_OFFSET_X, queue.setBiome(
finalZ + Z + plotWorld.ROAD_OFFSET_Z, finalX + X + plotWorld.ROAD_OFFSET_X,
plotWorld.getPlotBiome() finalZ + Z + plotWorld.ROAD_OFFSET_Z,
); plotWorld.getPlotBiome()
} );
} }
} }
} }
}
if (enqueue) {
queue.enqueue(); queue.enqueue();
}); }
return true; return true;
} }
return false; return false;

View File

@ -47,16 +47,25 @@ public abstract class IndependentPlotGenerator {
public abstract String getName(); public abstract String getName();
/** /**
* Use the setBlock or setBiome method of the PlotChunk result parameter to make changes. * Generate chunk block data
* The PlotArea settings is the same one this was initialized with.
* The PseudoRandom random is a fast random object.
* *
* @param result queue * @param result queue
* @param settings PlotArea (settings) * @param settings PlotArea (settings)
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/ */
@Deprecated(forRemoval = true, since = "TODO")
public abstract void generateChunk(ScopedQueueCoordinator result, PlotArea settings); public abstract void generateChunk(ScopedQueueCoordinator result, PlotArea settings);
public boolean populateChunk(ScopedQueueCoordinator result, PlotArea setting) { /**
* Populates the queue representing a chunk area with tile entities and entities
*
* @param result Queue to write to
* @param settings PlotArea (settings)
* @return True if any population occurred
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/
@Deprecated(forRemoval = true, since = "TODO")
public boolean populateChunk(ScopedQueueCoordinator result, PlotArea settings) {
return false; return false;
} }

View File

@ -96,7 +96,7 @@ public abstract class SquarePlotManager extends GridPlotManager {
.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1; .floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - (int) Math int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - (int) Math
.floor(squarePlotWorld.ROAD_WIDTH / 2) - 1; .floor(squarePlotWorld.ROAD_WIDTH / 2) - 1;
return Location.at(squarePlotWorld.getWorldName(), x, Math.min(getWorldHeight(), 255), z); return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMaxGenHeight(), z);
} }
@Override @Override
@ -260,7 +260,7 @@ public abstract class SquarePlotManager extends GridPlotManager {
- (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2); - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2);
int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH
- (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2); - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2);
return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMinBuildHeight(), z); return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMinGenHeight(), z);
} }
} }

View File

@ -309,7 +309,7 @@ public class PlotListener {
} }
if ((lastPlot != null) && plot.getId().equals(lastPlot.getId()) && plot.hasOwner()) { if ((lastPlot != null) && plot.getId().equals(lastPlot.getId()) && plot.hasOwner()) {
final UUID plotOwner = plot.getOwnerAbs(); final UUID plotOwner = plot.getOwnerAbs();
String owner = PlayerManager.resolveName(plotOwner, false).getComponent(player); String owner = PlayerManager.resolveName(plotOwner, true).getComponent(player);
Caption header = fromFlag ? StaticCaption.of(title) : TranslatableCaption.of("titles" + Caption header = fromFlag ? StaticCaption.of(title) : TranslatableCaption.of("titles" +
".title_entered_plot"); ".title_entered_plot");
Caption subHeader = fromFlag ? StaticCaption.of(subtitle) : TranslatableCaption.of("titles" + Caption subHeader = fromFlag ? StaticCaption.of(subtitle) : TranslatableCaption.of("titles" +

View File

@ -35,6 +35,7 @@ import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
import com.plotsquared.core.util.WEManager; import com.plotsquared.core.util.WEManager;
import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.WorldUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.event.extent.EditSessionEvent;
@ -67,6 +68,9 @@ public class WESubscriber {
WorldEdit.getInstance().getEventBus().unregister(this); WorldEdit.getInstance().getEventBus().unregister(this);
return; return;
} }
if (event.getStage() != EditSession.Stage.BEFORE_HISTORY) {
return;
}
World worldObj = event.getWorld(); World worldObj = event.getWorld();
if (worldObj == null) { if (worldObj == null) {
return; return;

View File

@ -41,14 +41,17 @@ import org.khelekore.prtree.SimpleMBR;
* An unmodifiable 6-tuple (world,x,y,z,yaw,pitch) * An unmodifiable 6-tuple (world,x,y,z,yaw,pitch)
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Location extends BlockLoc implements Comparable<Location> { public sealed class Location extends BlockLoc implements Comparable<Location> permits UncheckedWorldLocation {
private final float yaw; private final float yaw;
private final float pitch; private final float pitch;
private final BlockVector3 blockVector3; private final BlockVector3 blockVector3;
private final World<?> world; private final World<?> world;
private Location( /**
* @since TODO
*/
protected Location(
final @NonNull World<?> world, final @NonNull BlockVector3 blockVector3, final @NonNull World<?> world, final @NonNull BlockVector3 blockVector3,
final float yaw, final float pitch final float yaw, final float pitch
) { ) {

View File

@ -0,0 +1,77 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2014 - 2022 IntellectualSites
*
* 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.plotsquared.core.location;
import com.plotsquared.core.util.AnnotationHelper;
import com.sk89q.worldedit.math.BlockVector3;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Used internally for generation to reference locations in worlds that "don't exist yet". There is no guarantee that the world
* name provided by {@link UncheckedWorldLocation#getWorldName()} exists on the server.
*
* @since TODO
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public final class UncheckedWorldLocation extends Location {
private final String worldName;
/**
* @since TODO
*/
private UncheckedWorldLocation(
final @NonNull String worldName, final int x, final int y, final int z
) {
super(World.nullWorld(), BlockVector3.at(x, y, z), 0f, 0f);
this.worldName = worldName;
}
/**
* Construct a new location with yaw and pitch equal to 0
*
* @param world World
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @return New location
*
* @since TODO
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public static @NonNull UncheckedWorldLocation at(
final @NonNull String world, final int x, final int y, final int z
) {
return new UncheckedWorldLocation(world, x, y, z);
}
@Override
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.")
public @NonNull String getWorldName() {
return this.worldName;
}
}

View File

@ -58,6 +58,21 @@ public interface World<T> {
*/ */
@NonNull String getName(); @NonNull String getName();
/**
* Get the min world height. Inclusive.
*
* @since 6.6.0
*/
int getMinHeight();
/**
* Get the max world height. Inclusive.
*
* @since 6.6.0
*/
int getMaxHeight();
class NullWorld<T> implements World<T> { class NullWorld<T> implements World<T> {
private NullWorld() { private NullWorld() {
@ -74,6 +89,16 @@ public interface World<T> {
return ""; return "";
} }
@Override
public int getMinHeight() {
return 0;
}
@Override
public int getMaxHeight() {
return 0;
}
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
return obj instanceof NullWorld; return obj instanceof NullWorld;

View File

@ -122,7 +122,7 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE;
*/ */
public class Plot { public class Plot {
@Deprecated(forRemoval = true, since = "6.6.0")
public static final int MAX_HEIGHT = 256; public static final int MAX_HEIGHT = 256;
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Plot.class.getSimpleName()); private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Plot.class.getSimpleName());
@ -1371,7 +1371,7 @@ public class Plot {
int z = largest.getMinimumPoint().getZ() - 1; int z = largest.getMinimumPoint().getZ() - 1;
PlotManager manager = getManager(); PlotManager manager = getManager();
int y = isLoaded() ? this.worldUtil.getHighestBlockSynchronous(getWorldName(), x, z) : 62; int y = isLoaded() ? this.worldUtil.getHighestBlockSynchronous(getWorldName(), x, z) : 62;
if (area.allowSigns() && (y <= 0 || y >= 255)) { if (area.allowSigns() && (y <= area.getMinGenHeight() || y >= area.getMaxGenHeight())) {
y = Math.max(y, manager.getSignLoc(this).getY() - 1); y = Math.max(y, manager.getSignLoc(this).getY() - 1);
} }
return Location.at(getWorldName(), x, y + 1, z); return Location.at(getWorldName(), x, y + 1, z);
@ -1387,7 +1387,7 @@ public class Plot {
if (isLoaded()) { if (isLoaded()) {
this.worldUtil.getHighestBlock(getWorldName(), x, z, y -> { this.worldUtil.getHighestBlock(getWorldName(), x, z, y -> {
int height = y; int height = y;
if (area.allowSigns() && (y <= 0 || y >= 255)) { if (area.allowSigns() && (y <= area.getMinGenHeight() || y >= area.getMaxGenHeight())) {
height = Math.max(y, manager.getSignLoc(this).getY() - 1); height = Math.max(y, manager.getSignLoc(this).getY() - 1);
} }
result.accept(Location.at(getWorldName(), x, height + 1, z)); result.accept(Location.at(getWorldName(), x, height + 1, z));
@ -1420,15 +1420,7 @@ public class Plot {
0 0
); );
} }
Location location = Location Location location = toHomeLocation(bottom, home);
.at(
bottom.getWorldName(),
bottom.getX() + home.getX(),
bottom.getY() + home.getY(),
bottom.getZ() + home.getZ(),
home.getYaw(),
home.getPitch()
);
if (!this.worldUtil.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) { if (!this.worldUtil.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) {
location = location.withY( location = location.withY(
Math.max(1 + this.worldUtil.getHighestBlockSynchronous( Math.max(1 + this.worldUtil.getHighestBlockSynchronous(
@ -1461,15 +1453,7 @@ public class Plot {
return; return;
} }
Location bottom = this.getBottomAbs(); Location bottom = this.getBottomAbs();
Location location = Location Location location = toHomeLocation(bottom, home);
.at(
bottom.getWorldName(),
bottom.getX() + home.getX(),
bottom.getY() + home.getY(),
bottom.getZ() + home.getZ(),
home.getYaw(),
home.getPitch()
);
this.worldUtil.getBlock(location, block -> { this.worldUtil.getBlock(location, block -> {
if (!block.getBlockType().getMaterial().isAir()) { if (!block.getBlockType().getMaterial().isAir()) {
this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(), this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(),
@ -1482,6 +1466,17 @@ public class Plot {
} }
} }
private Location toHomeLocation(Location bottom, BlockLoc relativeHome) {
return Location.at(
bottom.getWorldName(),
bottom.getX() + relativeHome.getX(),
relativeHome.getY(), // y is absolute
bottom.getZ() + relativeHome.getZ(),
relativeHome.getYaw(),
relativeHome.getPitch()
);
}
/** /**
* Sets the home location * Sets the home location
* *
@ -1619,8 +1614,8 @@ public class Plot {
public double getVolume() { public double getVolume() {
double count = 0; double count = 0;
for (CuboidRegion region : getRegions()) { for (CuboidRegion region : getRegions()) {
count += (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * ( // CuboidRegion#getArea is deprecated and we want to ensure use of correct height
region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1) * MAX_HEIGHT; count += region.getLength() * region.getWidth() * (area.getMaxGenHeight() - area.getMinGenHeight() + 1);
} }
return count; return count;
} }
@ -1738,7 +1733,6 @@ public class Plot {
area.addPlot(this); area.addPlot(this);
updateWorldBorder(); updateWorldBorder();
} }
this.getPlotModificationManager().setSign(player.getName());
player.sendMessage(TranslatableCaption.of("working.claimed"), Template.of("plot", this.getId().toString())); player.sendMessage(TranslatableCaption.of("working.claimed"), Template.of("plot", this.getId().toString()));
if (teleport) { if (teleport) {
if (!auto && Settings.Teleport.ON_CLAIM) { if (!auto && Settings.Teleport.ON_CLAIM) {
@ -1786,6 +1780,7 @@ public class Plot {
); );
} }
plotworld.getPlotManager().claimPlot(this, null); plotworld.getPlotManager().claimPlot(this, null);
this.getPlotModificationManager().setSign(player.getName());
return true; return true;
} }
@ -2438,8 +2433,8 @@ public class Plot {
return regions_cache; return regions_cache;
} }
if (!this.isMerged()) { if (!this.isMerged()) {
Location pos1 = this.getBottomAbs(); Location pos1 = this.getBottomAbs().withY(getArea().getMinBuildHeight());
Location pos2 = this.getTopAbs(); Location pos2 = this.getTopAbs().withY(getArea().getMaxBuildHeight());
connected_cache = Sets.newHashSet(this); connected_cache = Sets.newHashSet(this);
CuboidRegion rg = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()); CuboidRegion rg = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3());
regions_cache = Collections.singleton(rg); regions_cache = Collections.singleton(rg);

View File

@ -34,8 +34,6 @@ import com.plotsquared.core.configuration.ConfigurationNode;
import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationSection;
import com.plotsquared.core.configuration.ConfigurationUtil; import com.plotsquared.core.configuration.ConfigurationUtil;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.CaptionUtility;
import com.plotsquared.core.configuration.caption.LocaleHolder;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.configuration.file.YamlConfiguration;
import com.plotsquared.core.generator.GridPlotWorld; import com.plotsquared.core.generator.GridPlotWorld;
@ -54,7 +52,6 @@ import com.plotsquared.core.plot.flag.FlagParseException;
import com.plotsquared.core.plot.flag.GlobalFlagContainer; import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.DoneFlag;
import com.plotsquared.core.plot.flag.types.DoubleFlag;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.QueueCoordinator; import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
@ -144,8 +141,10 @@ public abstract class PlotArea {
private boolean homeAllowNonmember = false; private boolean homeAllowNonmember = false;
private BlockLoc nonmemberHome; private BlockLoc nonmemberHome;
private BlockLoc defaultHome; private BlockLoc defaultHome;
private int maxBuildHeight = 256; private int maxBuildHeight = PlotSquared.platform().versionMaxHeight() + 1; // Exclusive
private int minBuildHeight = 1; private int minBuildHeight = PlotSquared.platform().versionMinHeight() + 1; // Inclusive
private int maxGenHeight = PlotSquared.platform().versionMaxHeight(); // Inclusive
private int minGenHeight = PlotSquared.platform().versionMinHeight(); // Inclusive
private GameMode gameMode = GameModes.CREATIVE; private GameMode gameMode = GameModes.CREATIVE;
private Map<String, PlotExpression> prices = new HashMap<>(); private Map<String, PlotExpression> prices = new HashMap<>();
private List<String> schematics = new ArrayList<>(); private List<String> schematics = new ArrayList<>();
@ -361,6 +360,8 @@ public abstract class PlotArea {
this.worldBorder = config.getBoolean("world.border"); this.worldBorder = config.getBoolean("world.border");
this.maxBuildHeight = config.getInt("world.max_height"); this.maxBuildHeight = config.getInt("world.max_height");
this.minBuildHeight = config.getInt("world.min_height"); this.minBuildHeight = config.getInt("world.min_height");
this.minGenHeight = config.getInt("world.min_gen_height");
this.maxGenHeight = config.getInt("world.max_gen_height");
switch (config.getString("world.gamemode").toLowerCase()) { switch (config.getString("world.gamemode").toLowerCase()) {
case "creative", "c", "1" -> this.gameMode = GameModes.CREATIVE; case "creative", "c", "1" -> this.gameMode = GameModes.CREATIVE;
@ -484,6 +485,8 @@ public abstract class PlotArea {
options.put("home.nonmembers", position); options.put("home.nonmembers", position);
options.put("world.max_height", this.getMaxBuildHeight()); options.put("world.max_height", this.getMaxBuildHeight());
options.put("world.min_height", this.getMinBuildHeight()); options.put("world.min_height", this.getMinBuildHeight());
options.put("world.min_gen_height", this.getMinGenHeight());
options.put("world.max_gen_height", this.getMaxGenHeight());
options.put("world.gamemode", this.getGameMode().getName().toLowerCase()); options.put("world.gamemode", this.getGameMode().getName().toLowerCase());
options.put("road.flags.default", null); options.put("road.flags.default", null);
@ -1078,8 +1081,8 @@ public abstract class PlotArea {
BlockVector2 pos1 = BlockVector2.at(value.getP1().getX(), value.getP1().getY()); BlockVector2 pos1 = BlockVector2.at(value.getP1().getX(), value.getP1().getY());
BlockVector2 pos2 = BlockVector2.at(value.getP2().getX(), value.getP2().getY()); BlockVector2 pos2 = BlockVector2.at(value.getP2().getX(), value.getP2().getY());
return new CuboidRegion( return new CuboidRegion(
pos1.toBlockVector3(), pos1.toBlockVector3(getMinGenHeight()),
pos2.toBlockVector3(Plot.MAX_HEIGHT - 1) pos2.toBlockVector3(getMaxGenHeight())
); );
} }
}; };
@ -1361,14 +1364,38 @@ public abstract class PlotArea {
this.defaultHome = defaultHome; this.defaultHome = defaultHome;
} }
/**
* Get the maximum height players may build in. Exclusive.
*/
public int getMaxBuildHeight() { public int getMaxBuildHeight() {
return this.maxBuildHeight; return this.maxBuildHeight;
} }
/**
* Get the minimum height players may build in. Inclusive.
*/
public int getMinBuildHeight() { public int getMinBuildHeight() {
return this.minBuildHeight; return this.minBuildHeight;
} }
/**
* Get the min height from which P2 will generate blocks. Inclusive.
*
* @since 6.6.0
*/
public int getMinGenHeight() {
return this.minGenHeight;
}
/**
* Get the max height to which P2 will generate blocks. Inclusive.
*
* @since 6.6.0
*/
public int getMaxGenHeight() {
return this.maxGenHeight;
}
public GameMode getGameMode() { public GameMode getGameMode() {
return this.gameMode; return this.gameMode;
} }

View File

@ -89,11 +89,17 @@ public class PlotCluster {
} }
private void setRegion() { private void setRegion() {
this.region = RegionUtil.createRegion(this.pos1.getX(), this.pos2.getX(), this.region = RegionUtil.createRegion(this.pos1.getX(), this.pos2.getX(), 0, 0,
this.pos1.getY(), this.pos2.getY() this.pos1.getY(), this.pos2.getY()
); );
} }
/**
* Returns a region of PlotIDs
*
* @deprecated - returns region of IDs, not of actual blocks.
*/
@Deprecated
public CuboidRegion getRegion() { public CuboidRegion getRegion() {
return this.region; return this.region;
} }
@ -165,7 +171,7 @@ public class PlotCluster {
Consumer<Location> locationConsumer = toReturn -> Consumer<Location> locationConsumer = toReturn ->
PlotSquared.platform().worldUtil().getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(), PlotSquared.platform().worldUtil().getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(),
highest -> { highest -> {
if (highest == 0) { if (highest <= area.getMinBuildHeight()) {
highest = 63; highest = 63;
} }
if (highest > toReturn.getY()) { if (highest > toReturn.getY()) {
@ -175,12 +181,12 @@ public class PlotCluster {
} }
} }
); );
if (home.getY() == 0) { if (home.getY() == Integer.MIN_VALUE) {
// default pos // default pos
Plot center = getCenterPlot(); Plot center = getCenterPlot();
center.getHome(location -> { center.getHome(location -> {
Location toReturn = location; Location toReturn = location;
if (toReturn.getY() == 0) { if (toReturn.getY() <= area.getMinBuildHeight()) {
PlotManager manager = this.area.getPlotManager(); PlotManager manager = this.area.getPlotManager();
Location locationSign = manager.getSignLoc(center); Location locationSign = manager.getSignLoc(center);
toReturn = toReturn.withY(locationSign.getY()); toReturn = toReturn.withY(locationSign.getY());

View File

@ -69,8 +69,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.plotsquared.core.plot.Plot.MAX_HEIGHT;
/** /**
* Manager that handles {@link Plot} modifications * Manager that handles {@link Plot} modifications
*/ */
@ -311,7 +309,7 @@ public final class PlotModificationManager {
return; return;
} }
CuboidRegion region = regions.poll(); CuboidRegion region = regions.poll();
PlotSquared.platform().regionManager().setBiome(region, extendBiome, biome, plot.getWorldName(), this); PlotSquared.platform().regionManager().setBiome(region, extendBiome, biome, plot.getArea(), this);
} }
}; };
run.run(); run.run();
@ -335,10 +333,9 @@ public final class PlotModificationManager {
ids.add(current.getId()); ids.add(current.getId());
} }
this.plot.clearRatings(); this.plot.clearRatings();
QueueCoordinator queue = null; QueueCoordinator queue = this.plot.getArea().getQueue();
if (createSign) { if (createSign) {
this.removeSign(); this.removeSign();
queue = this.plot.getArea().getQueue();
} }
PlotManager manager = this.plot.getArea().getPlotManager(); PlotManager manager = this.plot.getArea().getPlotManager();
if (createRoad) { if (createRoad) {
@ -527,28 +524,6 @@ public final class PlotModificationManager {
return false; return false;
} }
/**
* Remove the south road section of a plot<br>
* - Used when a plot is merged<br>
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public void removeRoadSouth(final @Nullable QueueCoordinator queue) {
if (this.plot.getArea().getType() != PlotAreaType.NORMAL && this.plot
.getArea()
.getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.plot.getRelative(Direction.SOUTH);
Location bot = other.getBottomAbs();
Location top = this.plot.getTopAbs();
Location pos1 = Location.at(this.plot.getWorldName(), bot.getX(), 0, top.getZ());
Location pos2 = Location.at(this.plot.getWorldName(), top.getX(), MAX_HEIGHT, bot.getZ());
PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null);
} else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
this.plot.getManager().removeRoadSouth(this.plot, queue);
}
}
/** /**
* Auto merge a plot in a specific direction. * Auto merge a plot in a specific direction.
* *
@ -915,6 +890,28 @@ public final class PlotModificationManager {
return this.setComponent(component, parsed.toPattern(), actor, queue); return this.setComponent(component, parsed.toPattern(), actor, queue);
} }
/**
* Remove the south road section of a plot<br>
* - Used when a plot is merged<br>
*
* @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues,
* otherwise writes to the queue but does not enqueue.
*/
public void removeRoadSouth(final @Nullable QueueCoordinator queue) {
if (this.plot.getArea().getType() != PlotAreaType.NORMAL && this.plot
.getArea()
.getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.plot.getRelative(Direction.SOUTH);
Location bot = other.getBottomAbs();
Location top = this.plot.getTopAbs();
Location pos1 = Location.at(this.plot.getWorldName(), bot.getX(), plot.getArea().getMinGenHeight(), top.getZ());
Location pos2 = Location.at(this.plot.getWorldName(), top.getX(), plot.getArea().getMaxGenHeight(), bot.getZ());
PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null);
} else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
this.plot.getManager().removeRoadSouth(this.plot, queue);
}
}
/** /**
* Remove the east road section of a plot<br> * Remove the east road section of a plot<br>
* - Used when a plot is merged<br> * - Used when a plot is merged<br>
@ -929,8 +926,8 @@ public final class PlotModificationManager {
Plot other = this.plot.getRelative(Direction.EAST); Plot other = this.plot.getRelative(Direction.EAST);
Location bot = other.getBottomAbs(); Location bot = other.getBottomAbs();
Location top = this.plot.getTopAbs(); Location top = this.plot.getTopAbs();
Location pos1 = Location.at(this.plot.getWorldName(), top.getX(), 0, bot.getZ()); Location pos1 = Location.at(this.plot.getWorldName(), top.getX(), plot.getArea().getMinGenHeight(), bot.getZ());
Location pos2 = Location.at(this.plot.getWorldName(), bot.getX(), MAX_HEIGHT, top.getZ()); Location pos2 = Location.at(this.plot.getWorldName(), bot.getX(), plot.getArea().getMaxGenHeight(), top.getZ());
PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null);
} else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
this.plot.getArea().getPlotManager().removeRoadEast(this.plot, queue); this.plot.getArea().getPlotManager().removeRoadEast(this.plot, queue);
@ -948,8 +945,8 @@ public final class PlotModificationManager {
.getArea() .getArea()
.getTerrain() == PlotAreaTerrainType.ROAD) { .getTerrain() == PlotAreaTerrainType.ROAD) {
Plot other = this.plot.getRelative(1, 1); Plot other = this.plot.getRelative(1, 1);
Location pos1 = this.plot.getTopAbs().add(1, 0, 1).withY(0); Location pos1 = this.plot.getTopAbs().add(1, 0, 1);
Location pos2 = other.getBottomAbs().subtract(1, 0, 1).withY(MAX_HEIGHT); Location pos2 = other.getBottomAbs().subtract(1, 0, 1);
PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null);
} else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove
this.plot.getArea().getPlotManager().removeRoadSouthEast(this.plot, queue); this.plot.getArea().getPlotManager().removeRoadSouthEast(this.plot, queue);

View File

@ -125,7 +125,7 @@ public abstract class PlotWorld {
/** /**
* @deprecated This method is not meant to be invoked or overridden, with no replacement. * @deprecated This method is not meant to be invoked or overridden, with no replacement.
*/ */
@Deprecated(forRemoval = true, since = "TODO") @Deprecated(forRemoval = true, since = "6.6.0")
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof PlotWorld; return other instanceof PlotWorld;
} }

View File

@ -75,9 +75,9 @@ public class ExpiryTask {
plots = plots != null ? plots : getPlotsToCheck(); plots = plots != null ? plots : getPlotsToCheck();
int diff = settings.REQUIRED_PLOTS; int diff = settings.REQUIRED_PLOTS;
boolean min = true; boolean min = true;
if (settings.REQUIRED_PLOTS - plots.size() < settings.REQUIRED_PLOTS) { if (plots.size() > settings.REQUIRED_PLOTS) {
min = false; min = false;
diff = settings.REQUIRED_PLOTS - plots.size(); diff = plots.size() - settings.REQUIRED_PLOTS;
} }
List<Long> entireList = List<Long> entireList =
plots.stream().map(plot -> ExpireManager.IMP.getAge(plot, settings.DELETE_IF_OWNER_IS_UNKNOWN)) plots.stream().map(plot -> ExpireManager.IMP.getAge(plot, settings.DELETE_IF_OWNER_IS_UNKNOWN))

View File

@ -391,7 +391,7 @@ public class FlagContainer {
/** /**
* @deprecated This method is not meant to be invoked or overridden, with no replacement. * @deprecated This method is not meant to be invoked or overridden, with no replacement.
*/ */
@Deprecated(forRemoval = true, since = "TODO") @Deprecated(forRemoval = true, since = "6.6.0")
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof FlagContainer; return other instanceof FlagContainer;
} }

View File

@ -93,6 +93,7 @@ import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag;
import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag; import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag;
import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag; import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
import com.plotsquared.core.plot.flag.implementations.PriceFlag; import com.plotsquared.core.plot.flag.implementations.PriceFlag;
import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
import com.plotsquared.core.plot.flag.implementations.PveFlag; import com.plotsquared.core.plot.flag.implementations.PveFlag;
import com.plotsquared.core.plot.flag.implementations.PvpFlag; import com.plotsquared.core.plot.flag.implementations.PvpFlag;
import com.plotsquared.core.plot.flag.implementations.RedstoneFlag; import com.plotsquared.core.plot.flag.implementations.RedstoneFlag;
@ -198,6 +199,7 @@ public final class GlobalFlagContainer extends FlagContainer {
this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE); this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE);
this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE); this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE);
this.addFlag(VineGrowFlag.VINE_GROW_TRUE); this.addFlag(VineGrowFlag.VINE_GROW_TRUE);
this.addFlag(ProjectilesFlag.PROJECTILES_FALSE);
// Double flags // Double flags
this.addFlag(PriceFlag.PRICE_NOT_BUYABLE); this.addFlag(PriceFlag.PRICE_NOT_BUYABLE);

View File

@ -221,7 +221,7 @@ public abstract class PlotFlag<T, F extends PlotFlag<T, F>> {
/** /**
* @deprecated This method is not meant to be invoked or overridden, with no replacement. * @deprecated This method is not meant to be invoked or overridden, with no replacement.
*/ */
@Deprecated(forRemoval = true, since = "TODO") @Deprecated(forRemoval = true, since = "6.6.0")
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof PlotFlag; return other instanceof PlotFlag;
} }

View File

@ -0,0 +1,46 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2014 - 2022 IntellectualSites
*
* 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.plotsquared.core.plot.flag.implementations;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.plot.flag.types.BooleanFlag;
import org.checkerframework.checker.nullness.qual.NonNull;
public class ProjectilesFlag extends BooleanFlag<ProjectilesFlag> {
public static final ProjectilesFlag PROJECTILES_TRUE = new ProjectilesFlag(true);
public static final ProjectilesFlag PROJECTILES_FALSE = new ProjectilesFlag(false);
private ProjectilesFlag(boolean value){
super(value, TranslatableCaption.of("flags.flag_description_projectiles"));
}
@Override
protected ProjectilesFlag flagOf(@NonNull final Boolean value) {
return value ? PROJECTILES_TRUE : PROJECTILES_FALSE;
}
}

View File

@ -34,6 +34,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -61,6 +62,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
private int lastX = Integer.MIN_VALUE; private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE; private int lastZ = Integer.MIN_VALUE;
private boolean settingBiomes = false; private boolean settingBiomes = false;
private boolean disableBiomes = false;
private boolean settingTiles = false; private boolean settingTiles = false;
private boolean regen = false; private boolean regen = false;
private int[] regenStart; private int[] regenStart;
@ -68,7 +70,8 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
private CuboidRegion regenRegion = null; private CuboidRegion regenRegion = null;
private Consumer<BlockVector2> consumer = null; private Consumer<BlockVector2> consumer = null;
private boolean unloadAfter = true; private boolean unloadAfter = true;
private Runnable whenDone; private Runnable whenDone = null;
private SideEffectSet sideEffectSet = null;
@Nullable @Nullable
private LightingMode lightingMode = LightingMode.valueOf(Settings.QUEUE.LIGHTING_MODE); private LightingMode lightingMode = LightingMode.valueOf(Settings.QUEUE.LIGHTING_MODE);
@ -101,7 +104,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
@Override @Override
public boolean setBlock(int x, int y, int z, @NonNull BaseBlock id) { public boolean setBlock(int x, int y, int z, @NonNull BaseBlock id) {
if ((y > 255) || (y < 0)) { if ((y > world.getMaxY()) || (y < world.getMinY())) {
return false; return false;
} }
LocalChunk chunk = getChunk(x >> 4, z >> 4); LocalChunk chunk = getChunk(x >> 4, z >> 4);
@ -120,8 +123,11 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
@SuppressWarnings("removal") @SuppressWarnings("removal")
@Override @Override
public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) { public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) {
if (disableBiomes) {
return false;
}
LocalChunk chunk = getChunk(x >> 4, z >> 4); LocalChunk chunk = getChunk(x >> 4, z >> 4);
for (int y = 0; y < 256; y++) { for (int y = world.getMinY(); y <= world.getMaxY(); y++) {
chunk.setBiome(x & 15, y, z & 15, biomeType); chunk.setBiome(x & 15, y, z & 15, biomeType);
} }
settingBiomes = true; settingBiomes = true;
@ -130,6 +136,9 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
@Override @Override
public final boolean setBiome(int x, int y, int z, @NonNull BiomeType biomeType) { public final boolean setBiome(int x, int y, int z, @NonNull BiomeType biomeType) {
if (disableBiomes) {
return false;
}
LocalChunk chunk = getChunk(x >> 4, z >> 4); LocalChunk chunk = getChunk(x >> 4, z >> 4);
chunk.setBiome(x & 15, y, z & 15, biomeType); chunk.setBiome(x & 15, y, z & 15, biomeType);
settingBiomes = true; settingBiomes = true;
@ -141,6 +150,12 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
return this.settingBiomes; return this.settingBiomes;
} }
@Override
public void setBiomesEnabled(boolean settingBiomes) {
this.settingBiomes = settingBiomes;
this.disableBiomes = true;
}
@Override @Override
public boolean setTile(int x, int y, int z, @NonNull CompoundTag tag) { public boolean setTile(int x, int y, int z, @NonNull CompoundTag tag) {
LocalChunk chunk = getChunk(x >> 4, z >> 4); LocalChunk chunk = getChunk(x >> 4, z >> 4);
@ -315,6 +330,29 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator {
this.whenDone = whenDone; this.whenDone = whenDone;
} }
@Override
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
// Don't ask about the @NonNull placement. That's how it needs to be else it errors.
@Override
public void setBiomeCuboid(
final com.plotsquared.core.location.@NonNull Location pos1,
final com.plotsquared.core.location.@NonNull Location pos2,
@NonNull final BiomeType biome
) {
if (disableBiomes) {
return;
}
super.setBiomeCuboid(pos1, pos2, biome);
}
/** /**
* Get the {@link LocalChunk} from the queue at the given chunk coordinates. Returns a new instance if one doesn't exist * Get the {@link LocalChunk} from the queue at the given chunk coordinates. Returns a new instance if one doesn't exist
*/ */

View File

@ -0,0 +1,175 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2014 - 2022 IntellectualSites
*
* 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.plotsquared.core.queue;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.util.AnnotationHelper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.function.pattern.Pattern;
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 org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* {@link QueueCoordinator} that caches all blocks set to it in a given array of form BlockState[][][]. An offset can be
* applied to blocks set to it, and the scope limited. This should have blocks set to it one chunk at a time, based on the
* result of {@link BlockArrayCacheScopedQueueCoordinator#getMin()} and {@link BlockArrayCacheScopedQueueCoordinator#getMax()}.
* The min and max points of this queue are offset according to the minimum point given in the constructor, and the offsets set
* in {@link BlockArrayCacheScopedQueueCoordinator#setOffsetX(int)} and
* {@link BlockArrayCacheScopedQueueCoordinator#setOffsetZ(int)}
*/
@AnnotationHelper.ApiDescription(info = "Internal use only. Subject to change at any time and created for specific use cases.")
public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinator {
private final BlockState[][][] blockStates;
private final int height;
private final int width;
private final int length;
private final int minY;
private final int maxY;
private final int scopeMinX;
private final int scopeMinZ;
private final int scopeMaxX;
private final int scopeMaxZ;
private int offsetX = 0;
private int offsetZ = 0;
/**
* Construct a new instance
*
* @param min Inclusive location of the minimum point to limit the scope to.
* @param max Inclusive location of the maximum point to limit the scope to.
* @since 6.8.0
*/
public BlockArrayCacheScopedQueueCoordinator(Location min, Location max) {
super(null, min, max);
this.width = max.getX() - min.getX() + 1;
this.length = max.getZ() - min.getZ() + 1;
this.minY = min.getY();
this.maxY = max.getY();
this.height = maxY - minY + 1;
this.scopeMinX = min.getX() & 15;
this.scopeMinZ = min.getZ() & 15;
this.scopeMaxX = scopeMinX + width;
this.scopeMaxZ = scopeMinZ + length;
this.blockStates = new BlockState[height][width][length];
}
public BlockState[][][] getBlockStates() {
return blockStates;
}
@Override
public boolean setBlock(int x, final int y, int z, final @NonNull BlockState id) {
x += offsetX;
z += offsetZ;
if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) {
blockStates[y - minY][x - scopeMinX][z - scopeMinZ] = id;
}
return false;
}
@Override
public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) {
int rx = x + offsetX;
int rz = z + offsetZ;
if (rx >= scopeMinX && rx < scopeMaxX && y >= minY && y <= maxY && rz >= scopeMinZ && rz < scopeMaxZ) {
BlockState state = pattern
.applyBlock(super.getMin().getBlockVector3().add(BlockVector3.at(x, y, z)))
.toImmutableState();
blockStates[y - minY][rx - scopeMinX][rz - scopeMinZ] = state;
}
return false;
}
@Override
public @NonNull Location getMin() {
return super.getMin().add(offsetX - scopeMinX, 0, offsetZ - scopeMinZ);
}
@Override
public @NonNull Location getMax() {
return getMin().add(15, 0, 15).withY(maxY);
}
@Override
public boolean setBlock(int x, int y, int z, final @NonNull BaseBlock id) {
x += offsetX;
z += offsetZ;
if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) {
blockStates[y - minY][x][z] = id.toImmutableState();
}
return false;
}
@Override
public @Nullable BlockState getBlock(final int x, final int y, final int z) {
if (x >= 0 && x < width && y >= minY && y <= maxY && z >= 0 && z < length) {
return blockStates[y - minY][x][z];
}
return null;
}
public void setOffsetX(final int offsetX) {
this.offsetX = offsetX;
}
public void setOffsetZ(final int offsetZ) {
this.offsetZ = offsetZ;
}
@Override
public int size() {
return height * width * length;
}
@Override
public boolean setBiome(final int x, final int z, @NonNull final BiomeType biome) {
//do nothing
return false;
}
@Override
public boolean setBiome(final int x, final int y, final int z, @NonNull final BiomeType biome) {
//do nothing
return false;
}
@Override
public void fillBiome(final BiomeType biome) {
//do nothing
}
@Override
public boolean setTile(final int x, final int y, final int z, @NonNull final CompoundTag tag) {
//do nothing
return false;
}
}

View File

@ -36,8 +36,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Queue that is limited to a single chunk * Queue that is limited to a single chunk. It does not allow a delegate queue and should be treated as a cache for changes to
* be set to. Does not support tile entities or entities.
*
* @deprecated This class is poorly designed and will no longer be used in P2
*/ */
@Deprecated(forRemoval = true, since = "6.8.0")
public class ChunkQueueCoordinator extends ScopedQueueCoordinator { public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
public final BiomeType[][][] biomeResult; public final BiomeType[][][] biomeResult;
@ -54,12 +58,12 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
@NonNull BlockVector3 top, @NonNull BlockVector3 top,
boolean biomes boolean biomes
) { ) {
super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); super(null, Location.at("", 0, weWorld.getMinY(), 0), Location.at("", 15, weWorld.getMaxY(), 15));
this.weWorld = weWorld; this.weWorld = weWorld;
this.width = top.getX() - bot.getX() + 1; this.width = top.getX() - bot.getX() + 1;
this.length = top.getZ() - bot.getZ() + 1; this.length = top.getZ() - bot.getZ() + 1;
this.result = new BlockState[256][width][length]; this.result = new BlockState[weWorld.getMaxY() - weWorld.getMinY() + 1][width][length];
this.biomeResult = biomes ? new BiomeType[256][width][length] : null; this.biomeResult = biomes ? new BiomeType[weWorld.getMaxY() - weWorld.getMinY() + 1][width][length] : null;
this.bot = bot; this.bot = bot;
this.top = top; this.top = top;
} }
@ -71,7 +75,7 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
@Override @Override
public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) { public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) {
if (this.biomeResult != null) { if (this.biomeResult != null) {
for (int y = 0; y < 256; y++) { for (int y = weWorld.getMinY(); y <= weWorld.getMaxY(); y++) {
this.storeCacheBiome(x, y, z, biomeType); this.storeCacheBiome(x, y, z, biomeType);
} }
return true; return true;
@ -101,9 +105,10 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
} }
private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) { private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) {
BlockState[][] resultY = result[y]; int yIndex = getYIndex(y);
BlockState[][] resultY = result[yIndex];
if (resultY == null) { if (resultY == null) {
result[y] = resultY = new BlockState[length][]; result[yIndex] = resultY = new BlockState[length][];
} }
BlockState[] resultYZ = resultY[z]; BlockState[] resultYZ = resultY[z];
if (resultYZ == null) { if (resultYZ == null) {
@ -113,9 +118,10 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
} }
private void storeCacheBiome(final int x, final int y, final int z, final @NonNull BiomeType id) { private void storeCacheBiome(final int x, final int y, final int z, final @NonNull BiomeType id) {
BiomeType[][] resultY = biomeResult[y]; int yIndex = getYIndex(y);
BiomeType[][] resultY = biomeResult[yIndex];
if (resultY == null) { if (resultY == null) {
biomeResult[y] = resultY = new BiomeType[length][]; biomeResult[yIndex] = resultY = new BiomeType[length][];
} }
BiomeType[] resultYZ = resultY[z]; BiomeType[] resultYZ = resultY[z];
if (resultYZ == null) { if (resultYZ == null) {
@ -132,7 +138,7 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
@Override @Override
public @Nullable BlockState getBlock(int x, int y, int z) { public @Nullable BlockState getBlock(int x, int y, int z) {
BlockState[][] blocksY = result[y]; BlockState[][] blocksY = result[getYIndex(y)];
if (blocksY != null) { if (blocksY != null) {
BlockState[] blocksYZ = blocksY[z]; BlockState[] blocksYZ = blocksY[z];
if (blocksYZ != null) { if (blocksYZ != null) {
@ -157,4 +163,8 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator {
return Location.at(getWorld().getName(), bot.getX(), bot.getY(), bot.getZ()); return Location.at(getWorld().getName(), bot.getX(), bot.getY(), bot.getZ());
} }
private int getYIndex(int y) {
return y - weWorld.getMinY();
}
} }

View File

@ -32,6 +32,7 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -135,6 +136,13 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
return false; return false;
} }
@Override
public void setBiomesEnabled(final boolean enabled) {
if (parent != null) {
parent.setBiomesEnabled(enabled);
}
}
@Override @Override
public boolean setEntity(@NonNull Entity entity) { public boolean setEntity(@NonNull Entity entity) {
if (parent != null) { if (parent != null) {
@ -248,6 +256,21 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
} }
} }
@Override
public SideEffectSet getSideEffectSet() {
if (parent != null) {
return parent.getSideEffectSet();
}
return null;
}
@Override
public void setSideEffectSet(final SideEffectSet sideEffectSet) {
if (parent != null) {
parent.setSideEffectSet(sideEffectSet);
}
}
@Override @Override
public @NonNull List<BlockVector2> getReadChunks() { public @NonNull List<BlockVector2> getReadChunks() {
if (parent != null) { if (parent != null) {

View File

@ -42,6 +42,7 @@ public class LocalChunk {
private final QueueCoordinator parent; private final QueueCoordinator parent;
private final int x; private final int x;
private final int z; private final int z;
private final int minSection;
private final BaseBlock[][] baseblocks; private final BaseBlock[][] baseblocks;
private final BiomeType[][] biomes; private final BiomeType[][] biomes;
@ -52,8 +53,10 @@ public class LocalChunk {
this.parent = parent; this.parent = parent;
this.x = x; this.x = x;
this.z = z; this.z = z;
baseblocks = new BaseBlock[16][]; this.minSection = parent.getMinLayer();
biomes = new BiomeType[16][]; int sections = parent.getMaxLayer() - parent.getMinLayer() + 1;
baseblocks = new BaseBlock[sections][];
biomes = new BiomeType[sections][];
} }
public @NonNull QueueCoordinator getParent() { public @NonNull QueueCoordinator getParent() {
@ -68,6 +71,15 @@ public class LocalChunk {
return this.z; return this.z;
} }
/**
* Get the minimum layer position stored (usually -4 or 0).
*
* @since 6.6.0
*/
public int getMinSection() {
return this.minSection;
}
public @NonNull BaseBlock[][] getBaseblocks() { public @NonNull BaseBlock[][] getBaseblocks() {
return this.baseblocks; return this.baseblocks;
} }
@ -81,7 +93,7 @@ public class LocalChunk {
} }
public void setBiome(final int x, final int y, final int z, final @NonNull BiomeType biomeType) { public void setBiome(final int x, final int y, final int z, final @NonNull BiomeType biomeType) {
final int i = y >> 4; final int i = getLayerIndex(y);
final int j = ChunkUtil.getJ(x, y, z); final int j = ChunkUtil.getJ(x, y, z);
BiomeType[] array = this.biomes[i]; BiomeType[] array = this.biomes[i];
if (array == null) { if (array == null) {
@ -96,7 +108,7 @@ public class LocalChunk {
} }
public void setBlock(final int x, final int y, final int z, final @NonNull BaseBlock baseBlock) { public void setBlock(final int x, final int y, final int z, final @NonNull BaseBlock baseBlock) {
final int i = y >> 4; final int i = getLayerIndex(y);
final int j = ChunkUtil.getJ(x, y, z); final int j = ChunkUtil.getJ(x, y, z);
BaseBlock[] array = baseblocks[i]; BaseBlock[] array = baseblocks[i];
if (array == null) { if (array == null) {
@ -117,4 +129,8 @@ public class LocalChunk {
return this.entities; return this.entities;
} }
private int getLayerIndex(final int y) {
return (y >> 4) - minSection;
}
} }

View File

@ -87,11 +87,14 @@ public class LocationOffsetDelegateQueueCoordinator extends DelegateQueueCoordin
@Override @Override
public boolean setBiome(int x, int z, @NonNull BiomeType biome) { public boolean setBiome(int x, int z, @NonNull BiomeType biome) {
boolean result = true; try {
for (int y = 0; y < 256; y++) { if (canPlace[x - blockX][z - blockZ]) {
result &= this.setBiome(x, y, z, biome); return super.setBiome(x, z, biome);
}
} catch (final Exception e) {
throw e;
} }
return result; return false;
} }
@Override @Override

View File

@ -35,6 +35,7 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -75,12 +76,31 @@ public abstract class QueueCoordinator {
* @param x chunk x coordinate * @param x chunk x coordinate
* @param z chunk z coordinate * @param z chunk z coordinate
* @return a new {@link ScopedQueueCoordinator} * @return a new {@link ScopedQueueCoordinator}
* @deprecated Use {@link ScopedQueueCoordinator#getForChunk(int, int, int, int)}
*/ */
@Deprecated(forRemoval = true, since = "6.6.0")
public ScopedQueueCoordinator getForChunk(int x, int z) { public ScopedQueueCoordinator getForChunk(int x, int z) {
if (getWorld() == null) {
return getForChunk(x, z, PlotSquared.platform().versionMinHeight(), PlotSquared.platform().versionMaxHeight());
}
return getForChunk(x, z, getWorld().getMinY(), getWorld().getMaxY());
}
/**
* Get a {@link ScopedQueueCoordinator} limited to the chunk at the specific chunk Coordinates
*
* @param x chunk x coordinate
* @param z chunk z coordinate
* @return a new {@link ScopedQueueCoordinator}
* @since 6.6.0
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/
@Deprecated(forRemoval = true, since = "TODO")
public ScopedQueueCoordinator getForChunk(int x, int z, int minY, int maxY) {
int bx = x << 4; int bx = x << 4;
int bz = z << 4; int bz = z << 4;
return new ScopedQueueCoordinator(this, Location.at(getWorld().getName(), bx, 0, bz), return new ScopedQueueCoordinator(this, Location.at(getWorld().getName(), bx, minY, bz),
Location.at(getWorld().getName(), bx + 15, 255, bz + 255) Location.at(getWorld().getName(), bx + 15, maxY, bz + 15)
); );
} }
@ -126,7 +146,8 @@ public abstract class QueueCoordinator {
} }
/** /**
* Set a chunk object (e.g. the Bukkit Chunk object) to the queue * Set a chunk object (e.g. the Bukkit Chunk object) to the queue. This will be used as fallback in case of WNA failure.
* Should ONLY be used in specific cases (i.e. generation, where a chunk is being populated)
* *
* @param chunkObject chunk object. Usually the implementation-specific chunk (e.g. bukkit Chunk) * @param chunkObject chunk object. Usually the implementation-specific chunk (e.g. bukkit Chunk)
*/ */
@ -230,6 +251,14 @@ public abstract class QueueCoordinator {
*/ */
public abstract boolean isSettingBiomes(); public abstract boolean isSettingBiomes();
/**
* If the queue should accept biome placement
*
* @param enabled If biomes should be enabled
* @since 6.8.0
*/
public abstract void setBiomesEnabled(boolean enabled);
/** /**
* Add entities to be created * Add entities to be created
* *
@ -395,6 +424,20 @@ public abstract class QueueCoordinator {
*/ */
public abstract void setLightingMode(@Nullable LightingMode mode); public abstract void setLightingMode(@Nullable LightingMode mode);
/**
* Get the overriding {@link SideEffectSet} to be used by the queue if it exists, else null
*
* @return Overriding {@link SideEffectSet} or null
*/
public abstract @Nullable SideEffectSet getSideEffectSet();
/**
* Set the overriding {@link SideEffectSet} to be used by the queue. Null to use default side effects.
*
* @param sideEffectSet side effects to override with, or null to use default
*/
public abstract void setSideEffectSet(@Nullable SideEffectSet sideEffectSet);
/** /**
* Fill a cuboid between two positions with a BlockState * Fill a cuboid between two positions with a BlockState
* *
@ -404,7 +447,7 @@ public abstract class QueueCoordinator {
*/ */
public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) { public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) {
int yMin = Math.min(pos1.getY(), pos2.getY()); int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); int yMax = Math.max(pos1.getY(), pos2.getY());
int xMin = Math.min(pos1.getX(), pos2.getX()); int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX()); int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ()); int zMin = Math.min(pos1.getZ(), pos2.getZ());
@ -427,7 +470,7 @@ public abstract class QueueCoordinator {
*/ */
public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull Pattern blocks) { public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull Pattern blocks) {
int yMin = Math.min(pos1.getY(), pos2.getY()); int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); int yMax = Math.max(pos1.getY(), pos2.getY());
int xMin = Math.min(pos1.getX(), pos2.getX()); int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX()); int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ()); int zMin = Math.min(pos1.getZ(), pos2.getZ());
@ -450,7 +493,7 @@ public abstract class QueueCoordinator {
*/ */
public void setBiomeCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BiomeType biome) { public void setBiomeCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BiomeType biome) {
int yMin = Math.min(pos1.getY(), pos2.getY()); int yMin = Math.min(pos1.getY(), pos2.getY());
int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); int yMax = Math.max(pos1.getY(), pos2.getY());
int xMin = Math.min(pos1.getX(), pos2.getX()); int xMin = Math.min(pos1.getX(), pos2.getX());
int xMax = Math.max(pos1.getX(), pos2.getX()); int xMax = Math.max(pos1.getX(), pos2.getX());
int zMin = Math.min(pos1.getZ(), pos2.getZ()); int zMin = Math.min(pos1.getZ(), pos2.getZ());
@ -464,4 +507,32 @@ public abstract class QueueCoordinator {
} }
} }
/**
* Get the min Y limit associated with the queue
*/
protected int getMinY() {
return getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMinHeight();
}
/**
* Get the max Y limit associated with the queue
*/
protected int getMaxY() {
return getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMaxHeight();
}
/**
* Get the min chunk layer associated with the queue. Usually 0 or -4;
*/
protected int getMinLayer() {
return (getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMinHeight()) >> 4;
}
/**
* Get the max chunk layer associated with the queue. Usually 15 or 19
*/
protected int getMaxLayer() {
return (getWorld() != null ? getWorld().getMaxY() : PlotSquared.platform().versionMaxHeight()) >> 4;
}
} }

View File

@ -35,34 +35,39 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Queue that only sets blocks with a designated area * Queue that only sets blocks with a designated X-Z area, will accept any Y values. Requires all blocks be set normalized in
* the x and z directions, i.e. starting from 0,0. An offset of the minimum point of the region will then be applied to x and z.
*
* @deprecated This should be renamed to NormalizedScopedQueueCoordinator or something.
*/ */
@Deprecated(forRemoval = true, since = "6.8.0")
public class ScopedQueueCoordinator extends DelegateQueueCoordinator { public class ScopedQueueCoordinator extends DelegateQueueCoordinator {
private final Location min;
private final Location max;
private final int minX; private final int minX;
private final int minY;
private final int minZ; private final int minZ;
private final int maxX; private final int maxX;
private final int maxY;
private final int maxZ; private final int maxZ;
private final int dx; private final int dx;
private final int dy;
private final int dz; private final int dz;
/**
* Create a new ScopedQueueCoordinator instance that delegates to a given QueueCoordinator. Locations are inclusive.
*/
public ScopedQueueCoordinator(@Nullable QueueCoordinator parent, @NonNull Location min, @NonNull Location max) { public ScopedQueueCoordinator(@Nullable QueueCoordinator parent, @NonNull Location min, @NonNull Location max) {
super(parent); super(parent);
this.min = min;
this.max = max;
this.minX = min.getX(); this.minX = min.getX();
this.minY = min.getY();
this.minZ = min.getZ(); this.minZ = min.getZ();
this.maxX = max.getX(); this.maxX = max.getX();
this.maxY = max.getY();
this.maxZ = max.getZ(); this.maxZ = max.getZ();
this.dx = maxX - minX; this.dx = maxX - minX;
this.dy = maxY - minY;
this.dz = maxZ - minZ; this.dz = maxZ - minZ;
} }
@ -73,11 +78,11 @@ public class ScopedQueueCoordinator extends DelegateQueueCoordinator {
@Override @Override
public boolean setBiome(int x, int y, int z, @NonNull BiomeType biome) { public boolean setBiome(int x, int y, int z, @NonNull BiomeType biome) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBiome(x + minX, y + minY, z + minZ, biome); return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBiome(x + minX, y, z + minZ, biome);
} }
public void fillBiome(BiomeType biome) { public void fillBiome(BiomeType biome) {
for (int y = 0; y <= dy; y++) { for (int y = min.getY(); y <= max.getY(); y++) {
for (int x = 0; x <= dx; x++) { for (int x = 0; x <= dx; x++) {
for (int z = 0; z < dz; z++) { for (int z = 0; z < dz; z++) {
setBiome(x, y, z, biome); setBiome(x, y, z, biome);
@ -88,35 +93,30 @@ public class ScopedQueueCoordinator extends DelegateQueueCoordinator {
@Override @Override
public boolean setBlock(int x, int y, int z, @NonNull BaseBlock id) { public boolean setBlock(int x, int y, int z, @NonNull BaseBlock id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBlock(x + minX, y + minY, z + minZ, id); return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBlock(x + minX, y, z + minZ, id);
} }
@Override @Override
public boolean setBlock(int x, int y, int z, @NonNull BlockState id) { public boolean setBlock(int x, int y, int z, @NonNull BlockState id) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBlock(x + minX, y + minY, z + minZ, id); return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBlock(x + minX, y, z + minZ, id);
} }
@Override @Override
public boolean setBlock(int x, int y, int z, @NonNull Pattern pattern) { public boolean setBlock(int x, int y, int z, @NonNull Pattern pattern) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setBlock( return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setBlock(x + minX, y, z + minZ, pattern);
x + minX,
y + minY,
z + minZ,
pattern
);
} }
@Override @Override
public boolean setTile(int x, int y, int z, @NonNull CompoundTag tag) { public boolean setTile(int x, int y, int z, @NonNull CompoundTag tag) {
return x >= 0 && x <= dx && y >= 0 && y <= dy && z >= 0 && z <= dz && super.setTile(x + minX, y + minY, z + minZ, tag); return x >= 0 && x <= dx && z >= 0 && z <= dz && super.setTile(x + minX, y, z + minZ, tag);
} }
public @NonNull Location getMin() { public @NonNull Location getMin() {
return Location.at(this.getWorld().getName(), this.minX, this.minY, this.minZ); return min;
} }
public @NonNull Location getMax() { public @NonNull Location getMax() {
return Location.at(this.getWorld().getName(), this.maxX, this.maxY, this.maxZ); return max;
} }
} }

View File

@ -31,6 +31,7 @@ import com.plotsquared.core.queue.QueueCoordinator;
import com.plotsquared.core.queue.ScopedQueueCoordinator; import com.plotsquared.core.queue.ScopedQueueCoordinator;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -41,24 +42,26 @@ public abstract class ChunkManager {
private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> forceChunks = new ConcurrentHashMap<>(); private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> forceChunks = new ConcurrentHashMap<>();
private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> addChunks = new ConcurrentHashMap<>(); private static final Map<BlockVector2, RunnableVal<ScopedQueueCoordinator>> addChunks = new ConcurrentHashMap<>();
/**
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/
@Deprecated(forRemoval = true, since = "TODO")
public static void setChunkInPlotArea( public static void setChunkInPlotArea(
RunnableVal<ScopedQueueCoordinator> force, RunnableVal<ScopedQueueCoordinator> force,
RunnableVal<ScopedQueueCoordinator> add, RunnableVal<ScopedQueueCoordinator> add,
String world, String world,
BlockVector2 loc BlockVector2 loc
) { ) {
QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(PlotSquared World weWorld = PlotSquared.platform().worldUtil().getWeWorld(world);
.platform() QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(weWorld);
.worldUtil()
.getWeWorld(world));
if (PlotSquared.get().getPlotAreaManager().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) { if (PlotSquared.get().getPlotAreaManager().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) {
int blockX = loc.getX() << 4; int blockX = loc.getX() << 4;
int blockZ = loc.getZ() << 4; int blockZ = loc.getZ() << 4;
ScopedQueueCoordinator scoped = ScopedQueueCoordinator scoped =
new ScopedQueueCoordinator( new ScopedQueueCoordinator(
queue, queue,
Location.at(world, blockX, 0, blockZ), Location.at(world, blockX, weWorld.getMinY(), blockZ),
Location.at(world, blockX + 15, 255, blockZ + 15) Location.at(world, blockX + 15, weWorld.getMaxY(), blockZ + 15)
); );
if (force != null) { if (force != null) {
force.run(scoped); force.run(scoped);
@ -80,6 +83,10 @@ public abstract class ChunkManager {
} }
} }
/**
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/
@Deprecated(forRemoval = true, since = "TODO")
public static boolean preProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) { public static boolean preProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
final RunnableVal<ScopedQueueCoordinator> forceChunk = forceChunks.get(loc); final RunnableVal<ScopedQueueCoordinator> forceChunk = forceChunks.get(loc);
if (forceChunk != null) { if (forceChunk != null) {
@ -90,6 +97,10 @@ public abstract class ChunkManager {
return false; return false;
} }
/**
* @deprecated {@link ScopedQueueCoordinator} will be renamed in v7.
*/
@Deprecated(forRemoval = true, since = "TODO")
public static boolean postProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) { public static boolean postProcessChunk(BlockVector2 loc, ScopedQueueCoordinator queue) {
final RunnableVal<ScopedQueueCoordinator> addChunk = forceChunks.get(loc); final RunnableVal<ScopedQueueCoordinator> addChunk = forceChunks.get(loc);
if (addChunk != null) { if (addChunk != null) {

View File

@ -39,30 +39,27 @@ public class ChunkUtil {
* - Used for efficient world generation<br> * - Used for efficient world generation<br>
*/ */
private static final short[] x_loc; private static final short[] x_loc;
private static final short[][] y_loc; private static final short[] y_loc;
private static final short[] z_loc; private static final short[] z_loc;
private static final short[][][] CACHE_J; private static final short[][][] CACHE_J;
static { static {
x_loc = new short[4096]; x_loc = new short[4096];
y_loc = new short[16][4096]; y_loc = new short[4096];
z_loc = new short[4096]; z_loc = new short[4096];
for (int i = 0; i < 16; i++) { for (int j = 0; j < 4096; j++) {
int i4 = i << 4; int y = j >> 8;
for (int j = 0; j < 4096; j++) { int a = j - ((y & 0xF) << 8);
int y = i4 + (j >> 8); int z1 = a >> 4;
int a = j - ((y & 0xF) << 8); int x1 = a - (z1 << 4);
int z1 = a >> 4; x_loc[j] = (short) x1;
int x1 = a - (z1 << 4); y_loc[j] = (short) y;
x_loc[j] = (short) x1; z_loc[j] = (short) z1;
y_loc[i][j] = (short) y;
z_loc[j] = (short) z1;
}
} }
CACHE_J = new short[256][16][16]; CACHE_J = new short[16][16][16];
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
for (int y = 0; y < 256; y++) { for (int y = 0; y < 16; y++) {
short j = (short) ((y & 0xF) << 8 | z << 4 | x); short j = (short) ((y & 0xF) << 8 | z << 4 | x);
CACHE_J[y][x][z] = j; CACHE_J[y][x][z] = j;
} }
@ -83,7 +80,7 @@ public class ChunkUtil {
* @return J value for xyz position in Array[4096]. * @return J value for xyz position in Array[4096].
*/ */
public static int getJ(int x, int y, int z) { public static int getJ(int x, int y, int z) {
return CACHE_J[y][x][z]; return CACHE_J[y & 15][x & 15][z & 15];
} }
/** /**
@ -97,14 +94,14 @@ public class ChunkUtil {
} }
/** /**
* Gets the y coordinate for specific I and J values for a Chunk 16x16x16x16 layerxyz Array[16][4096]. * Gets the y coordinate for specific I and J values for a Chunk Nx16x16x16 layerxyz Array[N][4096].
* *
* @param i Relative layer of the position in the layerxyz Array[16][4096]. * @param i Relative layer of the position in the layerxyz Array[16][4096]. May be negative.
* @param j Position in the xyz Array[4096]. * @param j Position in the xyz Array[4096].
* @return x coordinate within the chunk * @return x coordinate within the chunk
*/ */
public static int getY(int i, int j) { public static int getY(int i, int j) {
return y_loc[i][j]; return (i << 4) + y_loc[j];
} }
/** /**

View File

@ -37,15 +37,21 @@ public class MainUtil {
* Cache of mapping x,y,z coordinates to the chunk array<br> * Cache of mapping x,y,z coordinates to the chunk array<br>
* - Used for efficient world generation<br> * - Used for efficient world generation<br>
*/ */
@Deprecated(forRemoval = true, since = "6.0.0")
public static short[][] x_loc; public static short[][] x_loc;
@Deprecated(forRemoval = true, since = "6.0.0")
public static short[][] y_loc; public static short[][] y_loc;
@Deprecated(forRemoval = true, since = "6.0.0")
public static short[][] z_loc; public static short[][] z_loc;
@Deprecated(forRemoval = true, since = "6.0.0")
public static short[][][] CACHE_I = null; public static short[][][] CACHE_I = null;
@Deprecated(forRemoval = true, since = "6.0.0")
public static short[][][] CACHE_J = null; public static short[][][] CACHE_J = null;
/** /**
* This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area. * This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area.
*/ */
@Deprecated(forRemoval = true, since = "6.0.0")
public static void initCache() { public static void initCache() {
if (x_loc == null) { if (x_loc == null) {
x_loc = new short[16][4096]; x_loc = new short[16][4096];

View File

@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Deprecated(since = "6.6.2", forRemoval = true)
public class RegExUtil { public class RegExUtil {
public static Map<String, Pattern> compiledPatterns; public static Map<String, Pattern> compiledPatterns;

View File

@ -279,7 +279,10 @@ public abstract class RegionManager {
fromQueue1.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks()); fromQueue1.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks());
fromQueue2.addReadChunks(new CuboidRegion( fromQueue2.addReadChunks(new CuboidRegion(
swapPos.getBlockVector3(), swapPos.getBlockVector3(),
BlockVector3.at(swapPos.getX() + pos2.getX() - pos1.getX(), 0, swapPos.getZ() + pos2.getZ() - pos1.getZ()) BlockVector3.at(swapPos.getX() + pos2.getX() - pos1.getX(),
pos1.getY(),
swapPos.getZ() + pos2.getZ() - pos1.getZ()
)
).getChunks()); ).getChunks());
QueueCoordinator toQueue1 = blockQueue.getNewQueue(world1); QueueCoordinator toQueue1 = blockQueue.getNewQueue(world1);
QueueCoordinator toQueue2 = blockQueue.getNewQueue(world2); QueueCoordinator toQueue2 = blockQueue.getNewQueue(world2);
@ -352,7 +355,7 @@ public abstract class RegionManager {
int bz = Math.max(pos1.getZ(), cbz) & 15; int bz = Math.max(pos1.getZ(), cbz) & 15;
int tx = Math.min(pos2.getX(), cbx + 15) & 15; int tx = Math.min(pos2.getX(), cbx + 15) & 15;
int tz = Math.min(pos2.getZ(), cbz + 15) & 15; int tz = Math.min(pos2.getZ(), cbz + 15) & 15;
for (int y = 0; y < 256; y++) { for (int y = world1.getMinY(); y <= world1.getMaxY(); y++) {
for (int x = bx; x <= tx; x++) { for (int x = bx; x <= tx; x++) {
for (int z = bz; z <= tz; z++) { for (int z = bz; z <= tz; z++) {
int rx = cbx + x; int rx = cbx + x;
@ -363,7 +366,10 @@ public abstract class RegionManager {
} }
} }
} }
Region region = new CuboidRegion(BlockVector3.at(cbx + bx, 0, cbz + bz), BlockVector3.at(cbx + tx, 255, cbz + tz)); Region region = new CuboidRegion(
BlockVector3.at(cbx + bx, world1.getMinY(), cbz + bz),
BlockVector3.at(cbx + tx, world1.getMaxY(), cbz + tz)
);
toQueue.addEntities(world1.getEntities(region)); toQueue.addEntities(world1.getEntities(region));
if (removeEntities) { if (removeEntities) {
for (Entity entity : world1.getEntities(region)) { for (Entity entity : world1.getEntities(region)) {
@ -373,6 +379,7 @@ public abstract class RegionManager {
}); });
} }
@Deprecated(forRemoval = true, since = "6.6.0")
public void setBiome( public void setBiome(
final CuboidRegion region, final CuboidRegion region,
final int extendBiome, final int extendBiome,
@ -380,39 +387,48 @@ public abstract class RegionManager {
final String world, final String world,
final Runnable whenDone final Runnable whenDone
) { ) {
Location pos1 = Location setBiome(region, extendBiome, biome, PlotSquared.get().getPlotAreaManager().getPlotAreas(world, region)[0], whenDone);
.at( }
world,
region.getMinimumPoint().getX() - extendBiome,
region.getMinimumPoint().getY(),
region.getMinimumPoint().getZ() - extendBiome
);
Location pos2 = Location
.at(
world,
region.getMaximumPoint().getX() + extendBiome,
region.getMaximumPoint().getY(),
region.getMaximumPoint().getZ() + extendBiome
);
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world));
final int minX = pos1.getX(); /**
final int minZ = pos1.getZ(); * Set a region to a biome type.
final int maxX = pos2.getX(); *
final int maxZ = pos2.getZ(); * @param region region to set
* @param extendBiome how far outside the region to extent setting the biome too account for 3D biomes being 4x4
* @param biome biome to set
* @param area {@link PlotArea} in which the biome is being set
* @param whenDone task to run when complete
* @since 6.6.0
*/
public void setBiome(
final CuboidRegion region,
final int extendBiome,
final BiomeType biome,
final PlotArea area,
final Runnable whenDone
) {
final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
queue.addReadChunks(region.getChunks()); queue.addReadChunks(region.getChunks());
queue.setChunkConsumer(blockVector2 -> { final BlockVector3 regionMin = region.getMinimumPoint();
final int cx = blockVector2.getX() << 4; final BlockVector3 regionMax = region.getMaximumPoint();
final int cz = blockVector2.getZ() << 4; queue.setChunkConsumer(chunkPos -> {
BlockVector3 chunkMin = BlockVector3.at(
Math.max(chunkPos.getX() << 4, regionMin.getBlockX()),
regionMin.getBlockY(),
Math.max(chunkPos.getZ() << 4, regionMin.getBlockZ())
);
BlockVector3 chunkMax = BlockVector3.at(
Math.min((chunkPos.getX() << 4) + 15, regionMax.getBlockX()),
regionMax.getBlockY(),
Math.min((chunkPos.getZ() << 4) + 15, regionMax.getBlockZ())
);
CuboidRegion chunkRegion = new CuboidRegion(region.getWorld(), chunkMin, chunkMax);
WorldUtil.setBiome( WorldUtil.setBiome(
world, area.getWorldName(),
Math.max(minX, cx), chunkRegion,
Math.max(minZ, cz),
Math.min(maxX, cx + 15),
Math.min(maxZ, cz + 15),
biome biome
); );
worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world); worldUtil.refreshChunk(chunkPos.getBlockX(), chunkPos.getBlockZ(), area.getWorldName());
}); });
queue.setCompleteTask(whenDone); queue.setCompleteTask(whenDone);
queue.enqueue(); queue.enqueue();

View File

@ -76,8 +76,9 @@ public class RegionUtil {
return new CuboidRegion(min, max); return new CuboidRegion(min, max);
} }
@Deprecated(forRemoval = true, since = "6.6.0")
public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) {
return createRegion(pos1x, pos2x, 0, Plot.MAX_HEIGHT - 1, pos1z, pos2z); return createRegion(pos1x, pos2x, 0, 255, pos1z, pos2z);
} }
public static CuboidRegion createRegion( public static CuboidRegion createRegion(

View File

@ -305,12 +305,13 @@ public abstract class SchematicHandler {
final int WIDTH = dimension.getX(); final int WIDTH = dimension.getX();
final int LENGTH = dimension.getZ(); final int LENGTH = dimension.getZ();
final int HEIGHT = dimension.getY(); final int HEIGHT = dimension.getY();
final int worldHeight = plot.getArea().getMaxGenHeight() - plot.getArea().getMinGenHeight() + 1;
// Validate dimensions // Validate dimensions
CuboidRegion region = plot.getLargestRegion(); CuboidRegion region = plot.getLargestRegion();
boolean sizeMismatch = boolean sizeMismatch =
((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || ( ((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || (
(region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT
> 256); > worldHeight);
if (!Settings.Schematics.PASTE_MISMATCHES && sizeMismatch) { if (!Settings.Schematics.PASTE_MISMATCHES && sizeMismatch) {
actor.sendMessage(TranslatableCaption.of("schematics.schematic_size_mismatch")); actor.sendMessage(TranslatableCaption.of("schematics.schematic_size_mismatch"));
TaskManager.runTask(whenDone); TaskManager.runTask(whenDone);
@ -321,14 +322,14 @@ public abstract class SchematicHandler {
// Calculate the optimal height to paste the schematic at // Calculate the optimal height to paste the schematic at
final int y_offset_actual; final int y_offset_actual;
if (autoHeight) { if (autoHeight) {
if (HEIGHT >= 256) { if (HEIGHT >= worldHeight) {
y_offset_actual = yOffset; y_offset_actual = yOffset;
} else { } else {
PlotArea pw = plot.getArea(); PlotArea pw = plot.getArea();
if (pw instanceof ClassicPlotWorld) { if (pw instanceof ClassicPlotWorld) {
y_offset_actual = yOffset + pw.getMinBuildHeight() + ((ClassicPlotWorld) pw).PLOT_HEIGHT; y_offset_actual = yOffset + pw.getMinBuildHeight() + ((ClassicPlotWorld) pw).PLOT_HEIGHT;
} else { } else {
y_offset_actual = yOffset + 1 + this.worldUtil y_offset_actual = yOffset + pw.getMinBuildHeight() + this.worldUtil
.getHighestBlockSynchronous(plot.getWorldName(), region.getMinimumPoint().getX() + 1, .getHighestBlockSynchronous(plot.getWorldName(), region.getMinimumPoint().getX() + 1,
region.getMinimumPoint().getZ() + 1 region.getMinimumPoint().getZ() + 1
); );
@ -360,9 +361,9 @@ public abstract class SchematicHandler {
// Paste schematic here // Paste schematic here
final QueueCoordinator queue = plot.getArea().getQueue(); final QueueCoordinator queue = plot.getArea().getQueue();
for (int ry = 0; ry < Math.min(256, HEIGHT); ry++) { for (int ry = 0; ry < Math.min(worldHeight, HEIGHT); ry++) {
int yy = y_offset_actual + ry; int yy = y_offset_actual + ry;
if (yy > 255 || yy < 0) { if (yy > plot.getArea().getMaxGenHeight() || yy < plot.getArea().getMinGenHeight()) {
continue; continue;
} }
for (int rz = 0; rz < blockArrayClipboard.getDimensions().getZ(); rz++) { for (int rz = 0; rz < blockArrayClipboard.getDimensions().getZ(); rz++) {
@ -379,18 +380,18 @@ public abstract class SchematicHandler {
BlockVector3 loc = BlockVector3.at(rx, ry, rz); BlockVector3 loc = BlockVector3.at(rx, ry, rz);
BaseBlock id = blockArrayClipboard.getFullBlock(loc); BaseBlock id = blockArrayClipboard.getFullBlock(loc);
queue.setBlock(xx, yy, zz, id); queue.setBlock(xx, yy, zz, id);
if (ry == 0) { BiomeType biome = blockArrayClipboard.getBiome(loc);
BiomeType biome = blockArrayClipboard.getBiome(loc); queue.setBiome(xx, yy, zz, biome);
queue.setBiome(xx, yy, zz, biome);
}
} }
} }
} }
if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) {
queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); queue.addProgressSubscriber(subscriberFactory.createWithActor(actor));
} }
whenDone.value = true; if (whenDone != null) {
queue.setCompleteTask(whenDone); whenDone.value = true;
queue.setCompleteTask(whenDone);
}
queue.enqueue(); queue.enqueue();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -34,6 +34,7 @@ import java.util.HashMap;
public abstract class SetupUtils { public abstract class SetupUtils {
public static HashMap<String, GeneratorWrapper<?>> generators = new HashMap<>(); public static HashMap<String, GeneratorWrapper<?>> generators = new HashMap<>();
protected boolean loaded = false;
/** /**
* @since 6.1.0 * @since 6.1.0

View File

@ -44,27 +44,27 @@ public final class TimeUtil {
StringBuilder toReturn = new StringBuilder(); StringBuilder toReturn = new StringBuilder();
if (time >= 33868800) { if (time >= 33868800) {
int years = (int) (time / 33868800); int years = (int) (time / 33868800);
time -= years * 33868800; time -= years * 33868800L;
toReturn.append(years).append("y "); toReturn.append(years).append("y ");
} }
if (time >= 604800) { if (time >= 604800) {
int weeks = (int) (time / 604800); int weeks = (int) (time / 604800);
time -= weeks * 604800; time -= weeks * 604800L;
toReturn.append(weeks).append("w "); toReturn.append(weeks).append("w ");
} }
if (time >= 86400) { if (time >= 86400) {
int days = (int) (time / 86400); int days = (int) (time / 86400);
time -= days * 86400; time -= days * 86400L;
toReturn.append(days).append("d "); toReturn.append(days).append("d ");
} }
if (time >= 3600) { if (time >= 3600) {
int hours = (int) (time / 3600); int hours = (int) (time / 3600);
time -= hours * 3600; time -= hours * 3600L;
toReturn.append(hours).append("h "); toReturn.append(hours).append("h ");
} }
if (time >= 60) { if (time >= 60) {
int minutes = (int) (time / 60); int minutes = (int) (time / 60);
time -= minutes * 60; time -= minutes * 60L;
toReturn.append(minutes).append("m "); toReturn.append(minutes).append("m ");
} }
if (toReturn.length() == 0 || time > 0) { if (toReturn.length() == 0 || time > 0) {

View File

@ -44,6 +44,9 @@ import java.util.UUID;
public class WEManager { public class WEManager {
private static final BlockVector3 MIN = BlockVector3.at(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
private static final BlockVector3 MAX = BlockVector3.at(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
public static boolean maskContains(Set<CuboidRegion> mask, int x, int y, int z) { public static boolean maskContains(Set<CuboidRegion> mask, int x, int y, int z) {
for (CuboidRegion region : mask) { for (CuboidRegion region : mask) {
if (RegionUtil.contains(region, x, y, z)) { if (RegionUtil.contains(region, x, y, z)) {
@ -91,10 +94,7 @@ public class WEManager {
Location location = player.getLocation(); Location location = player.getLocation();
String world = location.getWorldName(); String world = location.getWorldName();
if (!PlotSquared.get().getPlotAreaManager().hasPlotArea(world)) { if (!PlotSquared.get().getPlotAreaManager().hasPlotArea(world)) {
regions.add(RegionUtil regions.add(new CuboidRegion(MIN, MAX));
.createRegion(Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE,
Integer.MAX_VALUE
));
return regions; return regions;
} }
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();

View File

@ -39,6 +39,7 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
@ -78,14 +79,29 @@ public abstract class WorldUtil {
* @param p2x Max X * @param p2x Max X
* @param p2z Max Z * @param p2z Max Z
* @param biome Biome * @param biome Biome
* @deprecated use {@link WorldUtil#setBiome(String, CuboidRegion, BiomeType)}
*/ */
@Deprecated(forRemoval = true)
public static void setBiome(String world, int p1x, int p1z, int p2x, int p2z, BiomeType biome) { public static void setBiome(String world, int p1x, int p1z, int p2x, int p2z, BiomeType biome) {
BlockVector3 pos1 = BlockVector2.at(p1x, p1z).toBlockVector3(); World weWorld = PlotSquared.platform().worldUtil().getWeWorld(world);
BlockVector3 pos2 = BlockVector2.at(p2x, p2z).toBlockVector3(Plot.MAX_HEIGHT - 1); BlockVector3 pos1 = BlockVector2.at(p1x, p1z).toBlockVector3(weWorld.getMinY());
BlockVector3 pos2 = BlockVector2.at(p2x, p2z).toBlockVector3(weWorld.getMaxY());
CuboidRegion region = new CuboidRegion(pos1, pos2); CuboidRegion region = new CuboidRegion(pos1, pos2);
PlotSquared.platform().worldUtil().setBiomes(world, region, biome); PlotSquared.platform().worldUtil().setBiomes(world, region, biome);
} }
/**
* Set the biome in a region
*
* @param world World name
* @param region Region
* @param biome Biome
* @since 6.6.0
*/
public static void setBiome(String world, final CuboidRegion region, BiomeType biome) {
PlotSquared.platform().worldUtil().setBiomes(world, region, biome);
}
/** /**
* Check if a given world name corresponds to a real world * Check if a given world name corresponds to a real world
* *
@ -217,11 +233,14 @@ public abstract class WorldUtil {
/** /**
* Set the biome in a region * Set the biome in a region
* *
* @param world World name * @param worldName World name
* @param region Region * @param region Region
* @param biome New biome * @param biome New biome
*/ */
public abstract void setBiomes(@NonNull String world, @NonNull CuboidRegion region, @NonNull BiomeType biome); public void setBiomes(@NonNull String worldName, @NonNull CuboidRegion region, @NonNull BiomeType biome) {
final World world = getWeWorld(worldName);
region.forEach(bv -> world.setBiome(bv, biome));
}
/** /**
* Get the WorldEdit {@link com.sk89q.worldedit.world.World} corresponding to a world name * Get the WorldEdit {@link com.sk89q.worldedit.world.World} corresponding to a world name

View File

@ -38,6 +38,7 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.flag.GlobalFlagContainer; import com.plotsquared.core.plot.flag.GlobalFlagContainer;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.PlayerManager;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -110,6 +111,9 @@ public final class PlaceholderRegistry {
return plot.getAlias(); return plot.getAlias();
}); });
this.createPlaceholder("currentplot_owner", (player, plot) -> { this.createPlaceholder("currentplot_owner", (player, plot) -> {
if (plot.getFlag(ServerPlotFlag.class)){
return legacyComponent(TranslatableCaption.of("info.server"), player);
}
final UUID plotOwner = plot.getOwnerAbs(); final UUID plotOwner = plot.getOwnerAbs();
if (plotOwner == null) { if (plotOwner == null) {
return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player); return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player);

View File

@ -71,7 +71,7 @@ public class UUIDMapping {
/** /**
* @deprecated This method is not meant to be invoked or overridden, with no replacement. * @deprecated This method is not meant to be invoked or overridden, with no replacement.
*/ */
@Deprecated(forRemoval = true, since = "TODO") @Deprecated(forRemoval = true, since = "6.6.0")
protected boolean canEqual(final Object other) { protected boolean canEqual(final Object other) {
return other instanceof UUIDMapping; return other instanceof UUIDMapping;
} }

View File

@ -161,8 +161,9 @@
"setup.road_width": "<gold>Road width</gold>", "setup.road_width": "<gold>Road width</gold>",
"setup.road_height": "<gold>Road height</gold>", "setup.road_height": "<gold>Road height</gold>",
"setup.road_block": "<gold>Road block</gold>", "setup.road_block": "<gold>Road block</gold>",
"setup.wall_filling_block": "<gold>Wall filling block</gold><gray> (Block(s) been put under the plot border down to Y1)</gray>", "setup.wall_filling_block": "<gold>Wall filling block</gold><gray> (Block(s) been put under the plot border down to min gen height + 1)</gray>",
"setup.wall_height": "<gold>Wall height</gold>", "setup.wall_height": "<gold>Wall height</gold>",
"setup.min_gen_height": "<gold>Minimum height from which to generate (for 1.18+ can be negative).</gold>",
"setup.bedrock_boolean": "<gold>Whether a bedrock layer under the plot should be generated or not</gold>", "setup.bedrock_boolean": "<gold>Whether a bedrock layer under the plot should be generated or not</gold>",
"setup.singleplotarea_void_world": "<gold>Void world</gold>", "setup.singleplotarea_void_world": "<gold>Void world</gold>",
"plotareatype.plot_area_type_normal": "<gray>Standard plot generation</gray>", "plotareatype.plot_area_type_normal": "<gray>Standard plot generation</gray>",
@ -380,6 +381,9 @@
"info.plot_list_default": "<gold><plot></gold>", "info.plot_list_default": "<gold><plot></gold>",
"info.plot_list_player_online": "<dark_aqua><prefix></dark_aqua><hover:show_text:\"<dark_aqua>Online</dark_aqua>\"><gold><player></gold></hover>", "info.plot_list_player_online": "<dark_aqua><prefix></dark_aqua><hover:show_text:\"<dark_aqua>Online</dark_aqua>\"><gold><player></gold></hover>",
"info.plot_list_player_offline": "<dark_aqua><prefix></dark_aqua><hover:show_text:\"<dark_gray>Offline</dark_gray>\"><gold><player></gold></hover>", "info.plot_list_player_offline": "<dark_aqua><prefix></dark_aqua><hover:show_text:\"<dark_gray>Offline</dark_gray>\"><gold><player></gold></hover>",
"info.plot_list_player_unknown": "<hover:show_text:\"<red>The owner of this plot is unknown</red>\"><white><info.unknown></white></hover>",
"info.plot_list_player_server": "<hover:show_text:\"<red>The plot is owned by the server</red>\"><white><info.server></white></hover>",
"info.plot_list_player_everyone": "<hover:show_text:\"<blue>The plot is owned by everyone</blue>\"><white><info.everyone></white></hover>",
"info.area_info_format": "<header>\n<reset><gold>Name: </gold><gray><name></gray>\n<gold>Type: </gold><gray><type></gray>\n<gold>Terrain: </gold><gray><terrain></gray>\n<gold>Usage: </gold><gray><usage>%</gray>\n<gold>Claimed: </gold><gray><claimed></gray>\n<gold>Clusters: </gold><gray><clusters></gray>\n<gold>Region: </gold><gray><region></gray>\n<gold>Generator: </gold><gray><generator></gray>\n<footer>", "info.area_info_format": "<header>\n<reset><gold>Name: </gold><gray><name></gray>\n<gold>Type: </gold><gray><type></gray>\n<gold>Terrain: </gold><gray><terrain></gray>\n<gold>Usage: </gold><gray><usage>%</gray>\n<gold>Claimed: </gold><gray><claimed></gray>\n<gold>Clusters: </gold><gray><clusters></gray>\n<gold>Region: </gold><gray><region></gray>\n<gold>Generator: </gold><gray><generator></gray>\n<footer>",
"info.area_list_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>", "info.area_list_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>",
"info.area_list_item": "<click:run_command:<command_tp>><hover:show_text:\"<command_tp>\"><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:<command_info>><hover:show_text:\"<hover_info>\"><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>", "info.area_list_item": "<click:run_command:<command_tp>><hover:show_text:\"<command_tp>\"><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:<command_info>><hover:show_text:\"<hover_info>\"><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>",
@ -612,6 +616,7 @@
"flags.flag_description_lectern_read_book": "<gray>Prevent players taking books from lecterns.</gray>", "flags.flag_description_lectern_read_book": "<gray>Prevent players taking books from lecterns.</gray>",
"flags.flag_description_prevent_creative_copy": "<gray>Prevents people from copying item NBT data in the plot unless they're added as members.</gray>", "flags.flag_description_prevent_creative_copy": "<gray>Prevents people from copying item NBT data in the plot unless they're added as members.</gray>",
"flags.flag_description_leaf_decay": "<gray>Set to `false` to prevent leaves from decaying.", "flags.flag_description_leaf_decay": "<gray>Set to `false` to prevent leaves from decaying.",
"flags.flag_description_projectiles": "<gray>Prevents guests from shooting projectiles on the plot when set to false.</gray>",
"flags.flag_error_boolean": "Flag value must be a boolean (true | false).", "flags.flag_error_boolean": "Flag value must be a boolean (true | false).",
"flags.flag_error_enum": "Must be one of: <list>", "flags.flag_error_enum": "Must be one of: <list>",
"flags.flag_error_integer": "Flag value must be a whole positive number.", "flags.flag_error_integer": "Flag value must be a whole positive number.",

View File

@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<img src="https://i.imgur.com/33Y65YL.png" width="150"> <img src="https://raw.githubusercontent.com/IntellectualSites/Assets/main/plugins/PlotSquared/PlotSquared.svg" width="300">
</p> </p>
--- ---

View File

@ -18,7 +18,7 @@ plugins {
idea idea
} }
version = "6.5.2-SNAPSHOT" version = "6.8.2-SNAPSHOT"
allprojects { allprojects {
group = "com.plotsquared" group = "com.plotsquared"
@ -34,12 +34,15 @@ allprojects {
maven { maven {
name = "Sonatype OSS (S01)" name = "Sonatype OSS (S01)"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots") url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} }
maven { maven {
name = "Jitpack" name = "Jitpack"
url = uri("https://jitpack.io") url = uri("https://jitpack.io")
content {
includeModule("com.github.MilkBowl", "VaultAPI")
}
} }
maven { maven {
@ -61,9 +64,12 @@ subprojects {
plugin<EclipsePlugin>() plugin<EclipsePlugin>()
plugin<IdeaPlugin>() plugin<IdeaPlugin>()
} }
dependencies {
implementation(platform("com.intellectualsites.bom:bom-1.18.x:1.2"))
}
} }
val javadocDir = rootDir.resolve("docs").resolve("javadoc").resolve(project.name)
allprojects { allprojects {
dependencies { dependencies {
// Tests // Tests
@ -137,7 +143,7 @@ allprojects {
} }
developer { developer {
id.set("NotMyFault") id.set("NotMyFault")
name.set("NotMyFault") name.set("Alexander Brandes")
organization.set("IntellectualSites") organization.set("IntellectualSites")
email.set("contact@notmyfault.dev") email.set("contact@notmyfault.dev")
} }
@ -169,11 +175,6 @@ allprojects {
} }
tasks { tasks {
named<Delete>("clean") {
doFirst {
javadocDir.deleteRecursively()
}
}
compileJava { compileJava {
options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "1000")) options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "1000"))
@ -184,16 +185,6 @@ allprojects {
options.encoding = "UTF-8" options.encoding = "UTF-8"
} }
javadoc {
val opt = options as StandardJavadocDocletOptions
opt.addStringOption("Xdoclint:none", "-quiet")
opt.tags(
"apiNote:a:API Note:",
"implSpec:a:Implementation Requirements:",
"implNote:a:Implementation Note:"
)
}
shadowJar { shadowJar {
this.archiveClassifier.set(null as String?) this.archiveClassifier.set(null as String?)
this.archiveFileName.set("${project.name}-${project.version}.${this.archiveExtension.getOrElse("jar")}") this.archiveFileName.set("${project.name}-${project.version}.${this.archiveExtension.getOrElse("jar")}")
@ -218,37 +209,3 @@ nexusPublishing {
} }
} }
} }
tasks {
val aggregatedJavadocs = create<Javadoc>("aggregatedJavadocs") {
title = "${project.name} ${project.version} API"
setDestinationDir(javadocDir)
options.destinationDirectory = javadocDir
doFirst {
javadocDir.deleteRecursively()
}
}.also {
it.group = "Documentation"
it.description = "Generate javadocs from all child projects as if it was a single project"
}
subprojects.forEach { subProject ->
subProject.afterEvaluate {
subProject.tasks.withType<Javadoc>().forEach { task ->
aggregatedJavadocs.source += task.source
aggregatedJavadocs.classpath += task.classpath
aggregatedJavadocs.excludes += task.excludes
aggregatedJavadocs.includes += task.includes
val rootOptions = aggregatedJavadocs.options as StandardJavadocDocletOptions
val subOptions = task.options as StandardJavadocDocletOptions
rootOptions.links(*subOptions.links.orEmpty().minus(rootOptions.links.orEmpty().toSet()).toTypedArray())
}
}
}
build {
dependsOn(aggregatedJavadocs)
}
}

View File

@ -1,15 +1,9 @@
[versions] [versions]
# Minecraft expectations
gson = "2.8.8" # Version set by Minecraft
log4j-api = "2.17.1" # Version set by Minecraft
guava = "31.0.1-jre" # Version set by Minecraft
# Platform expectations # Platform expectations
paper = "1.18.1-R0.1-SNAPSHOT" paper = "1.18.1-R0.1-SNAPSHOT"
checker-qual = "3.21.2" checker-qual = "3.22.0"
guice = "5.1.0" guice = "5.1.0"
findbugs = "3.0.1" spotbugs = "4.7.0"
snakeyaml = "1.30" # Version set by Bukkit
# Adventure & MiniMessage # Adventure & MiniMessage
adventure-api = "4.9.3" adventure-api = "4.9.3"
@ -17,24 +11,18 @@ adventure-text-minimessage = "4.1.0-SNAPSHOT"
adventure-platform-bukkit = "4.0.1" adventure-platform-bukkit = "4.0.1"
# Plugins # Plugins
worldedit = "7.2.9" worldedit = "7.2.10"
fawe = "2.0.1"
vault = "1.7.1"
placeholderapi = "2.11.1" placeholderapi = "2.11.1"
luckperms = "5.4" luckperms = "5.4"
essentialsx = "2.19.2" essentialsx = "2.19.4"
mvdwapi = "3.1.1" mvdwapi = "3.1.1"
# Third party # Third party
prtree = "2.0.0" prtree = "2.0.0"
aopalliance = "1.0" aopalliance = "1.0"
cloud-services = "1.6.1" cloud-services = "1.6.2"
arkitektonika = "2.1.1" arkitektonika = "2.1.1"
paster = "1.1.4" squirrelid = "0.3.1"
bstats = "3.0.0"
paperlib = "1.0.7"
squirrelid = "0.3.0"
serverlib = "2.3.1"
http4j = "1.3" http4j = "1.3"
# Gradle plugins # Gradle plugins
@ -48,15 +36,10 @@ nexus = "1.1.0"
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" } paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checker-qual" } checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checker-qual" }
# Minecraft expectations
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
log4j = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j-api" }
# Platform expectations # Platform expectations
snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" }
guice = { group = "com.google.inject", name = "guice", version.ref = "guice" } guice = { group = "com.google.inject", name = "guice", version.ref = "guice" }
guiceassistedinject = { group = "com.google.inject.extensions", name = "guice-assistedinject", version.ref = "guice" } guiceassistedinject = { group = "com.google.inject.extensions", name = "guice-assistedinject", version.ref = "guice" }
findbugs = { group = "com.google.code.findbugs", name = "annotations", version.ref = "findbugs" } spotbugs = { group = "com.github.spotbugs", name = "spotbugs-annotations", version.ref = "spotbugs" }
# Adventure & MiniMessage # Adventure & MiniMessage
adventure = { group = "net.kyori", name = "adventure-api", version.ref = "adventure-api" } adventure = { group = "net.kyori", name = "adventure-api", version.ref = "adventure-api" }
@ -66,9 +49,6 @@ adventurePlatformBukkit = { group = "net.kyori", name = "adventure-platform-bukk
# Plugins # Plugins
worldeditCore = { group = "com.sk89q.worldedit", name = "worldedit-core", version.ref = "worldedit" } worldeditCore = { group = "com.sk89q.worldedit", name = "worldedit-core", version.ref = "worldedit" }
worldeditBukkit = { group = "com.sk89q.worldedit", name = "worldedit-bukkit", version.ref = "worldedit" } worldeditBukkit = { group = "com.sk89q.worldedit", name = "worldedit-bukkit", version.ref = "worldedit" }
fastasyncworldeditBukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukkit", version.ref = "fawe" }
fastasyncworldeditCore = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Core", version.ref = "fawe" }
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" } placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" }
luckperms = { group = "net.luckperms", name = "api", version.ref = "luckperms" } luckperms = { group = "net.luckperms", name = "api", version.ref = "luckperms" }
essentialsx = { group = "net.essentialsx", name = "EssentialsX", version.ref = "essentialsx" } essentialsx = { group = "net.essentialsx", name = "EssentialsX", version.ref = "essentialsx" }
@ -78,14 +58,9 @@ prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref
aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" } aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" }
cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud-services" } cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud-services" }
mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" }
squirrelid = { group = "com.github.EngineHub", name = "SquirrelID", version.ref = "squirrelid" } squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" }
serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" }
bstats = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" }
arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" }
http4j = { group = "com.intellectualsites.http", name = "HTTP4J", version.ref = "http4j" } http4j = { group = "com.intellectualsites.http", name = "HTTP4J", version.ref = "http4j" }
paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref = "paster" }
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
[plugins] [plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@ -8,7 +8,8 @@
"com.google.guava:guava", "com.google.guava:guava",
"com.google.code.gson:gson", "com.google.code.gson:gson",
"gson", "gson",
"snakeyaml" "snakeyaml",
"net.kyori"
], ],
"timezone": "Europe/Berlin", "timezone": "Europe/Berlin",
"schedule": [ "schedule": [