Compare commits

..

60 Commits

Author SHA1 Message Date
f582ec03c5 Release 7.0.0 2023-08-23 12:50:00 +02:00
893be136f0 Update dependency gradle to v8.3 (#4147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-23 12:22:47 +02:00
b74ba30281 Fixed NPE in DebugRoadRegen command 2023-08-21 19:09:35 -04:00
ba9dab1f73 Fixed a typo. 2023-08-18 00:28:51 -04:00
8e60fdb477 Merge remote-tracking branch 'origin/main' 2023-08-18 00:10:03 -04:00
443fe8dd47 Added deprecation 2023-08-18 00:09:48 -04:00
e56e52ba4f Fix 'grant' placeholder 2023-08-11 14:05:23 +02:00
cd008bed9b Update dependency net.essentialsx:EssentialsX to v2.20.1 (#4139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-11 09:52:49 +02:00
d4c90283d6 Cleanup dependencies 2023-08-08 22:33:24 +02:00
dc04ec955a Back to snapshot for development 2023-08-02 13:57:50 +02:00
72f511ce99 Release 7.0.0-rc.4 2023-08-02 13:51:03 +02:00
0d63c2bdb6 feat: allow bypass of econ costs (#4126) 2023-08-02 13:48:07 +02:00
49e13384cf fix: remove "default" spawn reason (#4132) 2023-08-02 13:47:53 +02:00
1ddc19ff69 Update dependency com.intellectualsites.bom:bom-newest to v1.34 (#4130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-01 10:45:47 +02:00
a6d436e841 Update dependency org.junit.jupiter:junit-jupiter to v5.10.0 (#4131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-01 10:45:38 +02:00
9b0b39ac2e feat: add a permission requirement to /plot merge all (#4127) 2023-07-31 14:04:08 +02:00
638f0bd078 fix: do not use overall max schem height for checking road schem height (#4124) 2023-07-30 12:17:35 +02:00
c27b838dad fix: add missing method in UncheckedWorldLocation (#4112)
Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-07-24 18:00:56 +00:00
e0cb2949df fix: switch to consistent heights for schematic generation (#4113) 2023-07-24 16:56:53 +01:00
59be582c28 fix: correct reflected fields for chunk needs saving (#4111) 2023-07-24 16:56:46 +01:00
f6cbb3792f [ci skip] Update documentation location 2023-07-22 11:40:01 +02:00
a68918f830 Update dependency gradle to v8.2.1 (#4117)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-22 11:16:24 +02:00
1a7ded864e Update dependency com.diffplug.spotless to v6.20.0 (#4118)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-22 09:11:22 +00:00
cbc8bc8879 [ci skip] Publish javadocs for releases only 2023-07-22 11:05:30 +02:00
21f79d1c13 Back to snapshot for development 2023-07-22 11:01:11 +02:00
293d7acf2d Release 7.0.0-rc.3 2023-07-22 10:56:35 +02:00
d876d3722a Fix default flags registration for third parties (#4114)
Co-authored-by: Leomixer17 <leonardo.dgs@yahoo.com>
2023-07-17 22:30:02 +02:00
dffb7672ff fix: add missing spawn event reasons (#4110) 2023-07-16 15:25:07 +01:00
f867867a42 Fix typo in comment 2023-07-15 19:56:44 +02:00
59eefd6865 fix: even better handling of schematic heights (#4102) 2023-07-10 23:13:36 +02:00
587a286d05 Back to snapsho for development 2023-07-05 13:35:51 +02:00
e10caf6aa0 Release 7.0.0-rc.2 2023-07-05 13:28:13 +02:00
08b325e37d feat: improvement of kick messages (#4099)
* Adding new player_not_in_plot message

* Adding new cannot_kick_player message

* Small typo

* Rejection: renaming of the player placeholder
2023-07-04 18:44:45 +02:00
c394108ba6 feat: add a sculk sensor flag (#4095) 2023-07-04 16:56:28 +01:00
31e89019f1 Update worldedit to v7.2.15 (#4096)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 10:43:53 +02:00
3a7075e28d Update dependency com.intellectualsites.bom:bom-newest to v1.31 (#4097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 10:43:36 +02:00
8373b7874e Update dependency gradle to v8.2 (#4098)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-01 10:42:20 +02:00
fe13882b97 Update renovate.json 2023-07-01 10:28:10 +02:00
f45064c4c4 fix: P2 areas are in worlds.yml 2023-06-23 14:11:12 +01:00
af32399dd2 Correct calculating the plot price, if 'merge' differs from 'claim' 2023-06-23 10:40:40 +02:00
f3c03348d9 fix: return on null plot on big boom (#4085)
- Fixes #4084
2023-06-22 20:09:31 +02:00
a53330e39b Disable update checker for RC phase 2023-06-22 20:08:43 +02:00
e2ba93dab9 Update unsupported MiniMessage syntax 2023-06-22 19:55:36 +02:00
9d43434e40 Add 1.20.1 to the issue template 2023-06-17 18:45:42 +02:00
4f421167d1 Move renovate to .github folder 2023-06-17 18:43:53 +02:00
94f4619c2c Publish javadocs for v7 2023-06-15 17:30:27 +02:00
9885d3e506 Fill in 'since' annotations 2023-06-15 17:24:21 +02:00
a54276d3b2 Strip legacy color codes if message cannot be parsed by MiniMessage (#4077) 2023-06-15 10:23:09 +02:00
cbb284b0fd Properly drop unsupported biomes from biome list (#4074)
* Drop CUSTOM from biome list

* Drop cherry_grove if present on pre 1.20 versions
2023-06-14 15:12:34 +02:00
ed22b22e9c [ci skip] Update bug_report.yml 2023-06-11 12:06:33 +02:00
444ccda807 Add support for 1.20 (#4061)
1.20 fixes
2023-06-09 13:22:55 +02:00
db361cc420 Wrong biome list for 1.19.4 if datapacks are not enabled (#4016)
* Remove cherry grove for 1.20 below

* Handle PR feedback. Replace version check with registry check

* Simplify the biomes list

* Update Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java

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

* Handle pr feedback

---------

Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
2023-06-09 13:22:23 +02:00
079dc02cfe Update dependency net.essentialsx:EssentialsX to v2.20.0 (#4063)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-09 11:09:06 +00:00
e98791c865 Update top level group id and lowercaswe artifact names (#4060)
* Update top level group Id (#4055)

* Lowercase artifact names
2023-06-08 10:40:02 +02:00
7c3112f30f Update gradle (#4044)
* Update gradle

* Update codeQL

* *
2023-06-04 13:57:39 +02:00
c01f5f5c7d Update dependency com.diffplug.spotless to v6.19.0 (#4052)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 09:21:53 +02:00
95caa19505 Update guice to v7 (major) (#4053)
Update guice to v7

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-01 09:21:43 +02:00
b8055201df fix: do not reset the connectedCache every time Plot#getRegions is called (#4046)
* fix: do not reset the connectedCache every time Plot#getRegions is called
 - Fixes IntellectualSites/FastAsyncWorldEdit#2188

* Remove unused import
2023-05-25 19:05:20 +02:00
81daefae4a fix: do not overwrite bedrock with wall (#4048)
- Fixes #4047
2023-05-25 19:04:53 +02:00
02437a8c72 feat: add cost for the merge when using plot auto-merge (#3841)
* feat: add cost for the merge when using plot auto-merge
 - Closes #3814

* fix: Don't charge for auto merge if there is no auto merge

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
2023-05-21 17:57:46 +02:00
59 changed files with 426 additions and 225 deletions

View File

@ -7,8 +7,8 @@ body:
attributes: attributes:
value: | value: |
Thanks for taking the time to fill out this bug report for PlotSquared! Fill out the following form to your best ability to help us fix the problem. Thanks for taking the time to fill out this bug report for PlotSquared! Fill out the following form to your best ability to help us fix the problem.
Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/plotsquared-documentation/). Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.gitbook.io/plotsquared/).
Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://forms.gle/btgdRn9yhGtzEiGW8) form! Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://github.com/IntellectualSites/PlotSquared/security/policy) GitHub form!
- type: dropdown - type: dropdown
attributes: attributes:
@ -27,6 +27,9 @@ 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.20.1'
- '1.20'
- '1.19.4'
- '1.19.3' - '1.19.3'
- '1.19.2' - '1.19.2'
- '1.19.1' - '1.19.1'

View File

@ -4,5 +4,5 @@ contact_links:
url: https://discord.gg/intellectualsites url: https://discord.gg/intellectualsites
about: Our support Discord, please ask questions and seek support here. about: Our support Discord, please ask questions and seek support here.
- name: PlotSquared Wiki - name: PlotSquared Wiki
url: https://intellectualsites.github.io/plotsquared-documentation/ url: https://intellectualsites.gitbook.io/plotsquared/
about: Take a look at the wiki page for instructions how to setup PlotSquared and use its commands. about: Take a look at the wiki page for instructions how to setup PlotSquared and use its commands.

View File

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

19
.github/renovate.json vendored Normal file
View File

@ -0,0 +1,19 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
":semanticCommitsDisabled"
],
"automerge": true,
"labels": [
"dependencies"
],
"rebaseWhen": "conflicted",
"schedule": ["on the first day of the month"],
"ignoreDeps": [
"com.google.code.gson:gson",
"com.google.guava:guava",
"org.yaml:snakeyaml",
"org.apache.logging.log4j:log4j-api",
]
}

View File

@ -21,6 +21,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v2
with: with:

View File

@ -18,23 +18,23 @@ repositories {
} }
dependencies { dependencies {
api(projects.plotSquaredCore) api(projects.plotsquaredCore)
// Metrics // Metrics
implementation("org.bstats:bstats-bukkit") implementation(libs.bstatsBukkit)
// Paper // Paper
compileOnly("io.papermc.paper:paper-api") compileOnly(libs.paper)
implementation("io.papermc:paperlib") implementation(libs.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("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false } compileOnly(libs.faweBukkit) { isTransitive = false }
testImplementation("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit") { isTransitive = false } testImplementation(libs.faweBukkit) { isTransitive = false }
compileOnly("com.github.MilkBowl:VaultAPI") { compileOnly(libs.vault) {
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("dev.notmyfault.serverlib:ServerLib") implementation(libs.serverlib)
// Our libraries // Our libraries
implementation(libs.arkitektonika) implementation(libs.arkitektonika)
implementation("com.intellectualsites.paster:Paster") implementation(libs.paster)
implementation("com.intellectualsites.informative-annotations:informative-annotations") implementation(libs.informativeAnnotations)
// Adventure // Adventure
implementation("net.kyori:adventure-platform-bukkit") implementation(libs.adventureBukkit)
} }
tasks.processResources { tasks.processResources {
@ -62,6 +62,7 @@ tasks.processResources {
} }
tasks.named<ShadowJar>("shadowJar") { tasks.named<ShadowJar>("shadowJar") {
dependsOn(":plotsquared-core:shadowJar")
dependencies { dependencies {
exclude(dependency("org.checkerframework:")) exclude(dependency("org.checkerframework:"))
} }
@ -102,7 +103,7 @@ tasks {
opt.links("https://jd.papermc.io/paper/1.19/") opt.links("https://jd.papermc.io/paper/1.19/")
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://intellectualsites.github.io/plotsquared-javadocs/core/") opt.links("https://intellectualsites.github.io/plotsquared-javadocs/core/")
opt.links("https://jd.advntr.dev/api/4.12.0/") opt.links("https://jd.advntr.dev/api/4.14.0/")
opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/")
opt.links("https://checkerframework.org/api/") opt.links("https://checkerframework.org/api/")
opt.isLinkSource = true opt.isLinkSource = true

View File

@ -34,9 +34,12 @@ import com.plotsquared.core.queue.ZeroedDelegateScopedQueueCoordinator;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
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.bukkit.HeightMap; import org.bukkit.HeightMap;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
@ -48,10 +51,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import static java.util.function.Predicate.not;
public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> { public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitPlotGenerator.class.getSimpleName()); private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitPlotGenerator.class.getSimpleName());
@ -284,7 +291,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
*/ */
@SuppressWarnings("deprecation") // The entire method is deprecated, but kept for compatibility with <=1.16.2 @SuppressWarnings("deprecation") // The entire method is deprecated, but kept for compatibility with <=1.16.2
@Override @Override
@Deprecated(since = "TODO") @Deprecated(since = "7.0.0")
public @NonNull ChunkData generateChunkData( public @NonNull ChunkData generateChunkData(
@NonNull World world, @NonNull Random random, int x, int z, @NonNull BiomeGrid biome @NonNull World world, @NonNull Random random, int x, int z, @NonNull BiomeGrid biome
) { ) {
@ -414,7 +421,11 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
if (lastPlotArea != null && name.equals(this.levelName) && chunkX == lastChunkX && chunkZ == lastChunkZ) { if (lastPlotArea != null && name.equals(this.levelName) && chunkX == lastChunkX && chunkZ == lastChunkZ) {
return lastPlotArea; return lastPlotArea;
} }
PlotArea area = UncheckedWorldLocation.at(name, chunkX << 4, 0, chunkZ << 4).getPlotArea(); BlockVector3 loc = BlockVector3.at(chunkX << 4, 0, chunkZ << 4);
if (lastPlotArea != null && lastPlotArea.getRegion().contains(loc) && lastPlotArea.getRegion().contains(loc)) {
return lastPlotArea;
}
PlotArea area = UncheckedWorldLocation.at(name, loc).getPlotArea();
if (area == null) { if (area == null) {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"Cannot generate chunk that does not belong to a plot area. World: %s", "Cannot generate chunk that does not belong to a plot area. World: %s",
@ -434,9 +445,16 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
private static final List<Biome> BIOMES; private static final List<Biome> BIOMES;
static { static {
ArrayList<Biome> biomes = new ArrayList<>(List.of(Biome.values())); Set<Biome> disabledBiomes = EnumSet.of(Biome.CUSTOM);
biomes.remove(Biome.CUSTOM); if (PlotSquared.platform().serverVersion()[1] <= 19) {
BIOMES = List.copyOf(biomes); final Biome cherryGrove = Registry.BIOME.get(NamespacedKey.minecraft("cherry_grove"));
if (cherryGrove != null) {
disabledBiomes.add(cherryGrove);
}
}
BIOMES = Arrays.stream(Biome.values())
.filter(not(disabledBiomes::contains))
.toList();
} }
@Override @Override

View File

@ -1116,6 +1116,7 @@ public class BlockEventListener implements Listener {
if (plot != null) { if (plot != null) {
plot.debug("Explosion was cancelled because explosion = false"); plot.debug("Explosion was cancelled because explosion = false");
} }
return;
} }
event.blockList().removeIf(blox -> !plot.equals(area.getOwnedPlot(BukkitUtil.adapt(blox.getLocation())))); event.blockList().removeIf(blox -> !plot.equals(area.getOwnedPlot(BukkitUtil.adapt(blox.getLocation()))));
} }

View File

@ -26,6 +26,7 @@ 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.CopperOxideFlag; import com.plotsquared.core.plot.flag.implementations.CopperOxideFlag;
import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag; import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag;
import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag;
import com.plotsquared.core.util.PlotFlagUtil; import com.plotsquared.core.util.PlotFlagUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -96,12 +97,12 @@ public class BlockEventListener117 implements Listener {
area, area,
MiscInteractFlag.class, MiscInteractFlag.class,
true true
) || plot != null && !plot.getFlag( ) || plot != null && (!plot.getFlag(MiscInteractFlag.class) || !plot.getFlag(SculkSensorInteractFlag.class))) {
MiscInteractFlag.class)) {
if (plotPlayer != null) { if (plotPlayer != null) {
if (plot != null) { if (plot != null) {
if (!plot.isAdded(plotPlayer.getUUID())) { if (!plot.isAdded(plotPlayer.getUUID())) {
plot.debug(plotPlayer.getName() + " couldn't trigger sculk sensors because misc-interact = false"); plot.debug(plotPlayer.getName() + " couldn't trigger sculk sensors because both " +
"sculk-sensor-interact and misc-interact = false");
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -112,13 +113,15 @@ public class BlockEventListener117 implements Listener {
if (plot != null) { if (plot != null) {
if (itemThrower == null && (itemThrower = item.getOwner()) == null) { if (itemThrower == null && (itemThrower = item.getOwner()) == null) {
plot.debug( plot.debug(
"A thrown item couldn't trigger sculk sensors because misc-interact = false and the item's owner could not be resolved."); "A thrown item couldn't trigger sculk sensors because both sculk-sensor-interact and " +
"misc-interact = false and the item's owner could not be resolved.");
event.setCancelled(true); event.setCancelled(true);
return; return;
} }
if (!plot.isAdded(itemThrower)) { if (!plot.isAdded(itemThrower)) {
if (!plot.isAdded(itemThrower)) { if (!plot.isAdded(itemThrower)) {
plot.debug("A thrown item couldn't trigger sculk sensors because misc-interact = false"); plot.debug("A thrown item couldn't trigger sculk sensors because both sculk-sensor-interact and " +
"misc-interact = false");
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -137,7 +140,6 @@ public class BlockEventListener117 implements Listener {
if (area == null) { if (area == null) {
for (int i = blocks.size() - 1; i >= 0; i--) { for (int i = blocks.size() - 1; i >= 0; i--) {
Location blockLocation = BukkitUtil.adapt(blocks.get(i).getLocation()); Location blockLocation = BukkitUtil.adapt(blocks.get(i).getLocation());
blockLocation = BukkitUtil.adapt(blocks.get(i).getLocation());
if (blockLocation.isPlotArea()) { if (blockLocation.isPlotArea()) {
blocks.remove(i); blocks.remove(i);
} }

View File

@ -26,6 +26,7 @@ import com.plotsquared.core.plot.Plot;
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.plot.world.SinglePlotArea; import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.util.ReflectionUtils;
import com.plotsquared.core.util.ReflectionUtils.RefClass; import com.plotsquared.core.util.ReflectionUtils.RefClass;
import com.plotsquared.core.util.ReflectionUtils.RefField; import com.plotsquared.core.util.ReflectionUtils.RefField;
import com.plotsquared.core.util.ReflectionUtils.RefMethod; import com.plotsquared.core.util.ReflectionUtils.RefMethod;
@ -64,9 +65,11 @@ public class ChunkListener implements Listener {
private final PlotAreaManager plotAreaManager; private final PlotAreaManager plotAreaManager;
private final int version; private final int version;
private RefMethod methodSetUnsaved;
private RefMethod methodGetHandleChunk; private RefMethod methodGetHandleChunk;
private RefMethod methodGetHandleWorld; private RefMethod methodGetHandleWorld;
private RefField mustSave; private RefField mustNotSave;
private Object objChunkStatusFull = null;
/* /*
private RefMethod methodGetFullChunk; private RefMethod methodGetFullChunk;
private RefMethod methodGetBukkitChunk; private RefMethod methodGetBukkitChunk;
@ -79,7 +82,6 @@ public class ChunkListener implements Listener {
*/ */
private Chunk lastChunk; private Chunk lastChunk;
private boolean ignoreUnload = false; private boolean ignoreUnload = false;
private boolean isTrueForNotSave = true;
@Inject @Inject
public ChunkListener(final @NonNull PlotAreaManager plotAreaManager) { public ChunkListener(final @NonNull PlotAreaManager plotAreaManager) {
@ -90,22 +92,27 @@ public class ChunkListener implements Listener {
} }
try { try {
RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
this.methodGetHandleWorld = classCraftWorld.getMethod("getHandle");
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
ReflectionUtils.RefClass classChunkAccess = getRefClass("net.minecraft.world.level.chunk.IChunkAccess");
this.methodSetUnsaved = classChunkAccess.getMethod("a", boolean.class);
try {
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
} catch (NoSuchMethodException ignored) {
try {
RefClass classChunkStatus = getRefClass("net.minecraft.world.level.chunk.ChunkStatus");
this.objChunkStatusFull = classChunkStatus.getRealClass().getField("n").get(null);
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle", classChunkStatus.getRealClass());
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
try { try {
if (version < 17) { if (version < 17) {
RefClass classChunk = getRefClass("{nms}.Chunk"); RefClass classChunk = getRefClass("{nms}.Chunk");
if (version == 13) { this.mustNotSave = classChunk.getField("mustNotSave");
this.mustSave = classChunk.getField("mustSave");
this.isTrueForNotSave = false;
} else {
this.mustSave = classChunk.getField("mustNotSave");
}
} else { } else {
RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk"); RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk");
this.mustSave = classChunk.getField("mustNotSave"); this.mustNotSave = classChunk.getField("mustNotSave");
} }
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
e.printStackTrace(); e.printStackTrace();
@ -167,10 +174,13 @@ public class ChunkListener implements Listener {
if (safe && shouldSave(world, chunk.getX(), chunk.getZ())) { if (safe && shouldSave(world, chunk.getX(), chunk.getZ())) {
return false; return false;
} }
Object c = this.methodGetHandleChunk.of(chunk).call(); Object c = objChunkStatusFull != null
RefField.RefExecutor field = this.mustSave.of(c); ? this.methodGetHandleChunk.of(chunk).call(objChunkStatusFull)
if ((Boolean) field.get() != isTrueForNotSave) { : this.methodGetHandleChunk.of(chunk).call();
field.set(isTrueForNotSave); RefField.RefExecutor field = this.mustNotSave.of(c);
methodSetUnsaved.of(c).call(false);
if (!((Boolean) field.get())) {
field.set(true);
if (chunk.isLoaded()) { if (chunk.isLoaded()) {
ignoreUnload = true; ignoreUnload = true;
chunk.unload(false); chunk.unload(false);

View File

@ -152,7 +152,8 @@ public class EntityEventListener implements Listener {
} }
} }
case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL", case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL",
"TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN" -> { "TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN", "NETHER_PORTAL",
"DUPLICATION", "FROZEN", "SPELL" -> {
if (!area.isMobSpawning()) { if (!area.isMobSpawning()) {
event.setCancelled(true); event.setCancelled(true);
return; return;

View File

@ -1167,7 +1167,7 @@ public class PlayerEventListener implements Listener {
} }
} }
if (type.isEdible()) { if (type.isEdible()) {
//Allow all players to eat while also allowing the block place event ot be fired //Allow all players to eat while also allowing the block place event to be fired
return; return;
} }
if (type == Material.ARMOR_STAND) { if (type == Material.ARMOR_STAND) {

View File

@ -31,45 +31,39 @@ import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkEvent; import org.bukkit.event.world.ChunkEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import static com.plotsquared.core.util.ReflectionUtils.getRefClass; 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 methodSetUnsaved;
private Field shouldSave = null; private Method methodGetHandleChunk;
private Object objChunkStatusFull = null;
public SingleWorldListener() throws Exception { public SingleWorldListener() throws Exception {
ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod(); ReflectionUtils.RefClass classChunkAccess = getRefClass("net.minecraft.world.level.chunk.IChunkAccess");
this.methodSetUnsaved = classChunkAccess.getMethod("a", boolean.class).getRealMethod();
try { try {
if (PlotSquared.platform().serverVersion()[1] < 17) { this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle").getRealMethod();
ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk"); } catch (NoSuchMethodException ignored) {
if (PlotSquared.platform().serverVersion()[1] == 13) { try {
this.shouldSave = classChunk.getField("mustSave").getRealField(); ReflectionUtils.RefClass classChunkStatus = getRefClass("net.minecraft.world.level.chunk.ChunkStatus");
} else { this.objChunkStatusFull = classChunkStatus.getRealClass().getField("n").get(null);
this.shouldSave = classChunk.getField("s").getRealField(); this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle", classChunkStatus.getRealClass()).getRealMethod();
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex);
} }
} else if (PlotSquared.platform().serverVersion()[1] == 17) {
ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk");
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) {
e.printStackTrace();
} }
} }
public void markChunkAsClean(Chunk chunk) { public void markChunkAsClean(Chunk chunk) {
try { try {
Object nmsChunk = methodGetHandleChunk.invoke(chunk); Object nmsChunk = objChunkStatusFull != null
if (shouldSave != null) { ? this.methodGetHandleChunk.invoke(chunk, objChunkStatusFull)
this.shouldSave.set(nmsChunk, false); : this.methodGetHandleChunk.invoke(chunk);
} methodSetUnsaved.invoke(nmsChunk, false);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -85,7 +79,12 @@ public class SingleWorldListener implements Listener {
if (!SinglePlotArea.isSinglePlotWorld(name)) { if (!SinglePlotArea.isSinglePlotWorld(name)) {
return; return;
} }
int x = event.getChunk().getX();
int z = event.getChunk().getZ();
if (x < 16 && x > -16 && z < 16 && z > -16) {
// Allow spawn to generate
return;
}
markChunkAsClean(event.getChunk()); markChunkAsClean(event.getChunk());
} }

View File

@ -28,24 +28,38 @@ import java.nio.file.Paths;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
* This is a helper class which replaces occurrences of 'suggest_command' with 'run_command' in messages_%.json. * This is a helper class which replaces older syntax no longer supported by MiniMessage with replacements in messages_%.json.
* MiniMessage changed the syntax between major releases. To warrant a smooth upgrade, we attempt to replace any occurrences * MiniMessage changed the syntax between major releases. To warrant a smooth upgrade, we attempt to replace any occurrences
* while loading PlotSquared. * while loading PlotSquared.
* *
* @since TODO * @since 7.0.0
*/ */
@NotPublic @NotPublic
public class TranslationUpdateManager { public class TranslationUpdateManager {
public static void upgradeTranslationFile() throws IOException { public static void upgradeTranslationFile() throws IOException {
String searchText = "suggest_command"; String suggestCommand = "suggest_command";
String replacementText = "run_command"; String suggestCommandReplacement = "run_command";
String minHeight = "minHeight";
String minheightReplacement = "minheight";
String maxHeight = "maxHeight";
String maxheightReplacement = "maxheight";
String usedGrants = "usedGrants";
String usedGrantsReplacement = "used_grants";
String remainingGrants = "remainingGrants";
String rremainingGrantsReplacement = "remaining_grants";
try (Stream<Path> paths = Files.walk(Paths.get(PlotSquared.platform().getDirectory().toPath().resolve("lang").toUri()))) { try (Stream<Path> paths = Files.walk(Paths.get(PlotSquared.platform().getDirectory().toPath().resolve("lang").toUri()))) {
paths paths
.filter(Files::isRegularFile) .filter(Files::isRegularFile)
.filter(p -> p.getFileName().toString().matches("messages_[a-z]{2}\\.json")) .filter(p -> p.getFileName().toString().matches("messages_[a-z]{2}\\.json"))
.forEach(p -> replaceInFile(p, searchText, replacementText)); .forEach(p -> {
replaceInFile(p, suggestCommand, suggestCommandReplacement);
replaceInFile(p, minHeight, minheightReplacement);
replaceInFile(p, maxHeight, maxheightReplacement);
replaceInFile(p, usedGrants, usedGrantsReplacement);
replaceInFile(p, remainingGrants, rremainingGrantsReplacement);
});
} }
} }

View File

@ -2,18 +2,18 @@ import java.time.format.DateTimeFormatter
dependencies { dependencies {
// Expected everywhere. // Expected everywhere.
compileOnlyApi("org.checkerframework:checker-qual") compileOnlyApi(libs.checkerqual)
// Minecraft expectations // Minecraft expectations
compileOnlyApi("com.google.code.gson:gson") compileOnlyApi(libs.gson)
compileOnly("com.google.guava:guava") compileOnly(libs.guava)
// Platform expectations // Platform expectations
compileOnlyApi("org.yaml:snakeyaml") compileOnlyApi(libs.snakeyaml)
// Adventure // Adventure
api("net.kyori:adventure-api") api(libs.adventureApi)
api("net.kyori:adventure-text-minimessage") api(libs.adventureMiniMessage)
// Guice // Guice
api(libs.guice) { api(libs.guice) {
@ -31,19 +31,19 @@ dependencies {
exclude(group = "dummypermscompat") exclude(group = "dummypermscompat")
} }
testImplementation(libs.worldeditCore) testImplementation(libs.worldeditCore)
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core") { isTransitive = false } compileOnly(libs.faweBukkit) { isTransitive = false }
testImplementation("com.fastasyncworldedit:FastAsyncWorldEdit-Core") { isTransitive = false } testImplementation(libs.faweCore) { isTransitive = false }
// Logging // Logging
compileOnlyApi("org.apache.logging.log4j:log4j-api") compileOnlyApi(libs.log4j)
// 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("com.intellectualsites.paster:Paster") api(libs.paster)
api("com.intellectualsites.informative-annotations:informative-annotations") api(libs.informativeAnnotations)
} }
tasks.processResources { tasks.processResources {
@ -68,8 +68,8 @@ tasks {
val isRelease = if (rootProject.version.toString().endsWith("-SNAPSHOT")) "TODO" else rootProject.version.toString() val isRelease = if (rootProject.version.toString().endsWith("-SNAPSHOT")) "TODO" else rootProject.version.toString()
val opt = options as StandardJavadocDocletOptions val opt = options as StandardJavadocDocletOptions
opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-core/" + libs.worldeditCore.get().versionConstraint.toString()) opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-core/" + libs.worldeditCore.get().versionConstraint.toString())
opt.links("https://jd.advntr.dev/api/4.12.0/") opt.links("https://jd.advntr.dev/api/4.14.0/")
opt.links("https://jd.advntr.dev/text-minimessage/4.12.0/") opt.links("https://jd.advntr.dev/text-minimessage/4.14.0/")
opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/")
opt.links("https://checkerframework.org/api/") opt.links("https://checkerframework.org/api/")
opt.links("https://javadoc.io/doc/com.intellectualsites.informative-annotations/informative-annotations/latest/") opt.links("https://javadoc.io/doc/com.intellectualsites.informative-annotations/informative-annotations/latest/")

View File

@ -1281,7 +1281,7 @@ public class PlotSquared {
} }
/** /**
* Setup the database connection. * Set up the database connection.
*/ */
public void setupDatabase() { public void setupDatabase() {
try { try {

View File

@ -131,8 +131,8 @@ public class Auto extends SubCommand {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.removed_granted_plot"), TranslatableCaption.of("economy.removed_granted_plot"),
TagResolver.builder() TagResolver.builder()
.tag("usedGrants", Tag.inserting(Component.text(grantedPlots - left))) .tag("used_grants", Tag.inserting(Component.text(grantedPlots - left)))
.tag("remainingGrants", Tag.inserting(Component.text(left))) .tag("remaining_grants", Tag.inserting(Component.text(left)))
.build() .build()
); );
} }
@ -294,12 +294,15 @@ public class Auto extends SubCommand {
return true; return true;
} }
} }
if (this.econHandler != null && plotarea.useEconomy()) { if (this.econHandler != null && plotarea.useEconomy() && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON)) {
PlotExpression costExp = plotarea.getPrices().get("claim"); PlotExpression costExp = plotarea.getPrices().get("claim");
PlotExpression mergeCostExp = plotarea.getPrices().get("merge");
int size = sizeX * sizeZ;
double mergeCost = size <= 1 || mergeCostExp == null ? 0d : mergeCostExp.evaluate(size);
double cost = costExp.evaluate(Settings.Limit.GLOBAL ? double cost = costExp.evaluate(Settings.Limit.GLOBAL ?
player.getPlotCount() : player.getPlotCount() :
player.getPlotCount(plotarea.getWorldName())); player.getPlotCount(plotarea.getWorldName()));
cost = (sizeX * sizeZ) * cost; cost = size * cost + mergeCost;
if (cost > 0d) { if (cost > 0d) {
if (!this.econHandler.isSupported()) { if (!this.econHandler.isSupported()) {
player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null"));

View File

@ -141,7 +141,7 @@ public class Claim extends SubCommand {
} }
} }
} }
if (this.econHandler.isEnabled(area) && !force) { if (this.econHandler.isEnabled(area) && !force && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON)) {
PlotExpression costExr = area.getPrices().get("claim"); PlotExpression costExr = area.getPrices().get("claim");
double cost = costExr.evaluate(currentPlots); double cost = costExr.evaluate(currentPlots);
if (cost > 0d) { if (cost > 0d) {
@ -186,8 +186,8 @@ public class Claim extends SubCommand {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.removed_granted_plot"), TranslatableCaption.of("economy.removed_granted_plot"),
TagResolver.builder() TagResolver.builder()
.tag("usedGrants", Tag.inserting(Component.text(grants - 1))) .tag("used_grants", Tag.inserting(Component.text(grants - 1)))
.tag("remainingGrants", Tag.inserting(Component.text(grants))) .tag("remaining_grants", Tag.inserting(Component.text(grants)))
.build() .build()
); );
} }

View File

@ -96,6 +96,7 @@ public class DebugRoadRegen extends SubCommand {
PlotArea area = location.getPlotArea(); PlotArea area = location.getPlotArea();
if (area == null) { if (area == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
return false;
} }
Plot plot = player.getCurrentPlot(); Plot plot = player.getCurrentPlot();
if (plot == null) { if (plot == null) {

View File

@ -112,15 +112,15 @@ public class Kick extends SubCommand {
for (PlotPlayer<?> player2 : players) { for (PlotPlayer<?> player2 : players) {
if (!plot.equals(player2.getCurrentPlot())) { if (!plot.equals(player2.getCurrentPlot())) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("errors.invalid_player"), TranslatableCaption.of("kick.player_not_in_plot"),
TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) TagResolver.resolver("player", Tag.inserting(Component.text(player2.getName())))
); );
return; return;
} }
if (player2.hasPermission(Permission.PERMISSION_ADMIN_ENTRY_DENIED)) { if (player2.hasPermission(Permission.PERMISSION_ADMIN_ENTRY_DENIED)) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("cluster.cannot_kick_player"), TranslatableCaption.of("kick.cannot_kick_player"),
TagResolver.resolver("name", Tag.inserting(Component.text(player2.getName()))) TagResolver.resolver("player", Tag.inserting(Component.text(player2.getName())))
); );
return; return;
} }

View File

@ -183,7 +183,7 @@ public class MainCommand extends Command {
if (cmd.hasConfirmation(player)) { if (cmd.hasConfirmation(player)) {
CmdConfirm.addPending(player, cmd.getUsage(), () -> { CmdConfirm.addPending(player, cmd.getUsage(), () -> {
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();
if (area != null && econHandler.isEnabled(area)) { if (area != null && econHandler.isEnabled(area) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON)) {
PlotExpression priceEval = PlotExpression priceEval =
area.getPrices().get(cmd.getFullId()); area.getPrices().get(cmd.getFullId());
double price = priceEval != null ? priceEval.evaluate(0d) : 0d; double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
@ -201,7 +201,7 @@ public class MainCommand extends Command {
return; return;
} }
PlotArea area = player.getApplicablePlotArea(); PlotArea area = player.getApplicablePlotArea();
if (area != null && econHandler.isEnabled(area)) { if (area != null && econHandler.isEnabled(area) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON)) {
PlotExpression priceEval = area.getPrices().get(cmd.getFullId()); PlotExpression priceEval = area.getPrices().get(cmd.getFullId());
double price = priceEval != null ? priceEval.evaluate(0d) : 0d; double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
if (price != 0d && econHandler.getMoney(player) < price) { if (price != 0d && econHandler.getMoney(player) < price) {

View File

@ -109,7 +109,7 @@ public class Merge extends SubCommand {
} }
} }
if (direction == null && (args[0].equalsIgnoreCase("all") || args[0] if (direction == null && (args[0].equalsIgnoreCase("all") || args[0]
.equalsIgnoreCase("auto"))) { .equalsIgnoreCase("auto")) && player.hasPermission(Permission.PERMISSION_MERGE_ALL)) {
direction = Direction.ALL; direction = Direction.ALL;
} }
} }
@ -178,7 +178,7 @@ public class Merge extends SubCommand {
return true; return true;
} }
if (plot.getPlotModificationManager().autoMerge(Direction.ALL, maxSize, uuid, player, terrain)) { if (plot.getPlotModificationManager().autoMerge(Direction.ALL, maxSize, uuid, player, terrain)) {
if (this.econHandler.isEnabled(plotArea) && price > 0d) { if (this.econHandler.isEnabled(plotArea) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON) && price > 0d) {
this.econHandler.withdrawMoney(player, price); this.econHandler.withdrawMoney(player, price);
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.removed_balance"), TranslatableCaption.of("economy.removed_balance"),
@ -196,8 +196,8 @@ public class Merge extends SubCommand {
player.sendMessage(TranslatableCaption.of("merge.no_available_automerge")); player.sendMessage(TranslatableCaption.of("merge.no_available_automerge"));
return false; return false;
} }
if (!force && this.econHandler.isEnabled(plotArea) && price > 0d if (!force && this.econHandler.isEnabled(plotArea) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON) && price > 0d && this.econHandler.getMoney(
&& this.econHandler.getMoney(player) < price) { player) < price) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.cannot_afford_merge"), TranslatableCaption.of("economy.cannot_afford_merge"),
TagResolver.resolver("money", Tag.inserting(Component.text(this.econHandler.format(price)))) TagResolver.resolver("money", Tag.inserting(Component.text(this.econHandler.format(price))))
@ -218,7 +218,7 @@ public class Merge extends SubCommand {
return true; return true;
} }
if (plot.getPlotModificationManager().autoMerge(direction, maxSize - size, uuid, player, terrain)) { if (plot.getPlotModificationManager().autoMerge(direction, maxSize - size, uuid, player, terrain)) {
if (this.econHandler.isEnabled(plotArea) && price > 0d) { if (this.econHandler.isEnabled(plotArea) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON) && price > 0d) {
this.econHandler.withdrawMoney(player, price); this.econHandler.withdrawMoney(player, price);
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.removed_balance"), TranslatableCaption.of("economy.removed_balance"),
@ -259,7 +259,7 @@ public class Merge extends SubCommand {
accepter.sendMessage(TranslatableCaption.of("merge.merge_not_valid")); accepter.sendMessage(TranslatableCaption.of("merge.merge_not_valid"));
return; return;
} }
if (this.econHandler.isEnabled(plotArea) && price > 0d) { if (this.econHandler.isEnabled(plotArea) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON) && price > 0d) {
if (!force && this.econHandler.getMoney(player) < price) { if (!force && this.econHandler.getMoney(player) < price) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.cannot_afford_merge"), TranslatableCaption.of("economy.cannot_afford_merge"),
@ -303,7 +303,7 @@ public class Merge extends SubCommand {
player, player,
terrain terrain
)) { )) {
if (this.econHandler.isEnabled(plotArea) && price > 0d) { if (this.econHandler.isEnabled(plotArea) && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON) && price > 0d) {
if (!force && this.econHandler.getMoney(player) < price) { if (!force && this.econHandler.getMoney(player) < price) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("economy.cannot_afford_merge"), TranslatableCaption.of("economy.cannot_afford_merge"),

View File

@ -56,7 +56,7 @@ public class Music extends SubCommand {
.asList("music_disc_13", "music_disc_cat", "music_disc_blocks", "music_disc_chirp", .asList("music_disc_13", "music_disc_cat", "music_disc_blocks", "music_disc_chirp",
"music_disc_far", "music_disc_mall", "music_disc_mellohi", "music_disc_stal", "music_disc_far", "music_disc_mall", "music_disc_mellohi", "music_disc_stal",
"music_disc_strad", "music_disc_ward", "music_disc_11", "music_disc_wait", "music_disc_otherside", "music_disc_strad", "music_disc_ward", "music_disc_11", "music_disc_wait", "music_disc_otherside",
"music_disc_pigstep", "music_disc_5" "music_disc_pigstep", "music_disc_5", "music_disc_relic"
); );
private final InventoryUtil inventoryUtil; private final InventoryUtil inventoryUtil;

View File

@ -46,7 +46,7 @@ public class PluginCmd extends SubCommand {
player.sendMessage(StaticCaption.of( player.sendMessage(StaticCaption.of(
"<gray>>> </gray><gold><bold>Authors<reset><gray>: </gray><gold>Citymonstret </gold><gray>& </gray><gold>Empire92 </gold><gray>& </gray><gold>MattBDev </gold><gray>& </gray><gold>dordsor21 </gold><gray>& </gray><gold>NotMyFault </gold><gray>& </gray><gold>SirYwell</gold>")); "<gray>>> </gray><gold><bold>Authors<reset><gray>: </gray><gold>Citymonstret </gold><gray>& </gray><gold>Empire92 </gold><gray>& </gray><gold>MattBDev </gold><gray>& </gray><gold>dordsor21 </gold><gray>& </gray><gold>NotMyFault </gold><gray>& </gray><gold>SirYwell</gold>"));
player.sendMessage(StaticCaption.of( player.sendMessage(StaticCaption.of(
"<gray>>> </gray><gold><bold>Wiki<reset><gray>: </gray><gold><click:open_url:https://intellectualsites.github.io/plotsquared-documentation/>https://intellectualsites.github.io/plotsquared-documentation/</gold>")); "<gray>>> </gray><gold><bold>Wiki<reset><gray>: </gray><gold><click:open_url:https://intellectualsites.gitbook.io/plotsquared/>https://intellectualsites.gitbook.io/plotsquared/</gold>"));
player.sendMessage(StaticCaption.of( player.sendMessage(StaticCaption.of(
"<gray>>> </gray><gold><bold>Discord<reset><gray>: </gray><gold><click:open_url:https://discord.gg/intellectualsites>https://discord.gg/intellectualsites</gold>")); "<gray>>> </gray><gold><bold>Discord<reset><gray>: </gray><gold><click:open_url:https://discord.gg/intellectualsites>https://discord.gg/intellectualsites</gold>"));
player.sendMessage( player.sendMessage(

View File

@ -206,7 +206,7 @@ public class ComponentPresetManager {
return false; return false;
} }
if (componentPreset.cost() > 0.0D) { if (componentPreset.cost() > 0.0D && !player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_ECON)) {
if (!econHandler.isEnabled(plot.getArea())) { if (!econHandler.isEnabled(plot.getArea())) {
getPlayer().sendMessage( getPlayer().sendMessage(
TranslatableCaption.of("preset.economy_disabled"), TranslatableCaption.of("preset.economy_disabled"),

View File

@ -194,7 +194,7 @@ public class Settings extends Config {
public List<String> WORLDS = new ArrayList<>(Collections.singletonList("*")); public List<String> WORLDS = new ArrayList<>(Collections.singletonList("*"));
@Comment("See: https://intellectualsites.github.io/plotsquared-documentation/optimization/plot-analysis for a description of each value.") @Comment("See: https://intellectualsites.gitbook.io/plotsquared/optimization/plot-analysis for a description of each value.")
public static final class CALIBRATION { public static final class CALIBRATION {
public int VARIETY = 0; public int VARIETY = 0;
@ -214,7 +214,7 @@ public class Settings extends Config {
@Comment({"Chunk processor related settings", @Comment({"Chunk processor related settings",
"See https://intellectualsites.github.io/plotsquared-documentation/optimization/chunk-processor for more information."}) "See https://intellectualsites.gitbook.io/plotsquared/optimization/chunk-processor for more information."})
public static class Chunk_Processor { public static class Chunk_Processor {
@Comment("Auto trim will not save chunks which aren't claimed") @Comment("Auto trim will not save chunks which aren't claimed")
@ -280,7 +280,7 @@ public class Settings extends Config {
@Comment("Always show explosion Particles, even if explosion flag is set to false") @Comment("Always show explosion Particles, even if explosion flag is set to false")
public static boolean ALWAYS_SHOW_EXPLOSIONS = false; public static boolean ALWAYS_SHOW_EXPLOSIONS = false;
@Comment({"Blocks that may not be used in plot components", @Comment({"Blocks that may not be used in plot components",
"Checkout the wiki article regarding plot components before modifying: https://intellectualsites.github.io/plotsquared-documentation/customization/plot-components"}) "Checkout the wiki article regarding plot components before modifying: https://intellectualsites.gitbook.io/plotsquared/customization/plot-components"})
public static List<String> public static List<String>
INVALID_BLOCKS = Arrays.asList( INVALID_BLOCKS = Arrays.asList(
// Acacia Stuff // Acacia Stuff
@ -402,7 +402,7 @@ public class Settings extends Config {
@Comment({"Schematic Settings", @Comment({"Schematic Settings",
"See https://intellectualsites.github.io/plotsquared-documentation/schematics/schematic-on-claim for more information."}) "See https://intellectualsites.gitbook.io/plotsquared/schematics/schematic-on-claim for more information."})
public static final class Schematics { public static final class Schematics {
@Comment( @Comment(
@ -531,7 +531,7 @@ public class Settings extends Config {
@Comment({"Backup related settings", @Comment({"Backup related settings",
"See https://intellectualsites.github.io/plotsquared-documentation/plot-backups for more information."}) "See https://intellectualsites.gitbook.io/plotsquared/plot-backups for more information."})
public static final class Backup { public static final class Backup {
@Comment("Automatically backup plots when destructive commands are performed, e.g. /plot clear") @Comment("Automatically backup plots when destructive commands are performed, e.g. /plot clear")
@ -783,7 +783,7 @@ public class Settings extends Config {
public static boolean public static boolean
PERSISTENT_ROAD_REGEN = true; PERSISTENT_ROAD_REGEN = true;
@Comment({"Enable the `/plot component` preset GUI", @Comment({"Enable the `/plot component` preset GUI",
"Read more about components here: https://intellectualsites.github.io/plotsquared-documentation/customization/plot-components"}) "Read more about components here: https://intellectualsites.gitbook.io/plotsquared/customization/plot-components"})
public static boolean COMPONENT_PRESETS = true; public static boolean COMPONENT_PRESETS = true;
@Comment("Enable per user locale") @Comment("Enable per user locale")
public static boolean PER_USER_LOCALE = false; public static boolean PER_USER_LOCALE = false;

View File

@ -40,7 +40,7 @@ public interface Caption {
* *
* @param localeHolder Locale holder * @param localeHolder Locale holder
* @return {@link ComponentLike} * @return {@link ComponentLike}
* @since TODO * @since 7.0.0
*/ */
@NonNull Component toComponent(@NonNull LocaleHolder localeHolder); @NonNull Component toComponent(@NonNull LocaleHolder localeHolder);

View File

@ -51,7 +51,7 @@ public class CaptionHolder {
* Get the {@link TagResolver}s to use when resolving tags in the {@link Caption}. * Get the {@link TagResolver}s to use when resolving tags in the {@link Caption}.
* *
* @return The tag resolvers to use. * @return The tag resolvers to use.
* @since TODO * @since 7.0.0
*/ */
public TagResolver[] getTagResolvers() { public TagResolver[] getTagResolvers() {
return this.tagResolvers; return this.tagResolvers;
@ -61,7 +61,7 @@ public class CaptionHolder {
* Set the {@link TagResolver}s to use when resolving tags in the {@link Caption}. * Set the {@link TagResolver}s to use when resolving tags in the {@link Caption}.
* *
* @param tagResolvers The tag resolvers to use. * @param tagResolvers The tag resolvers to use.
* @since TODO * @since 7.0.0
*/ */
public void setTagResolvers(TagResolver... tagResolvers) { public void setTagResolvers(TagResolver... tagResolvers) {
this.tagResolvers = tagResolvers; this.tagResolvers = tagResolvers;

View File

@ -28,16 +28,20 @@ import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.ParsingException;
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;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern;
import static com.plotsquared.core.configuration.caption.ComponentTransform.nested; import static com.plotsquared.core.configuration.caption.ComponentTransform.nested;
import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks; import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks;
public class CaptionUtility { public class CaptionUtility {
private static final Pattern LEGACY_FORMATTING = Pattern.compile("§[a-gklmnor0-9]");
// flags which values are parsed by minimessage // flags which values are parsed by minimessage
private static final Set<Class<? extends PlotFlag<?, ?>>> MINI_MESSAGE_FLAGS = Set.of( private static final Set<Class<? extends PlotFlag<?, ?>>> MINI_MESSAGE_FLAGS = Set.of(
GreetingFlag.class, GreetingFlag.class,
@ -100,7 +104,14 @@ public class CaptionUtility {
*/ */
public static String stripClickEvents(final @NonNull String miniMessageString) { public static String stripClickEvents(final @NonNull String miniMessageString) {
// parse, transform and serialize again // parse, transform and serialize again
Component component = MiniMessage.miniMessage().deserialize(miniMessageString); Component component;
try {
component = MiniMessage.miniMessage().deserialize(miniMessageString);
} catch (ParsingException e) {
// if the String cannot be parsed, we try stripping legacy colors
String legacyStripped = LEGACY_FORMATTING.matcher(miniMessageString).replaceAll("");
component = MiniMessage.miniMessage().deserialize(legacyStripped);
}
component = CLICK_STRIP_TRANSFORM.transform(component); component = CLICK_STRIP_TRANSFORM.transform(component);
return MiniMessage.miniMessage().serialize(component); return MiniMessage.miniMessage().serialize(component);
} }

View File

@ -19,6 +19,7 @@
package com.plotsquared.core.configuration.file; package com.plotsquared.core.configuration.file;
import com.plotsquared.core.configuration.serialization.ConfigurationSerialization; import com.plotsquared.core.configuration.serialization.ConfigurationSerialization;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.error.YAMLException; import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.Node;
@ -30,6 +31,7 @@ import java.util.Map;
public class YamlConstructor extends SafeConstructor { public class YamlConstructor extends SafeConstructor {
YamlConstructor() { YamlConstructor() {
super(new LoaderOptions());
yamlConstructors.put(Tag.MAP, new ConstructCustomObject()); yamlConstructors.put(Tag.MAP, new ConstructCustomObject());
} }

View File

@ -21,6 +21,7 @@ package com.plotsquared.core.configuration.file;
import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationSection;
import com.plotsquared.core.configuration.serialization.ConfigurationSerializable; import com.plotsquared.core.configuration.serialization.ConfigurationSerializable;
import com.plotsquared.core.configuration.serialization.ConfigurationSerialization; import com.plotsquared.core.configuration.serialization.ConfigurationSerialization;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.representer.Representer; import org.yaml.snakeyaml.representer.Representer;
@ -30,6 +31,7 @@ import java.util.Map;
class YamlRepresenter extends Representer { class YamlRepresenter extends Representer {
YamlRepresenter() { YamlRepresenter() {
super(new DumperOptions());
this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection()); this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection());
this.multiRepresenters this.multiRepresenters
.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable()); .put(ConfigurationSerializable.class, new RepresentConfigurationSerializable());

View File

@ -379,10 +379,11 @@ public class ClassicPlotManager extends SquarePlotManager {
} }
} }
int yStart = classicPlotWorld.getMinBuildHeight() + (classicPlotWorld.PLOT_BEDROCK ? 1 : 0);
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 = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -390,7 +391,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 = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -398,7 +399,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 = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }
@ -406,7 +407,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 = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) {
queue.setBlock(x, y, z, blocks); queue.setBlock(x, y, z, blocks);
} }
} }

View File

@ -69,8 +69,8 @@ public class HybridGen extends IndependentPlotGenerator {
EnumSet<SchematicFeature> features EnumSet<SchematicFeature> features
) { ) {
int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT); int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT);
if ((features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ROAD_ON_TOP) boolean isRoad = features.contains(SchematicFeature.ROAD);
|| (!features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ON_TOP)) { if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) {
minY = world.SCHEM_Y; minY = world.SCHEM_Y;
} else { } else {
minY = world.getMinBuildHeight(); minY = world.getMinBuildHeight();

View File

@ -162,6 +162,7 @@ public class HybridPlotManager extends ClassicPlotManager {
} else { } else {
minY = hybridPlotWorld.getMinBuildHeight(); minY = hybridPlotWorld.getMinBuildHeight();
} }
int schemYDiff = (isRoad ? hybridPlotWorld.getRoadYStart() : hybridPlotWorld.getPlotYStart()) - minY;
BaseBlock airBlock = BlockTypes.AIR.getDefaultState().toBaseBlock(); BaseBlock airBlock = BlockTypes.AIR.getDefaultState().toBaseBlock();
for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int x = pos1.getX(); x <= pos2.getX(); x++) {
short absX = (short) ((x - hybridPlotWorld.ROAD_OFFSET_X) % size); short absX = (short) ((x - hybridPlotWorld.ROAD_OFFSET_X) % size);
@ -178,10 +179,14 @@ public class HybridPlotManager extends ClassicPlotManager {
for (int y = 0; y < blocks.length; y++) { for (int y = 0; y < blocks.length; y++) {
if (blocks[y] != null) { if (blocks[y] != null) {
queue.setBlock(x, minY + y, z, blocks[y]); queue.setBlock(x, minY + y, z, blocks[y]);
} else if (!isRoad) { } else if (y > schemYDiff) {
// This is necessary, otherwise any blocks not specified in the schematic will remain after a clear // This is necessary, otherwise any blocks not specified in the schematic will remain after a clear.
// Do not set air for road as this may cause cavernous roads when debugroadregen is used // This should only be done where the schematic has actually "started"
queue.setBlock(x, minY + y, z, airBlock); queue.setBlock(x, minY + y, z, airBlock);
} else if (isRoad) {
queue.setBlock(x, minY + y, z, hybridPlotWorld.ROAD_BLOCK.toPattern());
} else {
queue.setBlock(x, minY + y, z, hybridPlotWorld.MAIN_BLOCK.toPattern());
} }
} }
} }

View File

@ -76,6 +76,9 @@ public class HybridPlotWorld extends ClassicPlotWorld {
* The Y level at which schematic generation will start, lowest of either road or plot schematic generation. * The Y level at which schematic generation will start, lowest of either road or plot schematic generation.
*/ */
public int SCHEM_Y; public int SCHEM_Y;
private int plotY;
private int roadY;
private Location SIGN_LOCATION; private Location SIGN_LOCATION;
private File root = null; private File root = null;
private int lastOverlayHeightError = Integer.MIN_VALUE; private int lastOverlayHeightError = Integer.MIN_VALUE;
@ -252,68 +255,60 @@ public class HybridPlotWorld extends ClassicPlotWorld {
SCHEM_Y = schematicStartHeight(); SCHEM_Y = schematicStartHeight();
// plotY and roadY are important to allow plot and/or road schematic "overflow" into each other without causing AIOOB // plotY and roadY are important to allow plot and/or road schematic "overflow" into each other
// exceptions when attempting either to set blocks to, or get block from G_SCH // without causing AIOOB exceptions when attempting either to set blocks to, or get block from G_SCH
// Default plot schematic start height, normalized to the minimum height schematics are pasted from. // Default plot schematic start height, normalized to the minimum height schematics are pasted from.
int plotY = PLOT_HEIGHT - SCHEM_Y; 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;
// Default road schematic start height, normalized to the minimum height schematics are pasted from. // Default road schematic start height, normalized to the minimum height schematics are pasted from.
int roadY = minRoadWall - SCHEM_Y; roadY = minRoadWall - SCHEM_Y;
int worldGenHeight = getMaxGenHeight() - getMinGenHeight() + 1; int worldGenHeight = getMaxGenHeight() - getMinGenHeight() + 1;
int maxSchematicHeight = 0;
int plotSchemHeight = 0; int plotSchemHeight = 0;
// SCHEM_Y should be normalised to the plot "start" height // SCHEM_Y should be normalised to the plot "start" height
if (schematic3 != null) { if (schematic3 != null) {
plotSchemHeight = maxSchematicHeight = schematic3.getClipboard().getDimensions().getY(); plotSchemHeight = schematic3.getClipboard().getDimensions().getY();
if (maxSchematicHeight == worldGenHeight) { if (plotSchemHeight == worldGenHeight) {
SCHEM_Y = getMinGenHeight(); SCHEM_Y = getMinGenHeight();
plotY = 0; plotY = 0;
} else if (!Settings.Schematics.PASTE_ON_TOP) { } else if (!Settings.Schematics.PASTE_ON_TOP) {
SCHEM_Y = getMinBuildHeight(); SCHEM_Y = getMinGenHeight();
plotY = 0; plotY = 0;
} }
} }
int roadSchemHeight; int roadSchemHeight = 0;
if (schematic1 != null) { if (schematic1 != null) {
roadSchemHeight = Math.max( roadSchemHeight = Math.max(
schematic1.getClipboard().getDimensions().getY(), schematic1.getClipboard().getDimensions().getY(),
schematic2.getClipboard().getDimensions().getY() schematic2.getClipboard().getDimensions().getY()
); );
maxSchematicHeight = Math.max(roadSchemHeight, maxSchematicHeight); if (roadSchemHeight == worldGenHeight) {
if (maxSchematicHeight == worldGenHeight) {
SCHEM_Y = getMinGenHeight(); SCHEM_Y = getMinGenHeight();
roadY = 0; // Road is the lowest schematic roadY = 0; // Road is the lowest schematic
if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldGenHeight) { if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldGenHeight) {
// Road is the lowest schematic. Normalize plotY to it. // Road is the lowest schematic. Normalize plotY to it.
if (Settings.Schematics.PASTE_ON_TOP) { if (Settings.Schematics.PASTE_ON_TOP) {
plotY = PLOT_HEIGHT - getMinGenHeight(); plotY = PLOT_HEIGHT - getMinGenHeight();
} else {
plotY = getMinBuildHeight() - getMinGenHeight();
} }
} }
} else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) { } else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) {
if (SCHEM_Y == getMinGenHeight()) { // Only possible if plot schematic is enabled roadY = 0;
// Plot is still the lowest schematic, normalize roadY to it SCHEM_Y = getMinGenHeight();
roadY = getMinBuildHeight() - getMinGenHeight(); if (schematic3 != null) {
} else if (schematic3 != null) {
SCHEM_Y = getMinBuildHeight();
roadY = 0;// Road is the lowest schematic
if (Settings.Schematics.PASTE_ON_TOP) { if (Settings.Schematics.PASTE_ON_TOP) {
// Road is the lowest schematic. Normalize plotY to it. // Road is the lowest schematic. Normalize plotY to it.
plotY = PLOT_HEIGHT - getMinBuildHeight(); plotY = PLOT_HEIGHT - SCHEM_Y;
} }
maxSchematicHeight = Math.max(maxSchematicHeight, plotY + plotSchemHeight);
} }
} else { } else {
roadY = minRoadWall - SCHEM_Y; roadY = minRoadWall - SCHEM_Y;
maxSchematicHeight = Math.max(maxSchematicHeight, roadY + roadSchemHeight);
} }
} }
int maxSchematicHeight = Math.max(plotY + plotSchemHeight, roadY + roadSchemHeight);
if (schematic3 != null) { if (schematic3 != null) {
this.PLOT_SCHEMATIC = true; this.PLOT_SCHEMATIC = true;
@ -554,4 +549,24 @@ public class HybridPlotWorld extends ClassicPlotWorld {
return this.root; return this.root;
} }
/**
* Get the y value where the plot schematic should be pasted from.
*
* @return plot schematic y start value
* @since 7.0.0
*/
public int getPlotYStart() {
return SCHEM_Y + plotY;
}
/**
* Get the y value where the road schematic should be pasted from.
*
* @return road schematic y start value
* @since 7.0.0
*/
public int getRoadYStart() {
return SCHEM_Y + roadY;
}
} }

View File

@ -77,6 +77,10 @@ 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(); private static final BlockState AIR = BlockTypes.AIR.getDefaultState();
/**
* Deprecated and likely to be removed in a future release.
*/
@Deprecated(forRemoval = true, since = "7.0.0")
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;
@ -529,7 +533,7 @@ public class HybridUtils {
Math.min(plotworld.PLOT_HEIGHT, Math.min(plotworld.WALL_HEIGHT, plotworld.ROAD_HEIGHT)) : plotworld.ROAD_HEIGHT; Math.min(plotworld.PLOT_HEIGHT, Math.min(plotworld.WALL_HEIGHT, plotworld.ROAD_HEIGHT)) : plotworld.ROAD_HEIGHT;
int sx = bot.getX() - plotworld.ROAD_WIDTH + 1; int sx = bot.getX() - plotworld.ROAD_WIDTH + 1;
int sz = bot.getZ() + 1; int sz = bot.getZ() + 1;
int sy = Settings.Schematics.PASTE_ROAD_ON_TOP ? schemY : plot.getArea().getMinBuildHeight(); int sy = Settings.Schematics.PASTE_ROAD_ON_TOP ? schemY : plot.getArea().getMinGenHeight();
int ex = bot.getX(); int ex = bot.getX();
int ez = top.getZ(); int ez = top.getZ();
int ey = get_ey(plotworld, queue, sx, ex, sz, ez, sy); int ey = get_ey(plotworld, queue, sx, ex, sz, ez, sy);
@ -668,7 +672,7 @@ public class HybridUtils {
} }
if (condition) { if (condition) {
BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ)); BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ));
int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : area.getMinGenHeight() + 1; int minY = plotWorld.getRoadYStart();
int maxDy = Math.max(extend, blocks.length); int maxDy = Math.max(extend, blocks.length);
for (int dy = 0; dy < maxDy; dy++) { for (int dy = 0; dy < maxDy; dy++) {
if (dy > blocks.length - 1) { if (dy > blocks.length - 1) {

View File

@ -46,7 +46,7 @@ public abstract class IndependentPlotGenerator {
* @param result Queue to write to * @param result Queue to write to
* @param settings PlotArea (settings) * @param settings PlotArea (settings)
* @param biomes If biomes should be generated * @param biomes If biomes should be generated
* @since TODO * @since 7.0.0
*/ */
public abstract void generateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea settings, boolean biomes); public abstract void generateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea settings, boolean biomes);
@ -55,7 +55,7 @@ public abstract class IndependentPlotGenerator {
* *
* @param result Queue to write to * @param result Queue to write to
* @param setting PlotArea (settings) * @param setting PlotArea (settings)
* @since TODO * @since 7.0.0
*/ */
public void populateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea setting) { public void populateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea setting) {
} }
@ -108,7 +108,7 @@ public abstract class IndependentPlotGenerator {
* @param y World y position * @param y World y position
* @param z World z position * @param z World z position
* @return Biome type to be generated * @return Biome type to be generated
* @since TODO * @since 7.0.0
*/ */
public abstract BiomeType getBiome(PlotArea settings, int x, int y, int z); public abstract BiomeType getBiome(PlotArea settings, int x, int y, int z);

View File

@ -60,6 +60,19 @@ public final class UncheckedWorldLocation extends Location {
return new UncheckedWorldLocation(world, x, y, z); return new UncheckedWorldLocation(world, x, y, z);
} }
/**
* Construct a new location with yaw and pitch equal to 0
*
* @param world World
* @param loc Coordinates
* @return New location
* @since 7.0.0
*/
@DoNotUse
public static @NonNull UncheckedWorldLocation at(final @NonNull String world, BlockVector3 loc) {
return new UncheckedWorldLocation(world, loc.getX(), loc.getY(), loc.getZ());
}
@Override @Override
@DoNotUse @DoNotUse
public @NonNull String getWorldName() { public @NonNull String getWorldName() {

View File

@ -45,6 +45,7 @@ public enum Permission implements ComponentLike {
PERMISSION_ADMIN_ENTRY_FORCEFIELD("plots.admin.entry.forcefield"), PERMISSION_ADMIN_ENTRY_FORCEFIELD("plots.admin.entry.forcefield"),
PERMISSION_ADMIN_COMMANDS_CHATSPY("plots.admin.command.chatspy"), PERMISSION_ADMIN_COMMANDS_CHATSPY("plots.admin.command.chatspy"),
PERMISSION_MERGE("plots.merge"), PERMISSION_MERGE("plots.merge"),
PERMISSION_MERGE_ALL("plots.merge.all"),
PERMISSION_MERGE_OTHER("plots.merge.other"), PERMISSION_MERGE_OTHER("plots.merge.other"),
PERMISSION_MERGE_KEEP_ROAD("plots.merge.keeproad"), PERMISSION_MERGE_KEEP_ROAD("plots.merge.keeproad"),
PERMISSION_ADMIN_CAPS_OTHER("plots.admin.caps.other"), PERMISSION_ADMIN_CAPS_OTHER("plots.admin.caps.other"),
@ -200,7 +201,8 @@ public enum Permission implements ComponentLike {
PERMISSION_RATE("plots.rate"), PERMISSION_RATE("plots.rate"),
PERMISSION_ADMIN_FLIGHT("plots.admin.flight"), PERMISSION_ADMIN_FLIGHT("plots.admin.flight"),
PERMISSION_ADMIN_COMPONENTS_OTHER("plots.admin.component.other"), PERMISSION_ADMIN_COMPONENTS_OTHER("plots.admin.component.other"),
PERMISSION_ADMIN_BYPASS_BORDER("plots.admin.border.bypass"); PERMISSION_ADMIN_BYPASS_BORDER("plots.admin.border.bypass"),
PERMISSION_ADMIN_BYPASS_ECON("plots.admin.econ.bypass");
//</editor-fold> //</editor-fold>
private final String text; private final String text;

View File

@ -180,8 +180,7 @@ public abstract class PlotArea implements ComponentLike {
this.worldConfiguration = worldConfiguration; this.worldConfiguration = worldConfiguration;
} }
private static Collection<PlotFlag<?, ?>> parseFlags(List<String> flagStrings) { private static void parseFlags(FlagContainer flagContainer, List<String> flagStrings) {
final Collection<PlotFlag<?, ?>> flags = new ArrayList<>();
for (final String key : flagStrings) { for (final String key : flagStrings) {
final String[] split; final String[] split;
if (key.contains(";")) { if (key.contains(";")) {
@ -193,7 +192,7 @@ public abstract class PlotArea implements ComponentLike {
GlobalFlagContainer.getInstance().getFlagFromString(split[0]); GlobalFlagContainer.getInstance().getFlagFromString(split[0]);
if (flagInstance != null) { if (flagInstance != null) {
try { try {
flags.add(flagInstance.parse(split[1])); flagContainer.addFlag(flagInstance.parse(split[1]));
} catch (final FlagParseException e) { } catch (final FlagParseException e) {
LOGGER.warn( LOGGER.warn(
"Failed to parse default flag with key '{}' and value '{}'. " "Failed to parse default flag with key '{}' and value '{}'. "
@ -204,9 +203,10 @@ public abstract class PlotArea implements ComponentLike {
); );
e.printStackTrace(); e.printStackTrace();
} }
} else {
flagContainer.addUnknownFlag(split[0], split[1]);
} }
} }
return flags;
} }
@NonNull @NonNull
@ -405,7 +405,7 @@ public abstract class PlotArea implements ComponentLike {
} }
} }
} }
this.getFlagContainer().addAll(parseFlags(flags)); parseFlags(this.getFlagContainer(), flags);
ConsolePlayer.getConsole().sendMessage( ConsolePlayer.getConsole().sendMessage(
TranslatableCaption.of("flags.area_flags"), TranslatableCaption.of("flags.area_flags"),
TagResolver.resolver("flags", Tag.inserting(Component.text(flags.toString()))) TagResolver.resolver("flags", Tag.inserting(Component.text(flags.toString())))
@ -427,7 +427,7 @@ public abstract class PlotArea implements ComponentLike {
} }
} }
this.roadFlags = roadflags.size() > 0; this.roadFlags = roadflags.size() > 0;
this.getRoadFlagContainer().addAll(parseFlags(roadflags)); parseFlags(this.getRoadFlagContainer(), roadflags);
ConsolePlayer.getConsole().sendMessage( ConsolePlayer.getConsole().sendMessage(
TranslatableCaption.of("flags.road_flags"), TranslatableCaption.of("flags.road_flags"),
TagResolver.resolver("flags", Tag.inserting(Component.text(roadflags.toString()))) TagResolver.resolver("flags", Tag.inserting(Component.text(roadflags.toString())))
@ -657,9 +657,9 @@ public abstract class PlotArea implements ComponentLike {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("height.height_limit"), TranslatableCaption.of("height.height_limit"),
TagResolver.builder() TagResolver.builder()
.tag("minHeight", Tag.inserting(Component.text(minBuildHeight))) .tag("minheight", Tag.inserting(Component.text(minBuildHeight)))
.tag( .tag(
"maxHeight", "maxheight",
Tag.inserting(Component.text(maxBuildHeight)) Tag.inserting(Component.text(maxBuildHeight))
).build() ).build()
); );

View File

@ -91,6 +91,7 @@ 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;
import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag;
import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag; import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
import com.plotsquared.core.plot.flag.implementations.SnowFormFlag; import com.plotsquared.core.plot.flag.implementations.SnowFormFlag;
import com.plotsquared.core.plot.flag.implementations.SnowMeltFlag; import com.plotsquared.core.plot.flag.implementations.SnowMeltFlag;
@ -172,6 +173,7 @@ public final class GlobalFlagContainer extends FlagContainer {
this.addFlag(MobBreakFlag.MOB_BREAK_FALSE); this.addFlag(MobBreakFlag.MOB_BREAK_FALSE);
this.addFlag(MobPlaceFlag.MOB_PLACE_FALSE); this.addFlag(MobPlaceFlag.MOB_PLACE_FALSE);
this.addFlag(MiscInteractFlag.MISC_INTERACT_FALSE); this.addFlag(MiscInteractFlag.MISC_INTERACT_FALSE);
this.addFlag(SculkSensorInteractFlag.SCULK_SENSOR_INTERACT_FALSE);
this.addFlag(MiscPlaceFlag.MISC_PLACE_FALSE); this.addFlag(MiscPlaceFlag.MISC_PLACE_FALSE);
this.addFlag(MycelGrowFlag.MYCEL_GROW_TRUE); this.addFlag(MycelGrowFlag.MYCEL_GROW_TRUE);
this.addFlag(NotifyEnterFlag.NOTIFY_ENTER_FALSE); this.addFlag(NotifyEnterFlag.NOTIFY_ENTER_FALSE);

View File

@ -88,7 +88,7 @@ public abstract class PlotFlag<T, F extends PlotFlag<T, F>> {
* Gets the flag name as a Kyori {@link Component} * Gets the flag name as a Kyori {@link Component}
* *
* @see #getFlagName(Class) * @see #getFlagName(Class)
* @since TODO * @since 7.0.0
*/ */
public static <T, F extends PlotFlag<T, F>> Component getFlagNameComponent(Class<F> flagClass) { public static <T, F extends PlotFlag<T, F>> Component getFlagNameComponent(Class<F> flagClass) {
return Component.text(getFlagName(flagClass)); return Component.text(getFlagName(flagClass));

View File

@ -0,0 +1,39 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.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 SculkSensorInteractFlag extends BooleanFlag<SculkSensorInteractFlag> {
public static final SculkSensorInteractFlag SCULK_SENSOR_INTERACT_TRUE = new SculkSensorInteractFlag(true);
public static final SculkSensorInteractFlag SCULK_SENSOR_INTERACT_FALSE = new SculkSensorInteractFlag(false);
private SculkSensorInteractFlag(boolean value) {
super(value, TranslatableCaption.of("flags.flag_description_sculk_sensor_interact"));
}
@Override
protected SculkSensorInteractFlag flagOf(@NonNull Boolean value) {
return value ? SCULK_SENSOR_INTERACT_TRUE : SCULK_SENSOR_INTERACT_FALSE;
}
}

View File

@ -29,17 +29,17 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Singleton @Singleton
public class DefaultPlotAreaManager implements PlotAreaManager { public class DefaultPlotAreaManager implements PlotAreaManager {
final PlotArea[] noPlotAreas = new PlotArea[0]; final PlotArea[] noPlotAreas = new PlotArea[0];
private final Map<String, PlotWorld> plotWorlds = new HashMap<>(); private final Map<String, PlotWorld> plotWorlds = new ConcurrentHashMap<>();
@Override @Override
public @NonNull PlotArea[] getAllPlotAreas() { public @NonNull PlotArea[] getAllPlotAreas() {

View File

@ -111,7 +111,7 @@ public interface PlotAreaManager {
* *
* @param worldName Name of the world to add * @param worldName Name of the world to add
* @return {@code true} if successful, {@code false} if world already existed * @return {@code true} if successful, {@code false} if world already existed
* @since TODO * @since 7.0.0
*/ */
boolean addWorld(@NonNull String worldName); boolean addWorld(@NonNull String worldName);

View File

@ -66,7 +66,7 @@ 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 ZeroedDelegateScopedQueueCoordinator} * @return a new {@link ZeroedDelegateScopedQueueCoordinator}
* @since TODO * @since 7.0.0
*/ */
public ZeroedDelegateScopedQueueCoordinator getForChunk(int x, int z, int minY, int maxY) { public ZeroedDelegateScopedQueueCoordinator getForChunk(int x, int z, int minY, int maxY) {
int bx = x << 4; int bx = x << 4;

View File

@ -32,7 +32,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* zero 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 * zero 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. * x and z.
* *
* @since TODO * @since 7.0.0
*/ */
public class ZeroedDelegateScopedQueueCoordinator extends DelegateQueueCoordinator { public class ZeroedDelegateScopedQueueCoordinator extends DelegateQueueCoordinator {
@ -50,7 +50,7 @@ public class ZeroedDelegateScopedQueueCoordinator extends DelegateQueueCoordinat
/** /**
* Create a new ScopedQueueCoordinator instance that delegates to a given QueueCoordinator. Locations are inclusive. * Create a new ScopedQueueCoordinator instance that delegates to a given QueueCoordinator. Locations are inclusive.
* *
* @since TODO * @since 7.0.0
*/ */
public ZeroedDelegateScopedQueueCoordinator(@Nullable QueueCoordinator parent, @NonNull Location min, @NonNull Location max) { public ZeroedDelegateScopedQueueCoordinator(@Nullable QueueCoordinator parent, @NonNull Location min, @NonNull Location max) {
super(parent); super(parent);

View File

@ -36,7 +36,7 @@ public abstract class ChunkManager {
private static final Map<BlockVector2, RunnableVal<ZeroedDelegateScopedQueueCoordinator>> addChunks = new ConcurrentHashMap<>(); private static final Map<BlockVector2, RunnableVal<ZeroedDelegateScopedQueueCoordinator>> addChunks = new ConcurrentHashMap<>();
/** /**
* @since TODO * @since 7.0.0
*/ */
public static void setChunkInPlotArea( public static void setChunkInPlotArea(
RunnableVal<ZeroedDelegateScopedQueueCoordinator> force, RunnableVal<ZeroedDelegateScopedQueueCoordinator> force,
@ -76,7 +76,7 @@ public abstract class ChunkManager {
} }
/** /**
* @since TODO * @since 7.0.0
*/ */
public static boolean preProcessChunk(BlockVector2 loc, ZeroedDelegateScopedQueueCoordinator queue) { public static boolean preProcessChunk(BlockVector2 loc, ZeroedDelegateScopedQueueCoordinator queue) {
final RunnableVal<ZeroedDelegateScopedQueueCoordinator> forceChunk = forceChunks.get(loc); final RunnableVal<ZeroedDelegateScopedQueueCoordinator> forceChunk = forceChunks.get(loc);
@ -89,7 +89,7 @@ public abstract class ChunkManager {
} }
/** /**
* @since TODO * @since 7.0.0
*/ */
public static boolean postProcessChunk(BlockVector2 loc, ZeroedDelegateScopedQueueCoordinator queue) { public static boolean postProcessChunk(BlockVector2 loc, ZeroedDelegateScopedQueueCoordinator queue) {
final RunnableVal<ZeroedDelegateScopedQueueCoordinator> addChunk = forceChunks.get(loc); final RunnableVal<ZeroedDelegateScopedQueueCoordinator> addChunk = forceChunks.get(loc);

View File

@ -27,7 +27,7 @@ import java.util.Collection;
/** /**
* A utility class for modifying components. * A utility class for modifying components.
* *
* @since TODO * @since 7.0.0
*/ */
public class ComponentHelper { public class ComponentHelper {
@ -37,7 +37,7 @@ public class ComponentHelper {
* @param components The components to join * @param components The components to join
* @param delimiter The delimiter to use between the components * @param delimiter The delimiter to use between the components
* @return The joined components * @return The joined components
* @since TODO * @since 7.0.0
*/ */
public static ComponentLike join(Collection<? extends ComponentLike> components, Component delimiter) { public static ComponentLike join(Collection<? extends ComponentLike> components, Component delimiter) {
return join(components.toArray(ComponentLike[]::new), delimiter); return join(components.toArray(ComponentLike[]::new), delimiter);
@ -49,7 +49,7 @@ public class ComponentHelper {
* @param components The components to join * @param components The components to join
* @param delimiter The delimiter to use between the components * @param delimiter The delimiter to use between the components
* @return The joined components * @return The joined components
* @since TODO * @since 7.0.0
*/ */
public static Component join(ComponentLike[] components, Component delimiter) { public static Component join(ComponentLike[] components, Component delimiter) {
TextComponent.Builder builder = Component.text(); TextComponent.Builder builder = Component.text();

View File

@ -41,7 +41,7 @@
"cluster.cluster_deleted": "<prefix><dark_aqua>Successfully deleted the cluster </dark_aqua><gold><cluster></gold><dark_aqua>.</dark_aqua>", "cluster.cluster_deleted": "<prefix><dark_aqua>Successfully deleted the cluster </dark_aqua><gold><cluster></gold><dark_aqua>.</dark_aqua>",
"cluster.cluster_resized": "<prefix><dark_aqua>Successfully resized the cluster.</dark_aqua>", "cluster.cluster_resized": "<prefix><dark_aqua>Successfully resized the cluster.</dark_aqua>",
"cluster.cluster_added_user": "<prefix><dark_aqua>Successfully added user to the cluster.</dark_aqua>", "cluster.cluster_added_user": "<prefix><dark_aqua>Successfully added user to the cluster.</dark_aqua>",
"cluster.cannot_kick_player": "<prefix><red>You cannot kick that player: </red><gray><name></gray>", "cluster.cannot_kick_player": "<prefix><red>You cannot kick the player <gray><name></gray>.</red>",
"cluster.cluster_invited": "<prefix><gold>You have been invited to the following cluster: </gold><gray><cluster>.</gray>", "cluster.cluster_invited": "<prefix><gold>You have been invited to the following cluster: </gold><gray><cluster>.</gray>",
"cluster.cluster_removed": "<prefix><gold>You have been removed from cluster: </gold><gray><cluster>.</gray>", "cluster.cluster_removed": "<prefix><gold>You have been removed from cluster: </gold><gray><cluster>.</gray>",
"cluster.cluster_kicked_user": "<prefix><dark_aqua>Successfully kicked the user from the cluster.</dark_aqua>", "cluster.cluster_kicked_user": "<prefix><dark_aqua>Successfully kicked the user from the cluster.</dark_aqua>",
@ -124,7 +124,7 @@
"economy.cannot_afford_merge": "<prefix><red>You cannot afford to merge the plots. It costs <gold><money></gold>.</red>", "economy.cannot_afford_merge": "<prefix><red>You cannot afford to merge the plots. It costs <gold><money></gold>.</red>",
"economy.added_balance": "<prefix><gold><money> </gold><gray>has been added to your balance.</gray>", "economy.added_balance": "<prefix><gold><money> </gold><gray>has been added to your balance.</gray>",
"economy.removed_balance": "<prefix><gold><money> </gold><gray>has been taken from your balance.</gray>", "economy.removed_balance": "<prefix><gold><money> </gold><gray>has been taken from your balance.</gray>",
"economy.removed_granted_plot": "<prefix><gray>You used <usedGrants> plot grant(s), you've got </gray><gold><remainingGrants></gold> <gray>left.</gray>", "economy.removed_granted_plot": "<prefix><gray>You used <used_grants> plot grant(s), you've got </gray><gold><remaining_grants></gold> <gray>left.</gray>",
"setup.choose_generator": "<gold>What generator do you want?</gold>", "setup.choose_generator": "<gold>What generator do you want?</gold>",
"setup.setup_not_started": "<prefix><gold>No setup started.</gold>", "setup.setup_not_started": "<prefix><gold>No setup started.</gold>",
"setup.setup_init": "<prefix><gold>Usage: </gold><gray>/plot setup <value></gray>", "setup.setup_init": "<prefix><gold>Usage: </gold><gray>/plot setup <value></gray>",
@ -411,6 +411,8 @@
"deny.no_enter": "<prefix><red>You are denied from the plot <red><gold><plot></gold><red> and therefore not allowed to enter.</red>", "deny.no_enter": "<prefix><red>You are denied from the plot <red><gold><plot></gold><red> and therefore not allowed to enter.</red>",
"deny.you_got_denied": "<prefix><red>You are denied from the plot you were previously on, and got teleported to spawn.</red>", "deny.you_got_denied": "<prefix><red>You are denied from the plot you were previously on, and got teleported to spawn.</red>",
"deny.cant_remove_owner": "<prefix><red>You can't remove the plot owner.</red>", "deny.cant_remove_owner": "<prefix><red>You can't remove the plot owner.</red>",
"kick.player_not_in_plot": "<prefix><red>The player <gray><player></gray> is not on this plot.</red>",
"kick.cannot_kick_player": "<prefix><red>You cannot kick the player <gray><player></gray>.</red>",
"kick.you_got_kicked": "<prefix><dark_aqua>You got kicked from the plot!</dark_aqua>", "kick.you_got_kicked": "<prefix><dark_aqua>You got kicked from the plot!</dark_aqua>",
"trusted.trusted_added": "<prefix><dark_aqua>You successfully trusted a user to the plot.</dark_aqua>", "trusted.trusted_added": "<prefix><dark_aqua>You successfully trusted a user to the plot.</dark_aqua>",
"trusted.plot_removed_user": "<prefix><red>Plot <plot> of which you were added to has been deleted due to owner inactivity.</red>", "trusted.plot_removed_user": "<prefix><red>Plot <plot> of which you were added to has been deleted due to owner inactivity.</red>",
@ -486,7 +488,7 @@
"single.get_position": "<prefix><gold>Go to the first corner and use: <gray><command> to create position 1.</gold>", "single.get_position": "<prefix><gold>Go to the first corner and use: <gray><command> to create position 1.</gold>",
"single.delete_world_region": "<prefix><red>Stop the server and delete: <world>/region.</red>", "single.delete_world_region": "<prefix><red>Stop the server and delete: <world>/region.</red>",
"single.regeneration_complete": "<prefix><gold>Regeneration complete.</gold>", "single.regeneration_complete": "<prefix><gold>Regeneration complete.</gold>",
"single.worldcreation_location": "<prefix><gold>World creation settings may be stored in multiple locations:</gold>\n<dark_gray> - </dark_gray><gray>bukkit.yml in your server's root folder.</gray>\n<dark_gray> - </dark_gray><gray>PlotSquared's settings.yml</gray>\n<dark_gray> - </dark_gray><gray>Hyperverse's worlds.yml (or any world management plugin)</gray>\n<dark_gray> - </dark_gray><red>Stop the server and delete it from these locations.</red>", "single.worldcreation_location": "<prefix><gold>World creation settings may be stored in multiple locations:</gold>\n<dark_gray> - </dark_gray><gray>bukkit.yml in your server's root folder.</gray>\n<dark_gray> - </dark_gray><gray>PlotSquared's worlds.yml</gray>\n<dark_gray> - </dark_gray><gray>Hyperverse's worlds.yml (or any world management plugin)</gray>\n<dark_gray> - </dark_gray><red>Stop the server and delete it from these locations.</red>",
"legacyconfig.legacy_config_found": "<prefix><green>A legacy configuration file was detected. Conversion will be attempted.</green>", "legacyconfig.legacy_config_found": "<prefix><green>A legacy configuration file was detected. Conversion will be attempted.</green>",
"legacyconfig.legacy_config_backup": "<prefix><gold>A copy of worlds.yml has been saved in the file worlds.yml.old</gold>.", "legacyconfig.legacy_config_backup": "<prefix><gold>A copy of worlds.yml has been saved in the file worlds.yml.old</gold>.",
"legacyconfig.legacy_config_replaced": "<prefix><gray><value1> has been replaced with <value2></gray>", "legacyconfig.legacy_config_replaced": "<prefix><gray><value1> has been replaced with <value2></gray>",
@ -572,6 +574,7 @@
"flags.flag_description_misc_break": "<gray>Set to `true` to allow guests to break miscellaneous items.</gray>", "flags.flag_description_misc_break": "<gray>Set to `true` to allow guests to break miscellaneous items.</gray>",
"flags.flag_description_misc_cap": "<gray>Set to an integer value to limit the amount of miscellaneous entities on the plot.</gray>", "flags.flag_description_misc_cap": "<gray>Set to an integer value to limit the amount of miscellaneous entities on the plot.</gray>",
"flags.flag_description_misc_interact": "<gray>Set to `true` to allow guests to interact with miscellaneous items.</gray>", "flags.flag_description_misc_interact": "<gray>Set to `true` to allow guests to interact with miscellaneous items.</gray>",
"flags.flag_description_sculk_sensor_interact": "<gray>Set to `true` to allow guests to interact with sculk sensors.</gray>",
"flags.flag_description_misc_place": "<gray>Set to `true` to allow guests to place miscellaneous items.</gray>", "flags.flag_description_misc_place": "<gray>Set to `true` to allow guests to place miscellaneous items.</gray>",
"flags.flag_description_mob_break": "<gray>Set to `true` to allow mobs to break blocks within the plot.</gray>", "flags.flag_description_mob_break": "<gray>Set to `true` to allow mobs to break blocks within the plot.</gray>",
"flags.flag_description_mob_cap": "<gray>Set to an integer value to limit the amount of mobs on the plot.</gray>", "flags.flag_description_mob_cap": "<gray>Set to an integer value to limit the amount of mobs on the plot.</gray>",

View File

@ -27,16 +27,16 @@ is to provide a lag-free and smooth experience.
* [Download](https://www.spigotmc.org/resources/77506/) * [Download](https://www.spigotmc.org/resources/77506/)
* [Discord](https://discord.gg/intellectualsites) * [Discord](https://discord.gg/intellectualsites)
* [Wiki](https://intellectualsites.github.io/plotsquared-documentation/) * [Wiki](https://intellectualsites.gitbook.io/plotsquared/)
* [Issues](https://github.com/IntellectualSites/PlotSquared/issues) * [Issues](https://github.com/IntellectualSites/PlotSquared/issues)
* [Translations](https://intellectualsites.crowdin.com/plotsquared/) * [Translations](https://intellectualsites.crowdin.com/plotsquared/)
* [Contributing](https://github.com/IntellectualSites/.github/blob/main/CONTRIBUTING.md) * [Contributing](https://github.com/IntellectualSites/.github/blob/main/CONTRIBUTING.md)
### Developer Resources ### Developer Resources
* [API Documentation](https://intellectualsites.github.io/plotsquared-documentation/api/api-documentation) * [API Documentation](https://intellectualsites.gitbook.io/plotsquared/api/api-documentation)
* [Event API](https://intellectualsites.github.io/plotsquared-documentation/api/event-api) * [Event API](https://intellectualsites.gitbook.io/plotsquared/api/event-api)
* [Flag API](https://intellectualsites.github.io/plotsquared-documentation/api/flag-api) * [Flag API](https://intellectualsites.gitbook.io/plotsquared/api/flag-api)
# Official Addons # Official Addons

View File

@ -17,11 +17,11 @@ plugins {
eclipse eclipse
idea idea
id("xyz.jpenilla.run-paper") version "2.1.0" alias(libs.plugins.runPaper)
} }
group = "com.plotsquared" group = "com.intellectualsites.plotsquared"
version = "7.0.0-SNAPSHOT" version = "7.0.0"
if (!File("$rootDir/.git").exists()) { if (!File("$rootDir/.git").exists()) {
logger.lifecycle(""" logger.lifecycle("""
@ -76,13 +76,9 @@ subprojects {
plugin<IdeaPlugin>() plugin<IdeaPlugin>()
} }
dependencies {
implementation(platform("com.intellectualsites.bom:bom-newest:1.27"))
}
dependencies { dependencies {
// Tests // Tests
testImplementation("org.junit.jupiter:junit-jupiter:5.9.3") testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
} }
plugins.withId("java") { plugins.withId("java") {
@ -210,7 +206,7 @@ subprojects {
} }
nexusPublishing { nexusPublishing {
repositories { this.repositories {
sonatype { sonatype {
nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/")) nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/")) snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
@ -222,12 +218,12 @@ tasks.getByName<Jar>("jar") {
enabled = false enabled = false
} }
val supportedVersions = listOf("1.16.5", "1.17", "1.17.1", "1.18.2", "1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4") val supportedVersions = listOf("1.16.5", "1.17", "1.17.1", "1.18.2", "1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20")
tasks { tasks {
supportedVersions.forEach { supportedVersions.forEach {
register<RunServer>("runServer-$it") { register<RunServer>("runServer-$it") {
minecraftVersion(it) minecraftVersion(it)
pluginJars(*project(":PlotSquared-Bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } pluginJars(*project(":plotsquared-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile }
.toTypedArray()) .toTypedArray())
jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true") jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true")
group = "run paper" group = "run paper"

View File

@ -1,13 +1,22 @@
[versions] [versions]
# Platform expectations # Platform expectations
guice = "5.1.0" paper = "1.20.1-R0.1-SNAPSHOT"
guice = "7.0.0"
spotbugs = "4.7.3" spotbugs = "4.7.3"
checkerqual = "3.37.0"
gson = "2.10"
guava = "31.1-jre"
snakeyaml = "2.0"
adventure = "4.14.0"
adventure-bukkit = "4.3.0"
log4j = "2.19.0"
# Plugins # Plugins
worldedit = "7.2.14" worldedit = "7.2.15"
fawe = "2.7.0"
placeholderapi = "2.11.3" placeholderapi = "2.11.3"
luckperms = "5.4" luckperms = "5.4"
essentialsx = "2.19.7" essentialsx = "2.20.1"
mvdwapi = "3.1.1" mvdwapi = "3.1.1"
# Third party # Third party
@ -16,18 +25,34 @@ aopalliance = "1.0"
cloud-services = "1.8.3" cloud-services = "1.8.3"
arkitektonika = "2.1.2" arkitektonika = "2.1.2"
squirrelid = "0.3.2" squirrelid = "0.3.2"
paster = "1.1.5"
bstats = "3.0.2"
paperlib = "1.0.8"
informative-annotations = "1.3"
vault = "1.7.1"
serverlib = "2.3.1"
# Gradle plugins # Gradle plugins
shadow = "7.1.2" shadow = "8.1.1"
grgit = "4.1.1" grgit = "4.1.1"
spotless = "6.18.0" spotless = "6.20.0"
nexus = "1.3.0" nexus = "1.3.0"
runPaper = "2.1.0"
[libraries] [libraries]
# Platform expectations # Platform expectations
paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper" }
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" }
spotbugs = { group = "com.github.spotbugs", name = "spotbugs-annotations", version.ref = "spotbugs" } spotbugs = { group = "com.github.spotbugs", name = "spotbugs-annotations", version.ref = "spotbugs" }
checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" }
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
snakeyaml = { group = "org.yaml", name = "snakeyaml", version.ref = "snakeyaml" }
adventureApi = { group = "net.kyori", name = "adventure-api", version.ref = "adventure" }
adventureMiniMessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventure" }
adventureBukkit = { group = "net.kyori", name = "adventure-platform-bukkit", version.ref = "adventure-bukkit" }
log4j = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" }
# Plugins # Plugins
worldeditCore = { group = "com.sk89q.worldedit", name = "worldedit-core", version.ref = "worldedit" } worldeditCore = { group = "com.sk89q.worldedit", name = "worldedit-core", version.ref = "worldedit" }
@ -35,6 +60,8 @@ worldeditBukkit = { group = "com.sk89q.worldedit", name = "worldedit-bukkit", ve
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" }
faweCore = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Core", version.ref = "fawe" }
faweBukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukkit", version.ref = "fawe" }
# Third party # Third party
prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" }
@ -43,9 +70,17 @@ cloudServices = { group = "cloud.commandframework", name = "cloud-services", ver
mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" }
squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" }
arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" }
paster = { group = "com.intellectualsites.paster", name = "Paster", version.ref = "paster" }
bstatsBase = { group = "org.bstats", name = "bstats-base", version.ref = "bstats" }
bstatsBukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "bstats" }
informativeAnnotations = { group = "com.intellectualsites.informative-annotations", name = "informative-annotations", version.ref = "informative-annotations" }
paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" }
vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" }
serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" }
[plugins] [plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" } grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" } nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" }
runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }

Binary file not shown.

View File

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

15
gradlew vendored
View File

@ -83,10 +83,8 @@ done
# This is normally unused # This is normally unused
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -133,10 +131,13 @@ location of your Java installation."
fi fi
else else
JAVACMD=java JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
@ -197,6 +198,10 @@ if "$cygwin" || "$msys" ; then
done done
fi fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command; # Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in # shell script including quotes and variable substitutions, so put them in

View File

@ -1,4 +1,4 @@
Javadocs generated for Javadocs generated for
<a href="https://github.com/IntellectualSites/PlotSquared/" rel="noopener nofollow noreferrer" target="_blank"> PlotSquared</a> | <a href="https://github.com/IntellectualSites/PlotSquared/" rel="noopener nofollow noreferrer" target="_blank"> PlotSquared</a> |
<a href="https://intellectualsites.github.io/plotsquared-documentation/" rel="noopener nofollow noreferrer"> Documentation </a> | <a href="https://intellectualsites.gitbook.io/plotsquared/" rel="noopener nofollow noreferrer"> Documentation </a> |
Visit us on our <a href="https://discord.gg/intellectualsites" rel="noopener nofollow noreferrer"> Discord server</a> :) Visit us on our <a href="https://discord.gg/intellectualsites" rel="noopener nofollow noreferrer"> Discord server</a> :)

View File

@ -1,12 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
":semanticCommitsDisabled"
],
"labels": [
"dependencies"
],
"rebaseWhen": "conflicted",
"schedule": ["on the first day of the month"]
}

View File

@ -2,7 +2,7 @@ rootProject.name = "PlotSquared"
include("Core", "Bukkit") include("Core", "Bukkit")
project(":Core").name = "PlotSquared-Core" project(":Core").name = "plotsquared-core"
project(":Bukkit").name = "PlotSquared-Bukkit" project(":Bukkit").name = "plotsquared-bukkit"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")