Compare commits

..

69 Commits
7.4.2 ... 7.5.4

Author SHA1 Message Date
fe1ef36f7e Release 7.5.4
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-06 17:52:21 +02:00
70bc02985f fix: allow cauldron in use flag to behave as expected (#4673) 2025-07-06 17:49:42 +02:00
3ec7e992a3 Update junit-framework monorepo (#4689)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 15:01:17 +00:00
9acaa9c554 Update dependency gradle to v8.14.3 (#4688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 15:00:50 +00:00
e132c01331 Update dependency com.gradleup.shadow to v8.3.8 (#4686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 16:45:35 +00:00
24e4e51884 Update dependency org.checkerframework:checker-qual to v3.49.5 (#4684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 19:35:10 +00:00
84ec090df1 fix: Add entity cap check of armor stands & end crystals into player interact listener (#4654)
When cancelled in the creature spawn event and placed by a player, the player will lose the armor stand / end crystal item from their inventory. This PR aims to fix this by moving the verification whether the entity should be cancelled up to the spawn egg right click, this way the item is not touched.
2025-06-26 17:35:40 +01:00
6c6ea1c1b4 Update dependency org.junit.jupiter:junit-jupiter to v5.13.2 (#4679)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 19:54:47 +00:00
97989face1 Update dependency org.junit.platform:junit-platform-launcher to v1.13.2 (#4680)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 13:51:13 +00:00
f471c02330 Update dependency com.gradleup.shadow to v8.3.7 (#4678)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 03:03:11 +00:00
94322d5982 Update dependency com.vanniktech.maven.publish to v0.33.0 (#4676)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-22 17:57:31 +00:00
6cbb894249 Fix/plot info syntax message (#4671)
* Adding plot-info category messages

* Use plot-info category list from language config
2025-06-15 12:42:06 +02:00
6f0fa19601 Update junit5 monorepo (#4667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 09:06:38 +00:00
0b692459e6 Update dependency gradle to v8.14.2 (#4666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 15:26:03 +00:00
0d410ed869 Update dependency org.checkerframework:checker-qual to v3.49.4 (#4665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 21:02:18 +00:00
711fba0b2a Update junit5 monorepo (#4662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 12:06:20 +00:00
671a27fa6f Update dependency com.diffplug.spotless to v7.0.4 (#4661)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-27 22:39:24 +00:00
03de685dc4 Update dependency net.essentialsx:EssentialsX to v2.21.1 (#4660)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-25 21:59:36 +00:00
f616885206 Update dependency net.luckperms:api to v5.5 (#4659)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-25 10:29:47 +00:00
7da4eb1ab5 fix: correctly parse help messages with prefix (#4652) 2025-05-24 14:39:31 +02:00
629646ab06 fix: cancel structure locate in classic plot worlds (#4653) 2025-05-24 14:39:14 +02:00
74a1a1f954 Update dependency gradle to v8.14.1 (#4658)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 17:04:52 +00:00
aa44078018 Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-05-18 19:30:24 +02:00
bfbf406418 Release 7.5.3
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-05-18 19:27:33 +02:00
2accedf264 fix: Don't use list to proof block is copper. Instead check with name (#4641)
* fix: Don't use list to proof block is copper. Instead check with name

* chore: Code-Cleanup
2025-05-18 14:04:39 +02:00
6ef0d58480 fix: cancel teleport to denied plot (#4650)
* chore: add 1.21.5 to runServer task, download Paper FAWE jar

* fix: don't allow teleport to denied plots
2025-05-18 14:03:51 +02:00
fbf4a638b4 chore/fix: use #getBlock in PlayerBucketEmptyEvent (#4651)
chore/fix: use #getBlock method for block retrieval in PlayerBucketEmptyEvent
2025-05-18 14:03:28 +02:00
9abfa21078 Add 'world' placeholder to status messages (#4632)
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-05-17 23:20:03 +02:00
b84599b4b3 Add server brand to debugpaste (#4640)
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-05-17 23:18:52 +02:00
058983cdd5 Update dependency com.vanniktech.maven.publish to v0.32.0 (#4648)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-14 19:09:18 +00:00
6ba3694121 Update dependency net.kyori:adventure-platform-bukkit to v4.4.0 (#4646)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-11 02:14:59 +00:00
8e8e31b80e Update dependency org.checkerframework:checker-qual to v3.49.3 (#4643)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 17:47:32 +00:00
da2e66c1f8 Update adventure to v4.21.0 (#4642)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 08:27:55 +00:00
d5d6fcb859 Update dependency gradle to v8.14 (#4638)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 12:06:27 +00:00
96f73331f9 Update dependency com.intellectualsites.paster:Paster to v1.1.7 (#4635)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 13:07:09 +00:00
020947d90c Update dependency com.intellectualsites.arkitektonika:Arkitektonika-Client to v2.1.4 (#4634)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 13:06:42 +00:00
7dbd0bcff8 Update dependency com.intellectualsites.informative-annotations:informative-annotations to v1.6 (#4633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 21:57:17 +00:00
9626302f04 Remove snapshot repositories (#4631)
* Remove snapshot repositories

Signed-off-by: Alexander Brandes <mc.cache@web.de>

* Update Papi location

Signed-off-by: Alexander Brandes <mc.cache@web.de>

---------

Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-04-21 11:34:11 +02:00
1b4a347e8b Move to new publishing portal (#4630)
* Move to new publishing portal

Signed-off-by: Alexander Brandes <mc.cache@web.de>

* Use new variables

Signed-off-by: Alexander Brandes <mc.cache@web.de>

* Try snapshot

Signed-off-by: Alexander Brandes <mc.cache@web.de>

* Back to main

Signed-off-by: Alexander Brandes <mc.cache@web.de>

---------

Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-04-20 22:20:30 +02:00
19e6ed4b9b Update dependency dev.notmyfault.serverlib:ServerLib to v2.3.7 (#4629)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-19 22:46:38 +00:00
6b1b0f2d6a Update junit5 monorepo (#4628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 16:43:06 +00:00
e499bc02ec Update dependency com.diffplug.spotless to v7.0.3 (#4626)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 03:19:23 +00:00
62084fffdd Fix bad PlotPlayer#getUUID() javadocs
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-04-06 22:01:57 +02:00
d012f79349 Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-04-06 21:51:17 +02:00
139d6efc70 Release 7.5.2
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-04-06 21:49:08 +02:00
6f5cb917f2 Update adventure to v4.20.0 (#4625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 21:25:07 +00:00
9bf66f1b7c Update dependency org.checkerframework:checker-qual to v3.49.2 (#4623)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 21:38:21 +00:00
92875ebe7f Update dependency net.essentialsx:EssentialsX to v2.21.0 (#4621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 22:56:51 +00:00
25a4545f14 Update dependency com.github.spotbugs:spotbugs-annotations to v4.9.3 (#4618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 06:33:24 +00:00
3fdeed019b Update junit5 monorepo (#4617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-14 14:40:52 +00:00
f3400df811 fix: plot entry trigger on teleport (#4593) 2025-03-05 19:43:27 +00:00
beb7cb40f4 Update dependency org.checkerframework:checker-qual to v3.49.1 (#4614)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 22:26:52 +00:00
2c0bb03e5c Update dependency com.github.spotbugs:spotbugs-annotations to v4.9.2 (#4613)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 21:56:49 +00:00
e8c170686c Fix IndexOutOfBoundsException on BlockFertilizeEvent (#4609) 2025-02-28 10:11:54 +01:00
ff8676cde3 Execute chunk loading operations outside the main thread (#4522)
* Wait with further command execution until chunk will be loaded

* Replaced `Throwable#printStackTraces` with `Logger#error`

* Moved from jetbrains to javax annotations

* Use preferred logging
2025-02-28 09:10:38 +00:00
817effb735 Update dependency gradle to v8.13 (#4610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 13:14:17 +00:00
a0a3d8828a Back to snapshot for development 2025-02-23 20:57:47 +00:00
8741bfcf88 Release 7.5.1 2025-02-23 20:46:30 +00:00
6a6c113e5b fix: use orTimeout instead of completing null in chunk coordinator 2025-02-23 20:25:17 +00:00
3f573b4d46 Update fawe to v2.13.0 (#4607)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-23 14:35:55 +00:00
2f6db9c3db Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-02-23 11:27:30 +01:00
2f050b7b47 Release 7.5.0
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-02-23 11:25:22 +01:00
eb0d854870 fix: allow queues to not generate chunks (#4599)
- initially apply to regenallroads
 - additionally add a 10s timeout for requesting a chunk before resubmitting it to the queue
 - addresses #4310
2025-02-23 11:21:18 +01:00
d4f10422e3 1.21.4 (#4582)
* chore: bump api to 1.21.4

* fix: replace (removed) constants with backwards compatible alternatives

* chore: cleanup import

* chore: update javadoc link for paper

* chore: i like this more

* fix: check for vehicle

* chore: compile against 1.20.4 again

* chore: add 1.21.4 to bug report issue template

* chore: add 1.21.4 to runServer supported versions array

* chore: update entity type enum name switch

* chore: remove 1.18 from supportedVersions for runServer task

* fix: attempt to update ReplicatingEntityWrapper

* fix/chore: missing boat handling on spawn

* chore: cleanup imports
2025-02-23 11:20:33 +01:00
4e2ea67992 fix: update error message of /p remove <player> if player does not need to be removed (#4592) 2025-02-22 19:25:49 +00:00
f533e194f4 Update junit5 monorepo (#4598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-21 14:18:09 +00:00
98bc2e7407 Update adventure to v4.19.0 (#4597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 03:18:04 +00:00
1b9d0d5317 Improve teleport behavior for home command (#4369) 2025-02-15 15:29:21 +00:00
8bb15d5c65 Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-02-12 21:15:51 +01:00
45 changed files with 652 additions and 405 deletions

View File

@ -27,6 +27,7 @@ body:
description: Which server version are you using? If your server version is not listed, it is not supported. Update to a supported version first.
multiple: false
options:
- '1.21.4'
- '1.21.3'
- '1.21.1'
- '1.20.6'

View File

@ -29,18 +29,18 @@ jobs:
fi
- name: Publish Release
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}
- name: Publish Snapshot
if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run: ./gradlew publishToSonatype
run: ./gradlew publishAllPublicationsToMavenCentralRepository
env:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }}
- name: Publish core javadoc
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}}
uses: cpina/github-action-push-to-another-repository@main

View File

@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
repositories {
maven {
name = "PlaceholderAPI"
url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/")
url = uri("https://repo.extendedclip.com/releases/")
}
maven {
@ -39,7 +39,9 @@ dependencies {
}
compileOnly(libs.placeholderapi)
compileOnly(libs.luckperms)
compileOnly(libs.essentialsx)
compileOnly(libs.essentialsx) {
exclude(group = "org.spigotmc")
}
compileOnly(libs.mvdwapi) { isTransitive = false }
// Other libraries
@ -101,7 +103,7 @@ tasks {
withType<Javadoc> {
val isRelease = if (rootProject.version.toString().endsWith("-SNAPSHOT")) "TODO" else rootProject.version.toString()
val opt = options as StandardJavadocDocletOptions
opt.links("https://jd.papermc.io/paper/1.20/")
opt.links("https://jd.papermc.io/paper/1.20.4/")
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://jd.advntr.dev/api/" + libs.adventureApi.get().versionConstraint.toString())

View File

@ -252,6 +252,11 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
return Bukkit.getVersion();
}
@Override
public @NonNull String serverBrand() {
return Bukkit.getName();
}
@Override
@SuppressWarnings("deprecation") // Paper deprecation
public void onEnable() {
@ -789,22 +794,23 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
if (entity.getMetadata("ps_custom_spawned").stream().anyMatch(MetadataValue::asBoolean)) {
continue;
}
// TODO: use (type) pattern matching when targeting java 21
switch (entity.getType().toString()) {
case "EGG":
case "FISHING_HOOK":
case "ENDER_SIGNAL":
case "FISHING_HOOK", "FISHING_BOBBER":
case "ENDER_SIGNAL", "EYE_OF_ENDER":
case "AREA_EFFECT_CLOUD":
case "EXPERIENCE_ORB":
case "LEASH_HITCH":
case "FIREWORK":
case "LIGHTNING":
case "LEASH_HITCH", "LEASH_KNOT":
case "FIREWORK", "FIREWORK_ROCKET":
case "LIGHTNING", "LIGHTNING_BOLT":
case "WITHER_SKULL":
case "UNKNOWN":
case "PLAYER":
// non moving / unmovable
continue;
case "THROWN_EXP_BOTTLE":
case "SPLASH_POTION":
case "THROWN_EXP_BOTTLE", "EXPERIENCE_BOTTLE":
case "SPLASH_POTION", "POTION":
case "SNOWBALL":
case "SHULKER_BULLET":
case "SPECTRAL_ARROW":
@ -836,6 +842,11 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
case "TNT_MINECART":
case "CHEST_BOAT":
case "BOAT":
case "ACACIA_BOAT", "BIRCH_BOAT", "CHERRY_BOAT", "DARK_OAK_BOAT", "JUNGLE_BOAT", "MANGROVE_BOAT",
"OAK_BOAT", "PALE_OAK_BOAT", "SPRUCE_BOAT", "BAMBOO_RAFT":
case "ACACIA_CHEST_BOAT", "BIRCH_CHEST_BOAT", "CHERRY_CHEST_BOAT", "DARK_OAK_CHEST_BOAT",
"JUNGLE_CHEST_BOAT", "MANGROVE_CHEST_BOAT", "OAK_CHEST_BOAT", "PALE_OAK_CHEST_BOAT",
"SPRUCE_CHEST_BOAT", "BAMBOO_CHEST_RAFT":
if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) {
com.plotsquared.core.location.Location location = BukkitUtil.adapt(entity.getLocation());
Plot plot = location.getPlot();
@ -864,14 +875,14 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
case "SMALL_FIREBALL":
case "FIREBALL":
case "DRAGON_FIREBALL":
case "DROPPED_ITEM":
case "DROPPED_ITEM", "ITEM":
if (Settings.Enabled_Components.KILL_ROAD_ITEMS
&& plotArea.getOwnedPlotAbs(BukkitUtil.adapt(entity.getLocation())) == null) {
this.removeRoadEntity(entity, iterator);
}
// dropped item
continue;
case "PRIMED_TNT":
case "PRIMED_TNT", "TNT":
case "FALLING_BLOCK":
// managed elsewhere
continue;
@ -949,7 +960,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
case "HORSE":
case "IRON_GOLEM":
case "MAGMA_CUBE":
case "MUSHROOM_COW":
case "MUSHROOM_COW", "MOOSHROOM":
case "OCELOT":
case "PIG":
case "PIG_ZOMBIE":
@ -958,7 +969,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
case "SILVERFISH":
case "SKELETON":
case "SLIME":
case "SNOWMAN":
case "SNOWMAN", "SNOW_GOLEM":
case "SPIDER":
case "SQUID":
case "VILLAGER":

View File

@ -25,7 +25,6 @@ import org.bukkit.Art;
import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.Rotation;
import org.bukkit.TreeSpecies;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.AbstractHorse;
@ -34,6 +33,7 @@ import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Bat;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Breedable;
import org.bukkit.entity.ChestBoat;
import org.bukkit.entity.ChestedHorse;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
@ -44,7 +44,6 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Rabbit;
import org.bukkit.entity.Sheep;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Tameable;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.InventoryHolder;
@ -103,11 +102,19 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
this.noGravity = true;
}
switch (entity.getType().toString()) {
case "BOAT" -> {
case "BOAT", "ACACIA_BOAT", "BIRCH_BOAT", "CHERRY_BOAT", "DARK_OAK_BOAT", "JUNGLE_BOAT", "MANGROVE_BOAT",
"OAK_BOAT", "PALE_OAK_BOAT", "SPRUCE_BOAT", "BAMBOO_RAFT" -> {
Boat boat = (Boat) entity;
this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType());
this.dataByte = getOrdinal(Boat.Type.values(), boat.getBoatType());
return;
}
case "ACACIA_CHEST_BOAT", "BIRCH_CHEST_BOAT", "CHERRY_CHEST_BOAT", "DARK_OAK_CHEST_BOAT",
"JUNGLE_CHEST_BOAT", "MANGROVE_CHEST_BOAT", "OAK_CHEST_BOAT", "PALE_OAK_CHEST_BOAT",
"SPRUCE_CHEST_BOAT", "BAMBOO_CHEST_RAFT" -> {
ChestBoat boat = (ChestBoat) entity;
this.dataByte = getOrdinal(Boat.Type.values(), boat.getBoatType());
storeInventory(boat);
}
case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "EXPERIENCE_ORB", "FALLING_BLOCK", "FIREBALL",
"FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND", "MINECART_MOB_SPAWNER",
"MINECART_TNT", "PLAYER", "PRIMED_TNT", "SLIME", "SMALL_FIREBALL", "SNOWBALL", "MINECART_FURNACE", "SPLASH_POTION",
@ -117,7 +124,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
return;
}
// MISC //
case "DROPPED_ITEM" -> {
case "DROPPED_ITEM", "ITEM" -> {
Item item = (Item) entity;
this.stack = item.getItemStack();
return;
@ -147,14 +154,14 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
}
// END MISC //
// INVENTORY HOLDER //
case "MINECART_CHEST", "MINECART_HOPPER" -> {
case "MINECART_CHEST", "CHEST_MINECART", "MINECART_HOPPER", "HOPPER_MINECART" -> {
storeInventory((InventoryHolder) entity);
return;
}
// START LIVING ENTITY //
// START AGEABLE //
// START TAMEABLE //
case "HORSE", "DONKEY", "LLAMA", "MULE", "SKELETON_HORSE" -> {
case "CAMEL", "HORSE", "DONKEY", "LLAMA", "TRADER_LLAMA", "MULE", "SKELETON_HORSE", "ZOMBIE_HORSE" -> {
AbstractHorse horse = (AbstractHorse) entity;
this.horse = new HorseStats();
this.horse.jump = horse.getJumpStrength();
@ -172,14 +179,13 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
return;
}
// END INVENTORY HOLDER //
case "WOLF", "OCELOT" -> {
case "WOLF", "OCELOT", "CAT", "PARROT" -> {
storeTameable((Tameable) entity);
storeBreedable((Breedable) entity);
storeLiving((LivingEntity) entity);
return;
}
// END TAMEABLE //
//todo fix sheep
case "SHEEP" -> {
Sheep sheep = (Sheep) entity;
if (sheep.isSheared()) {
@ -187,7 +193,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
} else {
this.dataByte = (byte) 0;
}
this.dataByte2 = sheep.getColor().getDyeData();
this.dataByte2 = getOrdinal(DyeColor.values(), sheep.getColor());
storeBreedable(sheep);
storeLiving(sheep);
return;
@ -268,7 +274,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
}
case "SKELETON", "WITHER_SKELETON", "GUARDIAN", "ELDER_GUARDIAN", "GHAST", "MAGMA_CUBE", "SQUID", "PIG_ZOMBIE", "HOGLIN",
"ZOMBIFIED_PIGLIN", "PIGLIN", "PIGLIN_BRUTE", "ZOMBIE", "WITHER", "WITCH", "SPIDER", "CAVE_SPIDER", "SILVERFISH",
"GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SHULKER", "SNOWMAN" -> {
"GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SHULKER", "SNOWMAN", "SNOW_GOLEM" -> {
storeLiving((LivingEntity) entity);
return;
}
@ -450,7 +456,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
}
Entity entity;
switch (this.getType().toString()) {
case "DROPPED_ITEM" -> {
case "DROPPED_ITEM", "ITEM" -> {
return world.dropItem(location, this.stack);
}
case "PLAYER", "LEASH_HITCH" -> {
@ -486,15 +492,25 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
entity.setGravity(false);
}
switch (entity.getType().toString()) {
case "BOAT" -> {
case "BOAT", "ACACIA_BOAT", "BIRCH_BOAT", "CHERRY_BOAT", "DARK_OAK_BOAT", "JUNGLE_BOAT", "MANGROVE_BOAT",
"OAK_BOAT", "PALE_OAK_BOAT", "SPRUCE_BOAT", "BAMBOO_RAFT" -> {
Boat boat = (Boat) entity;
boat.setWoodType(TreeSpecies.values()[dataByte]);
boat.setBoatType(Boat.Type.values()[dataByte]);
return entity;
}
case "SLIME" -> {
case "ACACIA_CHEST_BOAT", "BIRCH_CHEST_BOAT", "CHERRY_CHEST_BOAT", "DARK_OAK_CHEST_BOAT",
"JUNGLE_CHEST_BOAT", "MANGROVE_CHEST_BOAT", "OAK_CHEST_BOAT", "PALE_OAK_CHEST_BOAT",
"SPRUCE_CHEST_BOAT", "BAMBOO_CHEST_RAFT" -> {
ChestBoat boat = (ChestBoat) entity;
boat.setBoatType(Boat.Type.values()[dataByte]);
restoreInventory(boat);
return entity;
}
// SLIME is not even stored
/* case "SLIME" -> {
((Slime) entity).setSize(this.dataByte);
return entity;
}
} */
case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "DROPPED_ITEM", "EXPERIENCE_ORB", "FALLING_BLOCK",
"FIREBALL", "FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND",
"MINECART_MOB_SPAWNER", "MINECART_TNT", "PLAYER", "PRIMED_TNT", "SMALL_FIREBALL", "SNOWBALL",
@ -518,14 +534,14 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
}
// END MISC //
// INVENTORY HOLDER //
case "MINECART_CHEST", "MINECART_HOPPER" -> {
case "MINECART_CHEST", "CHEST_MINECART", "MINECART_HOPPER", "HOPPER_MINECART" -> {
restoreInventory((InventoryHolder) entity);
return entity;
}
// START LIVING ENTITY //
// START AGEABLE //
// START TAMEABLE //
case "HORSE", "LLAMA", "SKELETON_HORSE", "DONKEY", "MULE" -> {
case "CAMEL", "HORSE", "DONKEY", "LLAMA", "TRADER_LLAMA", "MULE", "SKELETON_HORSE", "ZOMBIE_HORSE" -> {
AbstractHorse horse = (AbstractHorse) entity;
horse.setJumpStrength(this.horse.jump);
if (horse instanceof ChestedHorse) {
@ -542,7 +558,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
return entity;
}
// END INVENTORY HOLDER //
case "WOLF", "OCELOT" -> {
case "WOLF", "OCELOT", "CAT", "PARROT" -> {
restoreTameable((Tameable) entity);
restoreBreedable((Breedable) entity);
restoreLiving((LivingEntity) entity);
@ -555,7 +571,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper {
sheep.setSheared(true);
}
if (this.dataByte2 != 0) {
sheep.setColor(DyeColor.getByDyeData(this.dataByte2));
sheep.setColor(DyeColor.values()[this.dataByte2]);
}
restoreBreedable(sheep);
restoreLiving(sheep);

View File

@ -28,7 +28,6 @@ import com.plotsquared.core.plot.flag.implementations.CopperOxideFlag;
import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag;
import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag;
import com.plotsquared.core.util.PlotFlagUtil;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
@ -42,31 +41,11 @@ import org.bukkit.event.block.BlockReceiveGameEvent;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@SuppressWarnings("unused")
public class BlockEventListener117 implements Listener {
private static final Set<Material> COPPER_OXIDIZING = Set.of(
Material.COPPER_BLOCK,
Material.EXPOSED_COPPER,
Material.WEATHERED_COPPER,
Material.OXIDIZED_COPPER,
Material.CUT_COPPER,
Material.EXPOSED_CUT_COPPER,
Material.WEATHERED_CUT_COPPER,
Material.OXIDIZED_CUT_COPPER,
Material.CUT_COPPER_STAIRS,
Material.EXPOSED_CUT_COPPER_STAIRS,
Material.WEATHERED_CUT_COPPER_STAIRS,
Material.OXIDIZED_CUT_COPPER_STAIRS,
Material.CUT_COPPER_SLAB,
Material.EXPOSED_CUT_COPPER_SLAB,
Material.WEATHERED_CUT_COPPER_SLAB,
Material.OXIDIZED_CUT_COPPER_SLAB
);
@Inject
public BlockEventListener117() {
}
@ -134,7 +113,7 @@ public class BlockEventListener117 implements Listener {
public void onBlockFertilize(BlockFertilizeEvent event) {
Block block = event.getBlock();
List<org.bukkit.block.BlockState> blocks = event.getBlocks();
Location location = BukkitUtil.adapt(blocks.get(0).getLocation());
Location location = BukkitUtil.adapt(block.getLocation());
PlotArea area = location.getPlotArea();
if (area == null) {
@ -184,7 +163,7 @@ public class BlockEventListener117 implements Listener {
if (plot == null) {
return;
}
if (COPPER_OXIDIZING.contains(event.getNewState().getType())) {
if (event.getNewState().getType().name().contains("COPPER")) {
if (!plot.getFlag(CopperOxideFlag.class)) {
plot.debug("Copper could not oxide because copper-oxide = false");
event.setCancelled(true);

View File

@ -42,6 +42,7 @@ import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlotFlagUtil;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.util.Enums;
import com.sk89q.worldedit.world.block.BlockType;
import io.papermc.lib.PaperLib;
import org.bukkit.Material;
@ -57,6 +58,7 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.Vehicle;
import org.bukkit.entity.minecart.ExplosiveMinecart;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -78,10 +80,17 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@SuppressWarnings("unused")
public class EntityEventListener implements Listener {
private static final Particle EXPLOSION_HUGE = Objects.requireNonNull(Enums.findByValue(
Particle.class,
"EXPLOSION_EMITTER",
"EXPLOSION_HUGE"
));
private final BukkitPlatform platform;
private final PlotAreaManager plotAreaManager;
private final EventDispatcher eventDispatcher;
@ -152,8 +161,8 @@ public class EntityEventListener implements Listener {
}
}
case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL",
"TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN", "NETHER_PORTAL",
"FROZEN", "SPELL", "DEFAULT" -> {
"TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN", "NETHER_PORTAL",
"FROZEN", "SPELL", "DEFAULT" -> {
if (!area.isMobSpawning()) {
event.setCancelled(true);
return;
@ -314,7 +323,7 @@ public class EntityEventListener implements Listener {
if (this.lastRadius != 0) {
List<Entity> nearby = event.getEntity().getNearbyEntities(this.lastRadius, this.lastRadius, this.lastRadius);
for (Entity near : nearby) {
if (near instanceof TNTPrimed || near.getType().equals(EntityType.MINECART_TNT)) {
if (near instanceof TNTPrimed || near instanceof ExplosiveMinecart) {
if (!near.hasMetadata("plot")) {
near.setMetadata("plot", new FixedMetadataValue((Plugin) PlotSquared.platform(), plot));
}
@ -338,7 +347,7 @@ public class EntityEventListener implements Listener {
event.setCancelled(true);
//Spawn Explosion Particles when enabled in settings
if (Settings.General.ALWAYS_SHOW_EXPLOSIONS) {
event.getLocation().getWorld().spawnParticle(Particle.EXPLOSION_HUGE, event.getLocation(), 0);
event.getLocation().getWorld().spawnParticle(EXPLOSION_HUGE, event.getLocation(), 0);
}
}

View File

@ -31,8 +31,10 @@ import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -132,7 +134,7 @@ public class EntitySpawnListener implements Listener {
Plot plot = location.getOwnedPlotAbs();
EntityType type = entity.getType();
if (plot == null) {
if (type == EntityType.DROPPED_ITEM) {
if (entity instanceof Item) {
if (Settings.Enabled_Components.KILL_ROAD_ITEMS) {
event.setCancelled(true);
}
@ -154,7 +156,7 @@ public class EntitySpawnListener implements Listener {
if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) {
event.setCancelled(true);
}
if (type == EntityType.ENDER_CRYSTAL || type == EntityType.ARMOR_STAND) {
if (entity instanceof EnderCrystal || type == EntityType.ARMOR_STAND) {
if (BukkitEntityUtil.checkEntity(entity, plot)) {
event.setCancelled(true);
}

View File

@ -29,6 +29,7 @@ import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent;
import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent;
import com.google.inject.Inject;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.command.Command;
import com.plotsquared.core.command.MainCommand;
import com.plotsquared.core.configuration.Settings;
@ -38,6 +39,7 @@ import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.flag.FlagContainer;
import com.plotsquared.core.plot.flag.implementations.BeaconEffectsFlag;
import com.plotsquared.core.plot.flag.implementations.DoneFlag;
@ -48,10 +50,12 @@ import com.plotsquared.core.plot.flag.types.BooleanFlag;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.PlotFlagUtil;
import io.papermc.paper.event.entity.EntityMoveEvent;
import io.papermc.paper.event.world.StructuresLocateEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.bukkit.Chunk;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.TileState;
import org.bukkit.entity.Entity;
@ -80,6 +84,9 @@ import java.util.regex.Pattern;
@SuppressWarnings("unused")
public class PaperListener implements Listener {
private static final NamespacedKey ITEM = NamespacedKey.minecraft("item");
private static final NamespacedKey FISHING_BOBBER = NamespacedKey.minecraft("fishing_bobber");
private final PlotAreaManager plotAreaManager;
private Chunk lastChunk;
@ -228,7 +235,7 @@ public class PaperListener implements Listener {
if (plot == null) {
EntityType type = event.getType();
// PreCreatureSpawnEvent **should** not be called for DROPPED_ITEM, just for the sake of consistency
if (type == EntityType.DROPPED_ITEM) {
if (type.getKey().equals(ITEM)) {
if (Settings.Enabled_Components.KILL_ROAD_ITEMS) {
event.setCancelled(true);
}
@ -354,7 +361,7 @@ public class PaperListener implements Listener {
event.setCancelled(true);
}
} else if (!plot.isAdded(pp.getUUID())) {
if (entity.getType().equals(EntityType.FISHING_HOOK)) {
if (entity.getType().getKey().equals(FISHING_BOBBER)) {
if (plot.getFlag(FishingFlag.class)) {
return;
}
@ -454,6 +461,21 @@ public class PaperListener implements Listener {
}
}
/**
* Don't let the server die when populating cartographers (villager offering maps) in classic plot worlds
* (as those don't generate POIs)
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onStructuresLocate(StructuresLocateEvent event) {
if (!PlotSquared.get().getPlotAreaManager().hasPlotArea(event.getWorld().getName())) {
return;
}
final PlotArea area = PlotSquared.get().getPlotAreaManager().getPlotAreaByString(event.getWorld().getName());
if (area != null && area.getType() == PlotAreaType.NORMAL) {
event.setCancelled(true);
}
}
private boolean getBooleanFlagValue(
@NonNull FlagContainer container,
@NonNull Class<? extends BooleanFlag<?>> flagClass,

View File

@ -64,9 +64,11 @@ import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
import com.plotsquared.core.plot.flag.implementations.TamedInteractFlag;
import com.plotsquared.core.plot.flag.implementations.TileDropFlag;
import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag;
import com.plotsquared.core.plot.flag.implementations.UseFlag;
import com.plotsquared.core.plot.flag.implementations.VehicleBreakFlag;
import com.plotsquared.core.plot.flag.implementations.VehicleUseFlag;
import com.plotsquared.core.plot.flag.implementations.VillagerInteractFlag;
import com.plotsquared.core.plot.flag.types.BlockTypeWrapper;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.MathMan;
@ -78,6 +80,7 @@ import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import io.papermc.lib.PaperLib;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
@ -88,10 +91,8 @@ import org.bukkit.Bukkit;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Boat;
@ -154,9 +155,11 @@ import org.bukkit.util.Vector;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -181,6 +184,7 @@ public class PlayerEventListener implements Listener {
Material.WRITTEN_BOOK
);
private static final Set<String> DYES;
static {
Set<String> mutableDyes = new HashSet<>(Set.of(
"WHITE_DYE",
@ -215,7 +219,7 @@ public class PlayerEventListener implements Listener {
// "temporary" fix for https://hub.spigotmc.org/jira/browse/SPIGOT-7813
// can (and should) be removed when 1.21 support is dropped
// List of all interactable 1.21 materials
INTERACTABLE_MATERIALS = Material.CHEST.isInteractable() ? null : Set.of(
INTERACTABLE_MATERIALS = Material.CHEST.isInteractable() ? null : Set.of(
"REDSTONE_ORE", "DEEPSLATE_REDSTONE_ORE", "CHISELED_BOOKSHELF", "DECORATED_POT", "CHEST", "CRAFTING_TABLE",
"FURNACE", "JUKEBOX", "OAK_FENCE", "SPRUCE_FENCE", "BIRCH_FENCE", "JUNGLE_FENCE", "ACACIA_FENCE", "CHERRY_FENCE",
"DARK_OAK_FENCE", "MANGROVE_FENCE", "BAMBOO_FENCE", "CRIMSON_FENCE", "WARPED_FENCE", "PUMPKIN",
@ -376,7 +380,7 @@ public class PlayerEventListener implements Listener {
@EventHandler
public void onVehicleEntityCollision(VehicleEntityCollisionEvent e) {
if (e.getVehicle().getType() == EntityType.BOAT) {
if (e.getVehicle() instanceof Boat) {
Location location = BukkitUtil.adapt(e.getEntity().getLocation());
if (location.isPlotArea()) {
if (e.getEntity() instanceof Player) {
@ -533,12 +537,14 @@ public class PlayerEventListener implements Listener {
// Delayed
// Async
TaskManager.runTaskLaterAsync(() -> {
if (!player.hasPlayedBefore() && player.isOnline()) {
player.saveData();
}
this.eventDispatcher.doJoinTask(pp);
}, TaskTime.seconds(1L));
TaskManager.runTaskLaterAsync(
() -> {
if (!player.hasPlayedBefore() && player.isOnline()) {
player.saveData();
}
this.eventDispatcher.doJoinTask(pp);
}, TaskTime.seconds(1L)
);
if (pp.hasPermission(Permission.PERMISSION_ADMIN_UPDATE_NOTIFICATION.toString()) && Settings.Enabled_Components.UPDATE_NOTIFICATIONS
&& PremiumVerification.isPremium() && UpdateUtility.hasUpdate) {
@ -593,14 +599,20 @@ public class PlayerEventListener implements Listener {
return;
}
Plot plot = area.getPlot(location);
if (plot != null) {
if (plot != null && !plot.equals(lastPlot)) {
final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot);
// there is one possibility to still allow teleportation:
// to is identical to the plot's home location, and untrusted-visit is true
// i.e. untrusted-visit can override deny-teleport
// this is acceptable, because otherwise it wouldn't make sense to have both flags set
if (result || (plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) {
plotListener.plotEntry(pp, plot);
if (result || (plot.getFlag(UntrustedVisitFlag.class) && plot
.getHomeSynchronous()
.equals(BukkitUtil.adaptComplete(to)))) {
// returns false if the player is not allowed to enter the plot (if they are denied, for example)
// don't let the move event cancel the entry after teleport, but rather catch and cancel early (#4647)
if (!plotListener.plotEntry(pp, plot)) {
event.setCancelled(true);
}
} else {
pp.sendMessage(
TranslatableCaption.of("deny.no_enter"),
@ -939,12 +951,15 @@ public class PlayerEventListener implements Listener {
builder.tag("plot_id", Tag.inserting(Component.text(id.toString())));
builder.tag("sender", Tag.inserting(Component.text(sender)));
if (plotPlayer.hasPermission("plots.chat.color")) {
builder.tag("msg", Tag.inserting(MiniMessage.miniMessage().deserialize(
message,
TagResolver.resolver(StandardTags.color(), StandardTags.gradient(),
StandardTags.rainbow(), StandardTags.decorations()
)
)));
builder.tag(
"msg", Tag.inserting(MiniMessage.miniMessage().deserialize(
message,
TagResolver.resolver(
StandardTags.color(), StandardTags.gradient(),
StandardTags.rainbow(), StandardTags.decorations()
)
))
);
} else {
builder.tag("msg", Tag.inserting(Component.text(message)));
}
@ -1253,7 +1268,9 @@ public class PlayerEventListener implements Listener {
eventType = PlayerBlockEventType.INTERACT_BLOCK;
blocktype1 = BukkitAdapter.asBlockType(block.getType());
if (INTERACTABLE_MATERIALS != null ? INTERACTABLE_MATERIALS.contains(blockType.name()) : blockType.isInteractable()) {
if (INTERACTABLE_MATERIALS != null
? INTERACTABLE_MATERIALS.contains(blockType.name())
: blockType.isInteractable()) {
if (!player.isSneaking()) {
break;
}
@ -1271,7 +1288,7 @@ public class PlayerEventListener implements Listener {
// in the following, lb needs to have the material of the item in hand i.e. type
switch (type.toString()) {
case "REDSTONE", "STRING", "PUMPKIN_SEEDS", "MELON_SEEDS", "COCOA_BEANS", "WHEAT_SEEDS", "BEETROOT_SEEDS",
"SWEET_BERRIES", "GLOW_BERRIES" -> {
"SWEET_BERRIES", "GLOW_BERRIES" -> {
return;
}
default -> {
@ -1296,6 +1313,17 @@ public class PlayerEventListener implements Listener {
//Allow all players to eat while also allowing the block place event to be fired
return;
}
// Process creature spawning of armor stands & end crystals here if spawned by the player in order to be able to
// reset the player's hand item if spawning needs to be cancelled.
if (type == Material.ARMOR_STAND || type == Material.END_CRYSTAL) {
Plot plot = location.getOwnedPlotAbs();
if (BukkitEntityUtil.checkEntity(type == Material.ARMOR_STAND ? EntityType.ARMOR_STAND : EntityType.ENDER_CRYSTAL,
plot)) {
event.setCancelled(true);
break;
}
}
// Continue with normal place event checks
if (type == Material.ARMOR_STAND) {
location = BukkitUtil.adapt(block.getRelative(event.getBlockFace()).getLocation());
eventType = PlayerBlockEventType.PLACE_MISC;
@ -1370,22 +1398,7 @@ public class PlayerEventListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
BlockFace bf = event.getBlockFace();
// Note: a month after Bukkit 1.14.4 released, they added the API method
// PlayerBucketEmptyEvent#getBlock(), which returns the block the
// bucket contents is going to be placed at. Currently we determine this
// block ourselves to retain compatibility with 1.13.
final Block block;
// if the block can be waterlogged, the event might waterlog the block
// sometimes
if (event.getBlockClicked().getBlockData() instanceof Waterlogged waterlogged
&& !waterlogged.isWaterlogged() && event.getBucket() != Material.LAVA_BUCKET) {
block = event.getBlockClicked();
} else {
block = event.getBlockClicked().getLocation()
.add(bf.getModX(), bf.getModY(), bf.getModZ())
.getBlock();
}
final Block block = event.getBlock();
Location location = BukkitUtil.adapt(block.getLocation());
PlotArea area = location.getPlotArea();
if (area == null) {
@ -1393,6 +1406,16 @@ public class PlayerEventListener implements Listener {
}
BukkitPlayer pp = BukkitUtil.adapt(event.getPlayer());
Plot plot = area.getPlot(location);
final List<BlockTypeWrapper> use =
Optional.ofNullable(plot).map(p -> p.getFlag(UseFlag.class)).orElse(area.isRoadFlags() ?
area.getFlag(UseFlag.class) : Collections.emptyList());
BlockType type = BukkitAdapter.asBlockType(block.getType());
for (final BlockTypeWrapper blockTypeWrapper : use) {
if (blockTypeWrapper.accepts(BlockTypes.AIR) || blockTypeWrapper
.accepts(type)) {
return;
}
}
if (plot == null) {
if (pp.hasPermission(Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
return;
@ -1464,6 +1487,16 @@ public class PlayerEventListener implements Listener {
Player player = event.getPlayer();
BukkitPlayer plotPlayer = BukkitUtil.adapt(player);
Plot plot = area.getPlot(location);
final List<BlockTypeWrapper> use =
Optional.ofNullable(plot).map(p -> p.getFlag(UseFlag.class)).orElse(area.isRoadFlags() ?
area.getFlag(UseFlag.class) : Collections.emptyList());
BlockType type = BukkitAdapter.asBlockType(blockClicked.getType());
for (final BlockTypeWrapper blockTypeWrapper : use) {
if (blockTypeWrapper.accepts(BlockTypes.AIR) || blockTypeWrapper
.accepts(type)) {
return;
}
}
if (plot == null) {
if (plotPlayer.hasPermission(Permission.PERMISSION_ADMIN_BUILD_ROAD)) {
return;

View File

@ -35,7 +35,7 @@ import com.plotsquared.core.util.PlotFlagUtil;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
@ -134,7 +134,7 @@ public class ProjectileEventListener implements Listener {
event.setCancelled(true);
}
} else if (!plot.isAdded(pp.getUUID())) {
if (entity.getType().equals(EntityType.FISHING_HOOK)) {
if (entity instanceof FishHook) {
if (plot.getFlag(FishingFlag.class)) {
return;
}
@ -194,7 +194,7 @@ public class ProjectileEventListener implements Listener {
return;
}
if (plot.isAdded(pp.getUUID()) || pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER) || plot.getFlag(
ProjectilesFlag.class) || (entity.getType().equals(EntityType.FISHING_HOOK) && plot.getFlag(
ProjectilesFlag.class) || (entity instanceof FishHook && plot.getFlag(
FishingFlag.class))) {
return;
}

View File

@ -30,6 +30,8 @@ import com.plotsquared.core.util.task.TaskTime;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.World;
import io.papermc.lib.PaperLib;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.plugin.Plugin;
@ -41,6 +43,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@ -55,6 +59,8 @@ import java.util.function.Consumer;
**/
public final class BukkitChunkCoordinator extends ChunkCoordinator {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitChunkCoordinator.class.getSimpleName());
private final List<ProgressSubscriber> progressSubscribers = new LinkedList<>();
private final Queue<BlockVector2> requestedChunks;
@ -70,6 +76,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
private final AtomicInteger expectedSize;
private final AtomicInteger loadingChunks = new AtomicInteger();
private final boolean forceSync;
private final boolean shouldGen;
private int batchSize;
private PlotSquaredTask task;
@ -87,7 +94,8 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
@Assisted final @NonNull Consumer<Throwable> throwableConsumer,
@Assisted("unloadAfter") final boolean unloadAfter,
@Assisted final @NonNull Collection<ProgressSubscriber> progressSubscribers,
@Assisted("forceSync") final boolean forceSync
@Assisted("forceSync") final boolean forceSync,
@Assisted("shouldGen") final boolean shouldGen
) {
this.requestedChunks = new LinkedBlockingQueue<>(requestedChunks);
this.availableChunks = new LinkedBlockingQueue<>();
@ -103,6 +111,7 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
this.bukkitWorld = Bukkit.getWorld(world.getName());
this.progressSubscribers.addAll(progressSubscribers);
this.forceSync = forceSync;
this.shouldGen = shouldGen;
}
@Override
@ -212,18 +221,28 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator {
* Requests a batch of chunks to be loaded
*/
private void requestBatch() {
BlockVector2 chunk;
for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) {
for (int i = 0; i < this.batchSize && this.requestedChunks.peek() != null; i++) {
// This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent
final BlockVector2 chunk = this.requestedChunks.poll();
loadingChunks.incrementAndGet();
PaperLib
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true)
.getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), shouldGen, true)
.orTimeout(10L, TimeUnit.SECONDS)
.whenComplete((chunkObject, throwable) -> {
loadingChunks.decrementAndGet();
if (throwable != null) {
throwable.printStackTrace();
// We want one less because this couldn't be processed
this.expectedSize.decrementAndGet();
if (throwable instanceof TimeoutException) {
LOGGER.warn("Timed out awaiting chunk load {}", chunk);
this.requestedChunks.offer(chunk);
} else {
LOGGER.error("Failed to load chunk {}", chunk, throwable);
// We want one less because this couldn't be processed
this.expectedSize.decrementAndGet();
}
} else if (chunkObject == null) {
if (shouldGen) {
LOGGER.error("Null chunk returned for chunk at {}", chunk);
}
} else if (PlotSquared.get().isMainThread(Thread.currentThread())) {
this.processChunk(chunkObject);
} else {

View File

@ -238,6 +238,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator {
.unloadAfter(isUnloadAfter())
.withProgressSubscribers(getProgressSubscribers())
.forceSync(isForceSync())
.shouldGen(isShouldGen())
.build();
return super.enqueue();
}

View File

@ -49,6 +49,7 @@ import org.bukkit.entity.Arrow;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.entity.EntityDamageEvent;
@ -341,8 +342,7 @@ public class BukkitEntityUtil {
}
//disable the firework damage. too much of a headache to support at the moment.
if (vplot != null) {
if (EntityDamageEvent.DamageCause.ENTITY_EXPLOSION == cause
&& damager.getType() == EntityType.FIREWORK) {
if (EntityDamageEvent.DamageCause.ENTITY_EXPLOSION == cause && damager instanceof Firework) {
return false;
}
}
@ -354,13 +354,17 @@ public class BukkitEntityUtil {
}
public static boolean checkEntity(Entity entity, Plot plot) {
return checkEntity(entity.getType(), plot);
}
public static boolean checkEntity(EntityType type, Plot plot) {
if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot.getArea()
.getFlagContainer().getFlagMap().isEmpty()) {
return false;
}
final com.sk89q.worldedit.world.entity.EntityType entityType =
BukkitAdapter.adapt(entity.getType());
BukkitAdapter.adapt(type);
if (EntityCategories.PLAYER.contains(entityType)) {
return false;

View File

@ -262,6 +262,11 @@ public class BukkitUtil extends WorldUtil {
});
}
@Override
public boolean isSmallBlock(Location location) {
return adapt(location).getBlock().getBoundingBox().getHeight() < 0.25;
}
@Override
@NonNegative
public int getHighestBlockSynchronous(final @NonNull String world, final int x, final int z) {

View File

@ -120,6 +120,14 @@ public interface PlotPlatform<P> extends LocaleHolder {
*/
@NonNull String serverImplementation();
/**
* Gets the server brand name
*
* @return server brand
* @since 7.5.3
*/
@NonNull String serverBrand();
/**
* Gets the native server code package prefix.
*

View File

@ -144,6 +144,7 @@ public class Buy extends Command {
plot.getPlotModificationManager().setSign(player.getName());
player.sendMessage(
TranslatableCaption.of("working.claimed"),
TagResolver.resolver("world", Tag.inserting(Component.text(plot.getArea().getWorldName()))),
TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString())))
);
this.eventDispatcher.callPostPlayerBuyPlot(player, previousOwner, plot, price);

View File

@ -131,6 +131,7 @@ public class Clear extends Command {
player.sendMessage(
TranslatableCaption.of("working.clearing_done"),
TagResolver.builder()
.tag("world", Tag.inserting(Component.text(plot.getArea().getWorldName())))
.tag("amount", Tag.inserting(Component.text(System.currentTimeMillis() - start)))
.tag("plot", Tag.inserting(Component.text(plot.getId().toString())))
.build()

View File

@ -24,6 +24,7 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.player.PlotPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
@ -98,6 +99,14 @@ public enum CommandCategory implements Caption {
return MiniMessage.miniMessage().deserialize(getComponent(localeHolder));
}
@Override
public @NonNull Component toComponent(
@NonNull final LocaleHolder localeHolder,
final @NonNull TagResolver @NonNull ... tagResolvers
) {
return MiniMessage.miniMessage().deserialize(getComponent(localeHolder));
}
/**
* Checks if a player has access to this command category
*

View File

@ -86,7 +86,8 @@ public class DebugPaste extends SubCommand {
b.append("# WorldEdit implementation:\n");
b.append(PlotSquared.platform().worldEditImplementations()).append("\n\n");
b.append("# Server Information\n");
b.append("Server Version: ").append(PlotSquared.platform().serverImplementation())
b.append("Server Version: ").append(PlotSquared.platform().serverBrand()).append(": ")
.append(PlotSquared.platform().serverImplementation()).append("\n")
.append("\n");
b.append("online_mode: ").append(!Settings.UUID.OFFLINE).append(';')
.append(!Settings.UUID.OFFLINE).append('\n');

View File

@ -124,6 +124,7 @@ public class Delete extends SubCommand {
"amount",
Tag.inserting(Component.text(String.valueOf(System.currentTimeMillis() - start)))
),
TagResolver.resolver("world", Tag.inserting(Component.text(plotArea.getWorldName()))),
TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString())))
);
eventDispatcher.callPostDelete(plot);

View File

@ -113,38 +113,34 @@ public class Help extends Command {
}
if (cat == null && page == 0) {
TextComponent.Builder builder = Component.text();
builder.append(MINI_MESSAGE.deserialize(TranslatableCaption.of("help.help_header").getComponent(player)));
builder.append(TranslatableCaption.of("help.help_header").toComponent(player));
for (CommandCategory c : CommandCategory.values()) {
if (!c.canAccess(player)) {
continue;
}
builder.append(Component.newline()).append(MINI_MESSAGE
.deserialize(
TranslatableCaption.of("help.help_info_item").getComponent(player),
TagResolver.builder()
.tag("command", Tag.inserting(Component.text("/plot help")))
.tag("category", Tag.inserting(Component.text(c.name().toLowerCase())))
.tag("category_desc", Tag.inserting(c.toComponent(player)))
.build()
));
builder.append(Component.newline());
builder.append(TranslatableCaption.of("help.help_info_item").toComponent(
player, TagResolver.builder()
.tag("command", Tag.inserting(Component.text("/plot help")))
.tag("category", Tag.inserting(Component.text(c.name().toLowerCase())))
.tag("category_desc", Tag.inserting(c.toComponent(player)))
.build()
));
}
builder.append(Component.newline()).append(MINI_MESSAGE
.deserialize(
TranslatableCaption.of("help.help_info_item").getComponent(player),
TagResolver.builder()
.tag("command", Tag.inserting(Component.text("/plot help")))
.tag("category", Tag.inserting(Component.text("all")))
.tag(
"category_desc",
Tag.inserting(TranslatableCaption
.of("help.help_display_all_commands")
.toComponent(player))
)
.build()
));
builder.append(Component.newline()).append(MINI_MESSAGE.deserialize(TranslatableCaption
.of("help.help_footer")
.getComponent(player)));
builder.append(Component.newline());
builder.append(TranslatableCaption.of("help.help_info_item").toComponent(
player, TagResolver.builder()
.tag("command", Tag.inserting(Component.text("/plot help")))
.tag("category", Tag.inserting(Component.text("all")))
.tag(
"category_desc", Tag.inserting(TranslatableCaption
.of("help.help_display_all_commands")
.toComponent(player))
)
.build()
));
builder.append(Component.newline());
builder.append(TranslatableCaption.of("help.help_footer").toComponent(player));
player.sendMessage(StaticCaption.of(MINI_MESSAGE.serialize(builder.asComponent())));
return true;
}

View File

@ -20,7 +20,6 @@ package com.plotsquared.core.command;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.configuration.caption.StaticCaption;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.permissions.Permission;
@ -131,13 +130,9 @@ public class Info extends SubCommand {
info = getCaption(arg);
if (info == null) {
if (Settings.Ratings.USE_LIKES) {
player.sendMessage(StaticCaption.of(
"&6Categories&7: &amembers&7, &aalias&7, &abiome&7, &aseen&7, &adenied&7, &aflags&7, &aid&7, &asize&7, &atrusted&7, "
+ "&aowner&7, " + " &alikes"));
player.sendMessage(TranslatableCaption.of("info.plot_info_categories.use_likes"));
} else {
player.sendMessage(StaticCaption.of(
"&6Categories&7: &amembers&7, &aalias&7, &abiome&7, &aseen&7, &adenied&7, &aflags&7, &aid&7, &asize&7, &atrusted&7, "
+ "&aowner&7, " + " &arating"));
player.sendMessage(TranslatableCaption.of("info.plot_info_categories.use_rating"));
}
return false;
}

View File

@ -44,8 +44,13 @@ import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* PlotSquared command class.
*/
@ -147,8 +152,7 @@ public class MainCommand extends Command {
try {
injector.getInstance(command);
} catch (final Exception e) {
LOGGER.error("Failed to register command {}", command.getCanonicalName());
e.printStackTrace();
LOGGER.error("Failed to register command {}", command.getCanonicalName(), e);
}
}
@ -236,111 +240,171 @@ public class MainCommand extends Command {
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) {
// Optional command scope //
Location location = null;
Plot plot = null;
boolean tp = false;
if (args.length >= 2) {
PlotArea area = player.getApplicablePlotArea();
Plot newPlot = Plot.fromString(area, args[0]);
if (newPlot != null && (player instanceof ConsolePlayer || newPlot.getArea()
.equals(area) || player.hasPermission(Permission.PERMISSION_ADMIN)
|| player.hasPermission(Permission.PERMISSION_ADMIN_AREA_SUDO))
&& !newPlot.isDenied(player.getUUID())) {
final Location newLoc;
if (newPlot.getArea() instanceof SinglePlotArea) {
newLoc = newPlot.isLoaded() ? newPlot.getCenterSynchronous() : Location.at("", 0, 0, 0);
} else {
newLoc = newPlot.getCenterSynchronous();
}
if (player.canTeleport(newLoc)) {
// Save meta
try (final MetaDataAccess<Location> locationMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
location = locationMetaDataAccess.get().orElse(null);
locationMetaDataAccess.set(newLoc);
prepareArguments(new CommandExecutionData(player, args, confirm, whenDone, null))
.thenCompose(executionData -> {
if (executionData.isEmpty()) {
return CompletableFuture.completedFuture(false);
}
try (final MetaDataAccess<Plot> plotMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
plot = plotMetaDataAccess.get().orElse(null);
plotMetaDataAccess.set(newPlot);
}
tp = true;
} else {
player.sendMessage(TranslatableCaption.of("border.denied"));
return CompletableFuture.completedFuture(false);
}
// Trim command
args = Arrays.copyOfRange(args, 1, args.length);
}
if (args.length >= 2 && !args[0].isEmpty() && args[0].charAt(0) == '-') {
if ("f".equals(args[0].substring(1))) {
confirm = new RunnableVal3<>() {
@Override
public void run(Command cmd, Runnable success, Runnable failure) {
if (area != null && PlotSquared.platform().econHandler().isEnabled(area)) {
PlotExpression priceEval =
area.getPrices().get(cmd.getFullId());
double price = priceEval != null ? priceEval.evaluate(0d) : 0d;
if (price != 0d
&& PlotSquared.platform().econHandler().getMoney(player) < price) {
if (failure != null) {
failure.run();
}
return;
}
}
if (success != null) {
success.run();
}
var data = executionData.get();
try {
return super.execute(data.player(), data.args(), data.confirm(), data.whenDone());
} catch (CommandException e) {
throw e;
} catch (Throwable e) {
LOGGER.error("A error occurred while executing plot command", e);
String message = e.getMessage();
if (message != null) {
data.player().sendMessage(
TranslatableCaption.of("errors.error"),
TagResolver.resolver("value", Tag.inserting(Component.text(message)))
);
} else {
data.player().sendMessage(
TranslatableCaption.of("errors.error_console"));
}
};
args = Arrays.copyOfRange(args, 1, args.length);
} else {
player.sendMessage(TranslatableCaption.of("errors.invalid_command_flag"));
return CompletableFuture.completedFuture(false);
}
}
}
try {
super.execute(player, args, confirm, whenDone);
} catch (CommandException e) {
throw e;
} catch (Throwable e) {
e.printStackTrace();
String message = e.getMessage();
if (message != null) {
player.sendMessage(
TranslatableCaption.of("errors.error"),
TagResolver.resolver("value", Tag.inserting(Component.text(message)))
);
} else {
player.sendMessage(
TranslatableCaption.of("errors.error_console"));
}
}
// Reset command scope //
if (tp && !(player instanceof ConsolePlayer)) {
try (final MetaDataAccess<Location> locationMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
if (location == null) {
locationMetaDataAccess.remove();
} else {
locationMetaDataAccess.set(location);
}
}
try (final MetaDataAccess<Plot> plotMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
if (plot == null) {
plotMetaDataAccess.remove();
} else {
plotMetaDataAccess.set(plot);
}
}
}
} finally {
if (data.postCommandData() != null) {
resetCommandScope(data.player(), data.postCommandData());
}
}
return CompletableFuture.completedFuture(true);
});
return CompletableFuture.completedFuture(true);
}
private CompletableFuture<Optional<CommandExecutionData>> prepareArguments(CommandExecutionData data) {
if (data.args().length >= 2) {
PlotArea area = data.player().getApplicablePlotArea();
Plot newPlot = Plot.fromString(area, data.args()[0]);
return preparePlotArgument(newPlot, data, area)
.thenApply(d -> d.flatMap(x -> prepareFlagArgument(x, area)));
} else {
return CompletableFuture.completedFuture(Optional.of(data));
}
}
private CompletableFuture<Optional<CommandExecutionData>> preparePlotArgument(@Nullable Plot newPlot,
@Nonnull CommandExecutionData data,
@Nullable PlotArea area) {
if (newPlot != null && (data.player() instanceof ConsolePlayer
|| (area != null && area.equals(newPlot.getArea()))
|| data.player().hasPermission(Permission.PERMISSION_ADMIN)
|| data.player().hasPermission(Permission.PERMISSION_ADMIN_AREA_SUDO))
&& !newPlot.isDenied(data.player().getUUID())) {
return fetchPlotCenterLocation(newPlot)
.thenApply(newLoc -> {
if (!data.player().canTeleport(newLoc)) {
data.player().sendMessage(TranslatableCaption.of("border.denied"));
return Optional.empty();
}
// Save meta
var originalCommandMeta = setCommandScope(data.player(), new TemporaryCommandMeta(newLoc, newPlot));
return Optional.of(new CommandExecutionData(
data.player(),
Arrays.copyOfRange(data.args(), 1, data.args().length), // Trimmed command
data.confirm(),
data.whenDone(),
originalCommandMeta
));
});
}
return CompletableFuture.completedFuture(Optional.of(data));
}
private Optional<CommandExecutionData> prepareFlagArgument(@Nonnull CommandExecutionData data, @Nonnull PlotArea area) {
if (data.args().length >= 2 && !data.args()[0].isEmpty() && data.args()[0].charAt(0) == '-') {
if ("f".equals(data.args()[0].substring(1))) {
return Optional.of(new CommandExecutionData(
data.player(),
Arrays.copyOfRange(data.args(), 1, data.args().length), // Trimmed command
createForcedConfirmation(data.player(), area),
data.whenDone(),
data.postCommandData()
));
} else {
data.player().sendMessage(TranslatableCaption.of("errors.invalid_command_flag"));
return Optional.empty();
}
}
return Optional.of(data);
}
private CompletableFuture<Location> fetchPlotCenterLocation(Plot plot) {
if (plot.getArea() instanceof SinglePlotArea && !plot.isLoaded()) {
return CompletableFuture.completedFuture(Location.at("", 0, 0, 0));
}
CompletableFuture<Location> future = new CompletableFuture<>();
plot.getCenter(future::complete);
return future;
}
private @Nonnull RunnableVal3<Command, Runnable, Runnable> createForcedConfirmation(@Nonnull PlotPlayer<?> player,
@Nullable PlotArea area) {
return new RunnableVal3<>() {
@Override
public void run(Command cmd, Runnable success, Runnable failure) {
if (area != null && PlotSquared.platform().econHandler().isEnabled(area)
&& Optional.of(area.getPrices().get(cmd.getFullId()))
.map(priceEval -> priceEval.evaluate(0d))
.filter(price -> price != 0d)
.filter(price -> PlotSquared.platform().econHandler().getMoney(player) < price)
.isPresent()) {
if (failure != null) {
failure.run();
}
return;
}
if (success != null) {
success.run();
}
}
};
}
private @Nonnull TemporaryCommandMeta setCommandScope(@Nonnull PlotPlayer<?> player, @Nonnull TemporaryCommandMeta commandMeta) {
Objects.requireNonNull(commandMeta.location());
Objects.requireNonNull(commandMeta.plot());
Location location;
Plot plot;
try (final MetaDataAccess<Location> locationMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
location = locationMetaDataAccess.get().orElse(null);
locationMetaDataAccess.set(commandMeta.location());
}
try (final MetaDataAccess<Plot> plotMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
plot = plotMetaDataAccess.get().orElse(null);
plotMetaDataAccess.set(commandMeta.plot());
}
return new TemporaryCommandMeta(location, plot);
}
private void resetCommandScope(@Nonnull PlotPlayer<?> player, @Nonnull TemporaryCommandMeta commandMeta) {
try (final MetaDataAccess<Location> locationMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) {
if (commandMeta.location() == null) {
locationMetaDataAccess.remove();
} else {
locationMetaDataAccess.set(commandMeta.location());
}
}
try (final MetaDataAccess<Plot> plotMetaDataAccess
= player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
if (commandMeta.plot() == null) {
plotMetaDataAccess.remove();
} else {
plotMetaDataAccess.set(commandMeta.plot());
}
}
}
private record CommandExecutionData(@Nonnull PlotPlayer<?> player, @Nonnull String[] args,
@Nonnull RunnableVal3<Command, Runnable, Runnable> confirm,
@Nonnull RunnableVal2<Command, CommandResult> whenDone,
@Nullable TemporaryCommandMeta postCommandData) {}
private record TemporaryCommandMeta(@Nullable Location location, @Nullable Plot plot) {}
@Override
public boolean canExecute(PlotPlayer<?> player, boolean message) {
return true;

View File

@ -117,8 +117,8 @@ public class Remove extends SubCommand {
}
if (count == 0) {
player.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting(Component.text(args[0])))
TranslatableCaption.of("member.player_not_removed"),
TagResolver.resolver("player", Tag.inserting(Component.text(args[0])))
);
} else {
player.sendMessage(

View File

@ -582,6 +582,8 @@ public class Settings extends Config {
public static boolean PER_WORLD_VISIT = false;
@Comment("Search merged plots for having multiple owners when using the visit command")
public static boolean VISIT_MERGED_OWNERS = true;
@Comment("Allows to teleport based on block size instead to spawn on the highest block at the home command")
public static boolean SIZED_BASED = true;
}

View File

@ -20,6 +20,7 @@ package com.plotsquared.core.configuration.caption;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
@ -44,6 +45,16 @@ public interface Caption {
*/
@NonNull Component toComponent(@NonNull LocaleHolder localeHolder);
/**
* Get the Adventure {@link ComponentLike} for this caption while applying custom {@link TagResolver}
* (apart from the default {@code core.prefix})
* @param localeHolder Local holder
* @param tagResolvers custom tag resolvers to replace placeholders / parameters
* @return {@link ComponentLike}
* @since 7.5.4
*/
@NonNull Component toComponent(@NonNull LocaleHolder localeHolder, @NonNull TagResolver @NonNull... tagResolvers);
@NonNull String toString();
}

View File

@ -21,6 +21,7 @@ package com.plotsquared.core.configuration.caption;
import com.google.common.base.Preconditions;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
public final class StaticCaption implements Caption {
@ -51,6 +52,14 @@ public final class StaticCaption implements Caption {
return MiniMessage.miniMessage().deserialize(this.value);
}
@Override
public @NonNull Component toComponent(
@NonNull final LocaleHolder localeHolder,
final @NonNull TagResolver @NonNull ... tagResolvers
) {
return MiniMessage.miniMessage().deserialize(this.value, tagResolvers);
}
@Override
public @NonNull String toString() {
return "StaticCaption(" + value + ")";

View File

@ -27,6 +27,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Locale;
import java.util.regex.Pattern;
@ -96,13 +97,23 @@ public final class TranslatableCaption implements NamespacedCaption {
@Override
public @NonNull Component toComponent(@NonNull final LocaleHolder localeHolder) {
return this.toComponent(localeHolder, new TagResolver[0]);
}
@Override
public @NonNull Component toComponent(
@NonNull final LocaleHolder localeHolder,
final @NonNull TagResolver @NonNull ... tagResolvers
) {
if (getKey().equals("core.prefix")) {
return MiniMessage.miniMessage().deserialize(getComponent(localeHolder));
}
return MiniMessage.miniMessage().deserialize(getComponent(localeHolder), TagResolver.resolver(
TagResolver[] finalResolvers = Arrays.copyOf(tagResolvers, tagResolvers.length + 1);
finalResolvers[finalResolvers.length - 1] = TagResolver.resolver(
"prefix",
Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(localeHolder))
));
);
return MiniMessage.miniMessage().deserialize(getComponent(localeHolder), finalResolvers);
}
@Override

View File

@ -432,6 +432,7 @@ public class HybridUtils {
if (!UPDATE) {
Iterator<BlockVector2> iter = chunks.iterator();
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
queue.setShouldGen(false);
while (iter.hasNext()) {
BlockVector2 chunk = iter.next();
iter.remove();
@ -474,6 +475,7 @@ public class HybridUtils {
Iterator<BlockVector2> iterator = chunks.iterator();
if (chunks.size() >= 32) {
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
queue.setShouldGen(false);
for (int i = 0; i < 32; i++) {
final BlockVector2 chunk = iterator.next();
iterator.remove();
@ -487,6 +489,7 @@ public class HybridUtils {
return null;
}
QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName()));
queue.setShouldGen(false);
while (!chunks.isEmpty()) {
final BlockVector2 chunk = iterator.next();
iterator.remove();
@ -502,7 +505,6 @@ public class HybridUtils {
return;
}
} catch (Exception e) {
e.printStackTrace();
Iterator<BlockVector2> iterator = HybridUtils.regions.iterator();
BlockVector2 loc = iterator.next();
iterator.remove();
@ -510,7 +512,8 @@ public class HybridUtils {
"Error! Could not update '{}/region/r.{}.{}.mca' (Corrupt chunk?)",
area.getWorldHash(),
loc.getX(),
loc.getZ()
loc.getZ(),
e
);
}
TaskManager.runTaskLater(task, TaskTime.seconds(1L));
@ -558,7 +561,7 @@ public class HybridUtils {
try {
plotworld.setupSchematics();
} catch (SchematicHandler.UnsupportedFormatException e) {
e.printStackTrace();
LOGGER.error(e);
}
});
});

View File

@ -40,7 +40,8 @@ public interface ChunkCoordinatorFactory {
final @NonNull Consumer<Throwable> throwableConsumer,
@Assisted("unloadAfter") final boolean unloadAfter,
final @NonNull Collection<ProgressSubscriber> progressSubscribers,
@Assisted("forceSync") final boolean forceSync
@Assisted("forceSync") final boolean forceSync,
@Assisted("shouldGen") final boolean shouldGen
);
}

View File

@ -444,7 +444,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
/**
* Get this player's UUID.
* === !IMPORTANT ===<br>
* <p>=== !IMPORTANT ===</p>
* The UUID is dependent on the mode chosen in the settings.yml and may not be the same as Bukkit has
* (especially if using an old version of Bukkit that does not support UUIDs)
*

View File

@ -1407,6 +1407,9 @@ public class Plot {
);
}
Location location = toHomeLocation(bottom, home);
if (Settings.Teleport.SIZED_BASED && this.worldUtil.isSmallBlock(location) && this.worldUtil.isSmallBlock(location.add(0,1,0))) {
return location;
}
if (!this.worldUtil.getBlockSynchronous(location).getBlockType().getMaterial().isAir()) {
location = location.withY(
Math.max(1 + this.worldUtil.getHighestBlockSynchronous(
@ -1440,15 +1443,21 @@ public class Plot {
}
Location bottom = this.getBottomAbs();
Location location = toHomeLocation(bottom, home);
this.worldUtil.getBlock(location, block -> {
if (!block.getBlockType().getMaterial().isAir()) {
this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(),
y -> result.accept(location.withY(Math.max(1 + y, bottom.getY())))
);
} else {
result.accept(location);
}
});
if (Settings.Teleport.SIZED_BASED && this.worldUtil.isSmallBlock(location) && this.worldUtil.isSmallBlock(location.add(0,1,0))) {
result.accept(location);
} else {
this.worldUtil.getBlock(location, block -> {
if (!block.getBlockType().getMaterial().isAir()) {
this.worldUtil.getHighestBlock(this.getWorldName(), location.getX(), location.getZ(),
y -> result.accept(location.withY(Math.max(1 + y, bottom.getY())))
);
} else {
result.accept(location);
}
});
}
}
}
@ -1708,6 +1717,7 @@ public class Plot {
}
player.sendMessage(
TranslatableCaption.of("working.claimed"),
TagResolver.resolver("world", Tag.inserting(Component.text(this.getWorldName()))),
TagResolver.resolver("plot", Tag.inserting(Component.text(this.getId().toString())))
);
if (teleport) {

View File

@ -52,6 +52,7 @@ public class ChunkCoordinatorBuilder {
private int initialBatchSize = Settings.QUEUE.INITIAL_BATCH_SIZE;
private boolean unloadAfter = true;
private boolean forceSync = false;
private boolean shouldGen = true;
@Inject
public ChunkCoordinatorBuilder(@NonNull ChunkCoordinatorFactory chunkCoordinatorFactory) {
@ -203,6 +204,19 @@ public class ChunkCoordinatorBuilder {
return this;
}
/**
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
*
* @param shouldGen should generate new chunks or not
* @since 7.5.0
*/
public @NonNull ChunkCoordinatorBuilder shouldGen(final boolean shouldGen) {
this.shouldGen = shouldGen;
return this;
}
public @NonNull ChunkCoordinatorBuilder withProgressSubscriber(ProgressSubscriber progressSubscriber) {
this.progressSubscribers.add(progressSubscriber);
return this;
@ -234,7 +248,8 @@ public class ChunkCoordinatorBuilder {
this.throwableConsumer,
this.unloadAfter,
this.progressSubscribers,
this.forceSync
this.forceSync,
this.shouldGen
);
}

View File

@ -51,6 +51,7 @@ public class DelegateQueueCoordinator extends QueueCoordinator {
if (parent != null) {
this.setForceSync(parent.isForceSync());
this.setShouldGen(parent.isShouldGen());
}
}

View File

@ -45,6 +45,7 @@ public abstract class QueueCoordinator {
private final AtomicBoolean enqueued = new AtomicBoolean();
private boolean forceSync = false;
private boolean shouldGen = true;
@Nullable
private Object chunkObject;
@SuppressWarnings({"unused", "FieldCanBeLocal"})
@ -110,6 +111,30 @@ public abstract class QueueCoordinator {
this.forceSync = forceSync;
}
/**
* Get whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
*
* @since 7.5.0
*/
public boolean isShouldGen() {
return shouldGen;
}
/**
* Set whether chunks should be generated as part of this operation. Default is true. Disabling this may not be supported
* depending on server implementation. (i.e. setting to false may not actually disable generation as part of this operation
* - this is just a catch-all in case of future differing server implementations; the option will work on Spigot/Paper).
*
* @param shouldGen should generate new chunks or not
* @since 7.5.0
*/
public void setShouldGen(boolean shouldGen) {
this.shouldGen = shouldGen;
}
/**
* Get the Chunk Object set to the queue
*

View File

@ -177,6 +177,13 @@ public abstract class WorldUtil {
*/
public abstract void getBlock(@NonNull Location location, @NonNull Consumer<BlockState> result);
/**
* Checks if the block smaller as a slab
* @param location Block location
* @return true if it smaller as a slab
*/
public abstract boolean isSmallBlock(@NonNull Location location);
/**
* Get the block at a given location (synchronously)
*

View File

@ -25,30 +25,24 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.util.StringMan;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.jetbrains.annotations.NotNull;
public class HelpObject implements ComponentLike {
static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();
private final Component rendered;
public HelpObject(final Command command, final String label, final PlotPlayer<?> audience) {
rendered = MINI_MESSAGE.deserialize(
TranslatableCaption.of("help.help_item").getComponent(audience),
TagResolver.builder()
.tag("usage", Tag.inserting(Component.text(command.getUsage().replace("{label}", label))))
.tag("alias", Tag.inserting(Component.text(
command.getAliases().isEmpty() ? "" : StringMan.join(command.getAliases(), " | ")
)))
.tag("desc", Tag.inserting(command.getDescription().toComponent(audience)))
.tag("arguments", Tag.inserting(Component.text(buildArgumentList(command.getRequiredArguments()))))
.tag("label", Tag.inserting(Component.text(label)))
.build()
);
this.rendered = TranslatableCaption.of("help.help_item").toComponent(audience, TagResolver.builder()
.tag("usage", Tag.inserting(Component.text(command.getUsage().replace("{label}", label))))
.tag("alias", Tag.inserting(Component.text(
command.getAliases().isEmpty() ? "" : StringMan.join(command.getAliases(), " | ")
)))
.tag("desc", Tag.inserting(command.getDescription().toComponent(audience)))
.tag("arguments", Tag.inserting(Component.text(buildArgumentList(command.getRequiredArguments()))))
.tag("label", Tag.inserting(Component.text(label)))
.build());
}
private String buildArgumentList(final Argument<?>[] arguments) {

View File

@ -353,6 +353,8 @@
"info.infinite": "<gray>Infinite</gray>",
"info.plot_unowned": "<prefix><red>The current plot must have an owner to perform this action.</red>",
"info.plot_info_unclaimed": "<prefix><gray>Plot <gold><plot></gold> is not yet claimed.</gray>",
"info.plot_info_categories.use_rating": "<prefix><gold>Categories: </gold> <gray>members, alias, biome, seen, denied, flags, id, size, trusted, owner, rating</gray>",
"info.plot_info_categories.use_likes": "<prefix><gold>Categories: </gold> <gray>members, alias, biome, seen, denied, flags, id, size, trusted, owner, likes</gray>",
"info.plot_info_header": "<dark_gray><strikethrough>--------- <reset><gold>INFO </gold><dark_gray><strikethrough>---------</dark_gray><reset>",
"info.plot_info_hidden": "<prefix><red>You cannot view the information about this plot.</red>",
"info.plot_info_format": "<header>\n<gold>ID: <gray><id></gray>\nCreation: <gray><creationdate></gray>\nArea: <gray><area></gray>\nAlias: <gray><alias></gray>\nOwner: <gray><owner></gray>\nBiome: <gray><biome></gray>\nCan Build: <gray><build></gray>\nRating: <gray><rating></gray>\nSeen: <gray><seen></gray>\nTrusted: <gray><trusted></gray>\nMembers: <gray><members></gray>\nDenied: <gray><denied></gray>\nFlags: <gray><flags></gray>\nDescription: <gray><desc></gray></gold>\n<footer>",
@ -390,11 +392,11 @@
"info.area_list_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>",
"info.area_list_item": "<click:run_command:'<command_tp>'><hover:show_text:'<command_tp>'><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:'<command_info>'><hover:show_text:'<hover_info>'><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>",
"working.generating_component": "<prefix><gold>Started generating component from your settings.</gold>",
"working.clearing_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><plot></gold><dark_aqua> has been cleared! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>",
"working.deleting_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><plot></gold><dark_aqua> has been deleted! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>",
"working.clearing_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><world>;<plot></gold><dark_aqua> has been cleared! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>",
"working.deleting_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><world>;<plot></gold><dark_aqua> has been deleted! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>",
"working.plot_not_claimed": "<prefix><gray>Plot not claimed.</gray>",
"working.plot_is_claimed": "<prefix><gray>This plot is already claimed.</gray>",
"working.claimed": "<prefix><dark_aqua>You successfully claimed the plot </dark_aqua><gold><plot></gold><dark_aqua>.</dark_aqua>",
"working.claimed": "<prefix><dark_aqua>You successfully claimed the plot </dark_aqua><gold><world>;<plot></gold><dark_aqua>.</dark_aqua>",
"working.progress": "<prefix><gray>Current progress: </gray><gold><progress></gold><gray>%</gray>",
"working.component_complete": "<prefix><gold>Component generation has finished for plot <plot>.</gold>",
"list.comment_list_header_paged": "<gray>(Page </gray><gold><cur></gold><gray>/</gray><gold><max></gold><gray>) </gray><gold>List of <amount> comment(s):</gold>",

View File

@ -1,5 +1,6 @@
import com.diffplug.gradle.spotless.SpotlessPlugin
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
import com.vanniktech.maven.publish.SonatypeHost
import groovy.json.JsonSlurper
import xyz.jpenilla.runpaper.task.RunServer
import java.net.URI
@ -7,13 +8,12 @@ import java.net.URI
plugins {
java
`java-library`
`maven-publish`
signing
alias(libs.plugins.shadow)
alias(libs.plugins.spotless)
alias(libs.plugins.grgit)
alias(libs.plugins.nexus)
alias(libs.plugins.publish)
eclipse
idea
@ -22,7 +22,7 @@ plugins {
}
group = "com.intellectualsites.plotsquared"
version = "7.4.2"
version = "7.5.4"
if (!File("$rootDir/.git").exists()) {
logger.lifecycle("""
@ -41,16 +41,6 @@ subprojects {
repositories {
mavenCentral()
maven {
name = "Sonatype OSS"
url = uri("https://oss.sonatype.org/content/repositories/snapshots/")
}
maven {
name = "Sonatype OSS (S01)"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
maven {
name = "Jitpack"
url = uri("https://jitpack.io")
@ -68,7 +58,7 @@ subprojects {
apply {
plugin<JavaPlugin>()
plugin<JavaLibraryPlugin>()
plugin<MavenPublishPlugin>()
plugin<com.vanniktech.maven.publish.MavenPublishPlugin>()
plugin<ShadowPlugin>()
plugin<SpotlessPlugin>()
plugin<SigningPlugin>()
@ -79,8 +69,8 @@ subprojects {
dependencies {
// Tests
testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
testImplementation("org.junit.jupiter:junit-jupiter:5.13.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.3")
}
plugins.withId("java") {
@ -107,11 +97,6 @@ subprojects {
}
}
java {
withSourcesJar()
withJavadocJar()
}
val javaComponent = components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
@ -127,66 +112,67 @@ subprojects {
}
}
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
mavenPublishing {
coordinates(
groupId = "$group",
artifactId = project.name,
version = "${project.version}",
)
pom {
pom {
name.set(project.name)
description.set("PlotSquared, a land and world management plugin for Minecraft.")
url.set("https://github.com/IntellectualSites/PlotSquared")
name.set(project.name + " " + project.version)
description.set("PlotSquared, a land and world management plugin for Minecraft.")
url.set("https://github.com/IntellectualSites/PlotSquared")
licenses {
license {
name.set("GNU General Public License, Version 3.0")
url.set("https://www.gnu.org/licenses/gpl-3.0.html")
distribution.set("repo")
}
}
developers {
developer {
id.set("Sauilitired")
name.set("Alexander Söderberg")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
developer {
id.set("NotMyFault")
name.set("Alexander Brandes")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
email.set("contact(at)notmyfault.dev")
}
developer {
id.set("SirYwell")
name.set("Hannes Greule")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
developer {
id.set("dordsor21")
name.set("dordsor21")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
}
scm {
url.set("https://github.com/IntellectualSites/PlotSquared")
connection.set("scm:git:https://github.com/IntellectualSites/PlotSquared.git")
developerConnection.set("scm:git:git@github.com:IntellectualSites/PlotSquared.git")
tag.set("${project.version}")
}
issueManagement {
system.set("GitHub")
url.set("https://github.com/IntellectualSites/PlotSquared/issues")
}
licenses {
license {
name.set("GNU General Public License, Version 3.0")
url.set("https://www.gnu.org/licenses/gpl-3.0.html")
distribution.set("repo")
}
}
developers {
developer {
id.set("Sauilitired")
name.set("Alexander Söderberg")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
developer {
id.set("NotMyFault")
name.set("Alexander Brandes")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
email.set("contact(at)notmyfault.dev")
}
developer {
id.set("SirYwell")
name.set("Hannes Greule")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
developer {
id.set("dordsor21")
name.set("dordsor21")
organization.set("IntellectualSites")
organizationUrl.set("https://github.com/IntellectualSites")
}
}
scm {
url.set("https://github.com/IntellectualSites/PlotSquared")
connection.set("scm:git:https://github.com/IntellectualSites/PlotSquared.git")
developerConnection.set("scm:git:git@github.com:IntellectualSites/PlotSquared.git")
tag.set("${project.version}")
}
issueManagement {
system.set("GitHub")
url.set("https://github.com/IntellectualSites/PlotSquared/issues")
}
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
}
}
@ -194,7 +180,6 @@ subprojects {
compileJava {
options.compilerArgs.add("-parameters")
options.isDeprecation = true
options.encoding = "UTF-8"
}
@ -217,27 +202,18 @@ subprojects {
}
}
nexusPublishing {
this.repositories {
sonatype {
nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}
tasks.getByName<Jar>("jar") {
enabled = false
}
val supportedVersions = listOf("1.18.2", "1.19.4", "1.20.6", "1.21.1", "1.21.3")
val supportedVersions = listOf("1.19.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4", "1.21.5")
tasks {
register("cacheLatestFaweArtifact") {
val lastSuccessfulBuildUrl = uri("https://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/api/json").toURL()
val artifact = ((JsonSlurper().parse(lastSuccessfulBuildUrl) as Map<*, *>)["artifacts"] as List<*>)
.map { it as Map<*, *> }
.map { it["fileName"] as String }
.first { it -> it.contains("Bukkit") }
.first { it -> it.contains("Paper") }
project.ext["faweArtifact"] = artifact
}

View File

@ -2,41 +2,41 @@
# Platform expectations
paper = "1.20.4-R0.1-SNAPSHOT"
guice = "7.0.0"
spotbugs = "4.9.1"
checkerqual = "3.49.0"
spotbugs = "4.9.3"
checkerqual = "3.49.5"
gson = "2.10"
guava = "31.1-jre"
snakeyaml = "2.0"
adventure = "4.18.0"
adventure-bukkit = "4.3.4"
adventure = "4.21.0"
adventure-bukkit = "4.4.0"
log4j = "2.19.0"
# Plugins
worldedit = "7.2.20"
fawe = "2.12.3"
fawe = "2.13.0"
placeholderapi = "2.11.6"
luckperms = "5.4"
essentialsx = "2.20.1"
luckperms = "5.5"
essentialsx = "2.21.1"
mvdwapi = "3.1.1"
# Third party
prtree = "2.0.1"
aopalliance = "1.0"
cloud-services = "1.8.4"
arkitektonika = "2.1.3"
arkitektonika = "2.1.4"
squirrelid = "0.3.2"
paster = "1.1.6"
paster = "1.1.7"
bstats = "3.1.0"
paperlib = "1.0.8"
informative-annotations = "1.5"
informative-annotations = "1.6"
vault = "1.7.1"
serverlib = "2.3.6"
serverlib = "2.3.7"
# Gradle plugins
shadow = "8.3.6"
shadow = "8.3.8"
grgit = "4.1.1"
spotless = "7.0.2"
nexus = "2.0.0"
spotless = "7.0.4"
publish = "0.33.0"
runPaper = "2.3.1"
[libraries]
@ -81,5 +81,5 @@ serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.re
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" }
publish = { id = "com.vanniktech.maven.publish", version.ref = "publish" }
runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" }

Binary file not shown.

View File

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

6
gradlew vendored
View File

@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.

4
gradlew.bat vendored
View File

@ -70,11 +70,11 @@ goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell