Compare commits

..

27 Commits

Author SHA1 Message Date
renovate[bot]
27e4f6adf2 Update worldedit to v7.3.16 2025-09-08 14:56:04 +00:00
renovate[bot]
fd8cf3c475 Update dependency org.checkerframework:checker-qual to v3.50.0 (#4749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-08 01:36:33 +00:00
renovate[bot]
8c9957edeb Update actions/setup-java action to v5 (#4750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-08 01:36:15 +00:00
Jordan
aaba2b5b1a fix: improve error handling in backups (#4740)
* fix: improve error handling in backups
 - fixes #4460

* cleanup

* Update Core/src/main/java/com/plotsquared/core/backup/Backup.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Alexander Brandes <mc.cache@web.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-01 20:29:52 +02:00
Jordan
02a65c8855 fix: use PlotPlayer#getCurrentPlot across commands to allow /<command> <id> usage (#4738)
* fix: use PlotPlayer#getCurrentPlot across commands to allow /<command> <id> usage
 - fixes #4526
 - supersedes #4675

* cleanup
2025-08-30 20:33:13 +02:00
Jordan
8a5fa26796 fix: allow extended world height when teleporting player on join (#4739) 2025-08-30 20:32:40 +02:00
renovate[bot]
13cbb7e083 Update actions/checkout action to v5 (#4746)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-25 01:08:14 +00:00
EnZaXD
4d8d5b3a9f fix: special handle thrown eggs for projectile hit checks (#4728)
Cancelling the ProjectileHitEvent will not cover for thrown eggs spawning chickens due to how Bukkit has these events structured. The provided patch calls the same code used for normal projectiles in the specialized egg event to prevent unwanted chickens from spawning on other plots.

Signed-off-by: FlorianMichael <florian.michael07@gmail.com>
2025-08-23 13:08:28 +02:00
renovate[bot]
cd6a32cf44 Update adventure to v4.24.0 (#4733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 02:06:13 +00:00
renovate[bot]
273c0ad989 Update Ilshidur/action-discord action to v0.4.0 (#4734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 02:05:32 +00:00
renovate[bot]
774da7183b Update dependency com.gradleup.shadow to v8.3.9 (#4730)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 00:56:21 +00:00
renovate[bot]
e083015ab2 Update dependency com.github.spotbugs:spotbugs-annotations to v4.9.4 (#4729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 00:55:56 +00:00
Jordan
3f577d039b feat: add placeholder for multiple owners (#4711)
- closes #4695
2025-08-08 19:51:53 +02:00
Leviaria
4d2e4a3d1a fix: tab completion for /plot grant add/check <name> commands (#4720)
Fix tab completion for /plot grant add/check <name> commands

Fixed an issue where player name tab completion was not working correctly 
for /plot grant add <name> and /plot grant check <name> commands.

Previously, the tab completion logic would only attempt to complete player 
names after all arguments were processed, making it impossible to get 
player suggestions when typing the second argument.

Now the completion properly handles:
- /plot grant <TAB> → shows "add", "check" subcommands
- /plot grant add <TAB> → shows player list
- /plot grant check <TAB> → shows player list

Fixes #4382
2025-08-06 21:44:10 +02:00
renovate[bot]
e5d36579b1 Update fawe to v2.13.1 (#4724)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-04 01:52:49 +00:00
renovate[bot]
f0cde251bd Update dependency net.essentialsx:EssentialsX to v2.21.2 (#4723)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-04 01:52:09 +00:00
Jordan
58016bb1c8 fix: allow admin override when setting plot context in command (#4712)
* fix: allow admin override when setting plot context in command
 - when admins (plots.admin or console) attempted to use /plot x;z to set context on a plot they are denied on, it would not work
 - fixes #4696

* Print error to user if denied
2025-08-03 11:13:48 +02:00
Alexander Brandes
e5943ba627 Update adventure-platform-bukkit to 4.4.1
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-30 09:01:56 +02:00
Alexander Brandes
07dfdeef2c Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-29 21:20:36 +02:00
Alexander Brandes
025b08e716 Release 7.5.6
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-29 21:16:56 +02:00
Alexander Brandes
921435689e Update adventure-platform-bukkit to 4.4.1-SNAPSHOT (#4717)
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-29 21:09:20 +02:00
Alexander Brandes
aae154b23a Back to snapshot for development
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-29 18:36:10 +02:00
Alexander Brandes
0f33465d76 Release 7.5.5
Signed-off-by: Alexander Brandes <mc.cache@web.de>
2025-07-29 18:33:50 +02:00
renovate[bot]
438f1d9656 Update junit-framework monorepo (#4715)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 16:00:43 +00:00
renovate[bot]
cb38aeef93 Update dependency com.diffplug.spotless to v7.2.1 (#4714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 16:00:13 +00:00
Jordan
7be0655b86 fix: do not create south road twice on unlink (#4713)
- this was changed from else if to if in 7623698a00 (diff-b05df598e90ce5418467b07e84ef85a80be8bac7c70929063ace9ede4d5cf52eL1000) (for unknown reason)
 - fixes #4704
2025-07-28 13:44:55 +02:00
Jordan
774298bef5 feat: apply coord limits to more commands (#4710)
- fixes #4375
2025-07-28 09:20:28 +02:00
45 changed files with 388 additions and 213 deletions

View File

@@ -11,7 +11,7 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
DISCORD_USERNAME: PlotSquared Release
DISCORD_AVATAR: https://raw.githubusercontent.com/IntellectualSites/Assets/main/plugins/PlotSquared/PlotSquared.png
uses: Ilshidur/action-discord@0.3.2
uses: Ilshidur/action-discord@0.4.0
with:
args: |
"<@&525015541815967744> <@&679322738552471574> <@&699293353862496266>"

View File

@@ -9,11 +9,11 @@ jobs:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

View File

@@ -9,11 +9,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v4
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

View File

@@ -20,9 +20,9 @@ jobs:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Java
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

View File

@@ -47,6 +47,7 @@ import org.bukkit.event.entity.LingeringPotionSplashEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.player.PlayerEggThrowEvent;
import org.bukkit.projectiles.BlockProjectileSource;
import org.bukkit.projectiles.ProjectileSource;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -157,14 +158,26 @@ public class ProjectileEventListener implements Listener {
@EventHandler
public void onProjectileHit(ProjectileHitEvent event) {
Projectile entity = event.getEntity();
if (cancelProjectileHit(event.getEntity())) {
event.setCancelled(true);
}
}
@EventHandler
public void onPlayerEggThrow(PlayerEggThrowEvent event) {
if (cancelProjectileHit(event.getEgg())) {
event.setHatching(false);
}
}
private boolean cancelProjectileHit(Projectile entity) {
Location location = BukkitUtil.adapt(entity.getLocation());
if (!this.plotAreaManager.hasPlotArea(location.getWorldName())) {
return;
return false;
}
PlotArea area = location.getPlotArea();
if (area == null) {
return;
return false;
}
Plot plot = area.getPlot(location);
ProjectileSource shooter = entity.getShooter();
@@ -172,15 +185,14 @@ public class ProjectileEventListener implements Listener {
if (!((Player) shooter).isOnline()) {
if (plot != null) {
if (plot.isAdded(((Player) shooter).getUniqueId()) || plot.getFlag(ProjectilesFlag.class)) {
return;
return false;
}
} else if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, ProjectilesFlag.class, true)) {
return;
return false;
}
entity.remove();
event.setCancelled(true);
return;
return true;
}
PlotPlayer<?> pp = BukkitUtil.adapt((Player) shooter);
@@ -189,38 +201,36 @@ public class ProjectileEventListener implements Listener {
Permission.PERMISSION_ADMIN_PROJECTILE_UNOWNED
)) {
entity.remove();
event.setCancelled(true);
return true;
}
return;
return false;
}
if (plot.isAdded(pp.getUUID()) || pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER) || plot.getFlag(
ProjectilesFlag.class) || (entity instanceof FishHook && plot.getFlag(
FishingFlag.class))) {
return;
return false;
}
entity.remove();
event.setCancelled(true);
return;
return true;
}
if (!(shooter instanceof Entity) && shooter != null) {
if (plot == null) {
entity.remove();
event.setCancelled(true);
return;
return true;
}
Location sLoc =
BukkitUtil.adapt(((BlockProjectileSource) shooter).getBlock().getLocation());
if (!area.contains(sLoc.getX(), sLoc.getZ())) {
entity.remove();
event.setCancelled(true);
return;
return true;
}
Plot sPlot = area.getOwnedPlotAbs(sLoc);
if (sPlot == null || !PlotHandler.sameOwners(plot, sPlot)) {
entity.remove();
event.setCancelled(true);
return true;
}
}
return false;
}
}

View File

@@ -18,6 +18,8 @@
*/
package com.plotsquared.core.backup;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.IOException;
@@ -30,12 +32,14 @@ import java.nio.file.Path;
*/
public class Backup {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Backup.class.getSimpleName());
private final BackupProfile owner;
private final long creationTime;
@Nullable
private final Path file;
Backup(final BackupProfile owner, final long creationTime, final Path file) {
Backup(final BackupProfile owner, final long creationTime, @Nullable final Path file) {
this.owner = owner;
this.creationTime = creationTime;
this.file = file;
@@ -49,7 +53,7 @@ public class Backup {
try {
Files.deleteIfExists(file);
} catch (final IOException e) {
e.printStackTrace();
LOGGER.error("Error deleting backup at {}", file, e);
}
}
}

View File

@@ -21,14 +21,15 @@ package com.plotsquared.core.backup;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.exception.PlotSquaredException;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -51,7 +52,7 @@ import java.util.concurrent.CompletableFuture;
*/
public class PlayerBackupProfile implements BackupProfile {
static final MiniMessage MINI_MESSAGE = MiniMessage.builder().build();
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + PlayerBackupProfile.class.getSimpleName());
private final UUID owner;
private final Plot plot;
@@ -87,7 +88,7 @@ public class PlayerBackupProfile implements BackupProfile {
Files.createDirectory(path);
}
} catch (final Exception e) {
e.printStackTrace();
LOGGER.error("Error resolving {} from {}", child, parent, e);
}
return path;
}
@@ -104,7 +105,7 @@ public class PlayerBackupProfile implements BackupProfile {
try {
Files.createDirectories(path);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error creating directory {}", path, e);
return Collections.emptyList();
}
}
@@ -117,11 +118,11 @@ public class PlayerBackupProfile implements BackupProfile {
backups.add(
new Backup(this, basicFileAttributes.creationTime().toMillis(), file));
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error getting attributes for file {} to create backup", file, e);
}
});
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error walking files from {}", path, e);
}
backups.sort(Comparator.comparingLong(Backup::getCreationTime).reversed());
return (this.backupCache = backups);
@@ -133,7 +134,7 @@ public class PlayerBackupProfile implements BackupProfile {
public void destroy() {
this.listBackups().whenCompleteAsync((backups, error) -> {
if (error != null) {
error.printStackTrace();
LOGGER.error("Error while listing backups", error);
}
backups.forEach(Backup::delete);
this.backupCache = null;
@@ -141,10 +142,12 @@ public class PlayerBackupProfile implements BackupProfile {
}
public @NonNull Path getBackupDirectory() {
return resolve(resolve(
resolve(backupManager.getBackupPath(), Objects.requireNonNull(plot.getArea().toString(), "plot area id")),
Objects.requireNonNull(plot.getId().toDashSeparatedString(), "plot id")
), Objects.requireNonNull(owner.toString(), "owner"));
return resolve(
resolve(
resolve(backupManager.getBackupPath(), Objects.requireNonNull(plot.getArea().toString(), "plot area id")),
Objects.requireNonNull(plot.getId().toDashSeparatedString(), "plot id")
), Objects.requireNonNull(owner.toString(), "owner")
);
}
@Override
@@ -156,7 +159,8 @@ public class PlayerBackupProfile implements BackupProfile {
backups.get(backups.size() - 1).delete();
}
final List<Plot> plots = Collections.singletonList(plot);
final boolean result = this.schematicHandler.exportAll(plots, getBackupDirectory().toFile(),
final boolean result = this.schematicHandler.exportAll(
plots, getBackupDirectory().toFile(),
"%world%-%id%-" + System.currentTimeMillis(), () ->
future.complete(new Backup(this, System.currentTimeMillis(), null))
);
@@ -180,7 +184,7 @@ public class PlayerBackupProfile implements BackupProfile {
try {
schematic = this.schematicHandler.getSchematic(backup.getFile().toFile());
} catch (SchematicHandler.UnsupportedFormatException e) {
e.printStackTrace();
LOGGER.error("Unsupported format for backup {}", backup.getFile(), e);
}
if (schematic == null) {
future.completeExceptionally(new IllegalArgumentException(
@@ -200,10 +204,9 @@ public class PlayerBackupProfile implements BackupProfile {
if (value) {
future.complete(null);
} else {
future.completeExceptionally(new RuntimeException(MINI_MESSAGE.escapeTags(
future.completeExceptionally(new PlotSquaredException(
TranslatableCaption
.of("schematics.schematic_paste_failed")
.getComponent(ConsolePlayer.getConsole()))));
.of("schematics.schematic_paste_failed")));
}
}
}

View File

@@ -32,6 +32,8 @@ import com.plotsquared.core.util.task.TaskManager;
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -47,6 +49,7 @@ import java.util.concurrent.TimeUnit;
@Singleton
public class SimpleBackupManager implements BackupManager {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + SimpleBackupManager.class.getSimpleName());
private final Path backupPath;
private final boolean automaticBackup;
private final int backupLimit;
@@ -112,7 +115,12 @@ public class SimpleBackupManager implements BackupManager {
TagResolver.resolver("reason", Tag.inserting(Component.text(throwable.getMessage())))
);
}
throwable.printStackTrace();
LOGGER.error(
"Error creating backup for plot {};{} and player {}",
plot.getArea(),
plot.getId(),
player == null ? "null" : player.getName(), throwable
);
} else {
if (player != null) {
player.sendMessage(TranslatableCaption.of("backups.backup_automatic_finished"));
@@ -128,6 +136,7 @@ public class SimpleBackupManager implements BackupManager {
return this.automaticBackup;
}
@NonNull
public Path getBackupPath() {
return this.backupPath;
}

View File

@@ -21,7 +21,6 @@ package com.plotsquared.core.command;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -58,8 +57,7 @@ public class Alias extends SubCommand {
return false;
}
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -24,6 +24,7 @@ import com.plotsquared.core.backup.BackupProfile;
import com.plotsquared.core.backup.NullBackupProfile;
import com.plotsquared.core.backup.PlayerBackupProfile;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.exception.PlotSquaredException;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -32,6 +33,8 @@ import com.plotsquared.core.util.task.RunnableVal3;
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.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.nio.file.Files;
@@ -57,6 +60,8 @@ import java.util.stream.Stream;
permission = "plots.backup")
public final class Backup extends Command {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Backup.class.getSimpleName());
private final BackupManager backupManager;
@Inject
@@ -326,20 +331,43 @@ public final class Backup extends Command {
if (backupProfile instanceof NullBackupProfile) {
player.sendMessage(
TranslatableCaption.of("backups.backup_impossible"),
TagResolver.resolver("plot", Tag.inserting(
TranslatableCaption.of("generic.generic_other").toComponent(player)
))
TagResolver.resolver(
"plot", Tag.inserting(
TranslatableCaption.of("generic.generic_other").toComponent(player)
)
)
);
} else {
backupProfile.listBackups().whenComplete((backups, throwable) -> {
if (throwable != null) {
Component reason;
if (throwable instanceof PlotSquaredException pe) {
reason = pe.getCaption().toComponent(player);
} else {
reason = Component.text(throwable.getMessage());
}
player.sendMessage(
TranslatableCaption.of("backups.backup_load_failure"),
TagResolver.resolver("reason", Tag.inserting(Component.text(throwable.getMessage())))
TagResolver.resolver("reason", Tag.inserting(reason))
);
LOGGER.error("Error loading player ({}) backup", player.getName(), throwable);
return;
}
if (number < 1 || number > backups.size()) {
player.sendMessage(
TranslatableCaption.of("backups.backup_impossible"),
TagResolver.resolver(
"plot",
Tag.inserting(TranslatableCaption
.of("generic.generic_invalid_choice")
.toComponent(player))
)
);
throwable.printStackTrace();
} else {
if (number < 1 || number > backups.size()) {
final com.plotsquared.core.backup.Backup backup =
backups.get(number - 1);
if (backup == null || backup.getFile() == null || !Files
.exists(backup.getFile())) {
player.sendMessage(
TranslatableCaption.of("backups.backup_impossible"),
TagResolver.resolver(
@@ -350,37 +378,23 @@ public final class Backup extends Command {
)
);
} else {
final com.plotsquared.core.backup.Backup backup =
backups.get(number - 1);
if (backup == null || backup.getFile() == null || !Files
.exists(backup.getFile())) {
player.sendMessage(
TranslatableCaption.of("backups.backup_impossible"),
TagResolver.resolver(
"plot",
Tag.inserting(TranslatableCaption
.of("generic.generic_invalid_choice")
.toComponent(player))
)
);
} else {
CmdConfirm.addPending(player, "/plot backup load " + number,
() -> backupProfile.restoreBackup(backup, player)
.whenComplete((n, error) -> {
if (error != null) {
player.sendMessage(
TranslatableCaption.of("backups.backup_load_failure"),
TagResolver.resolver(
"reason",
Tag.inserting(Component.text(error.getMessage()))
)
);
} else {
player.sendMessage(TranslatableCaption.of("backups.backup_load_success"));
}
})
);
}
CmdConfirm.addPending(
player, "/plot backup load " + number,
() -> backupProfile.restoreBackup(backup, player)
.whenComplete((n, error) -> {
if (error != null) {
player.sendMessage(
TranslatableCaption.of("backups.backup_load_failure"),
TagResolver.resolver(
"reason",
Tag.inserting(Component.text(error.getMessage()))
)
);
} else {
player.sendMessage(TranslatableCaption.of("backups.backup_load_success"));
}
})
);
}
}
});

View File

@@ -20,6 +20,7 @@ package com.plotsquared.core.command;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlayerBuyPlotEvent;
import com.plotsquared.core.events.Result;
@@ -84,8 +85,9 @@ public class Buy extends Command {
checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned"));
checkTrue(!plot.isOwner(player.getUUID()), TranslatableCaption.of("economy.cannot_buy_own"));
Set<Plot> plots = plot.getConnectedPlots();
int plotCount = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(plot.getWorldName());
checkTrue(
player.getPlotCount() + plots.size() <= player.getAllowedPlots(),
plotCount + plots.size() <= player.getAllowedPlots(),
TranslatableCaption.of("permission.cant_claim_more_plots"),
TagResolver.resolver("amount", Tag.inserting(Component.text(player.getAllowedPlots())))
);

View File

@@ -26,7 +26,6 @@ import com.plotsquared.core.events.PlayerClaimPlotEvent;
import com.plotsquared.core.events.PlotMergeEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Direction;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.MetaDataAccess;
import com.plotsquared.core.player.PlayerMetaDataKeys;
@@ -72,8 +71,7 @@ public class Claim extends SubCommand {
if (args.length >= 1) {
schematic = args[0];
}
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -90,7 +88,7 @@ public class Claim extends SubCommand {
boolean force = event.getEventResult() == Result.FORCE;
int currentPlots = Settings.Limit.GLOBAL ?
player.getPlotCount() :
player.getPlotCount(location.getWorldName());
player.getPlotCount(plot.getWorldName());
final PlotArea area = plot.getArea();

View File

@@ -68,8 +68,8 @@ public class Continue extends SubCommand {
return false;
}
int size = plot.getConnectedPlots().size();
if (!Settings.Done.COUNTS_TOWARDS_LIMIT && (player.getAllowedPlots()
< player.getPlotCount() + size)) {
int plotCount = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(plot.getWorldName());
if (!Settings.Done.COUNTS_TOWARDS_LIMIT && (player.getAllowedPlots() < plotCount + size)) {
player.sendMessage(
TranslatableCaption.of("permission.cant_claim_more_plots"),
TagResolver.resolver("amount", Tag.inserting(Component.text(player.getAllowedPlots())))

View File

@@ -19,7 +19,6 @@
package com.plotsquared.core.command;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -37,8 +36,7 @@ public class Copy extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot1 = location.getPlotAbs();
Plot plot1 = player.getCurrentPlot();
if (plot1 == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -22,7 +22,6 @@ import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.generator.HybridPlotWorld;
import com.plotsquared.core.generator.HybridUtils;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import net.kyori.adventure.text.Component;
@@ -47,8 +46,7 @@ public class CreateRoadSchematic extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -57,7 +55,7 @@ public class CreateRoadSchematic extends SubCommand {
player.sendMessage(TranslatableCaption.of("schematics.schematic_too_large"));
return false;
}
if (!(location.getPlotArea() instanceof HybridPlotWorld)) {
if (!(plot.getArea() instanceof HybridPlotWorld)) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
}
this.hybridUtils.setupRoadSchematic(plot);

View File

@@ -22,7 +22,6 @@ import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.generator.HybridPlotManager;
import com.plotsquared.core.generator.HybridUtils;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
@@ -57,8 +56,7 @@ public class DebugRoadRegen extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (args.length < 1) {
player.sendMessage(
TranslatableCaption.of("commandconfig.command_syntax"),
@@ -92,8 +90,7 @@ public class DebugRoadRegen extends SubCommand {
}
public boolean regenPlot(PlotPlayer<?> player) {
Location location = player.getLocation();
PlotArea area = location.getPlotArea();
PlotArea area = player.getCurrentPlot().getArea();
if (area == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
return false;
@@ -148,8 +145,7 @@ public class DebugRoadRegen extends SubCommand {
return false;
}
Location location = player.getLocation();
PlotArea area = location.getPlotArea();
PlotArea area = player.getCurrentPlot().getArea();
if (area == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
}

View File

@@ -23,7 +23,6 @@ import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.events.TeleportCause;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -61,8 +60,7 @@ public class Delete extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -92,7 +90,7 @@ public class Delete extends SubCommand {
final java.util.Set<Plot> plots = plot.getConnectedPlots();
final int currentPlots = Settings.Limit.GLOBAL ?
player.getPlotCount() :
player.getPlotCount(location.getWorldName());
player.getPlotCount(plot.getWorldName());
Runnable run = () -> {
if (plot.getRunning() > 0) {
player.sendMessage(TranslatableCaption.of("errors.wait_for_timer"));

View File

@@ -70,8 +70,7 @@ public class Deny extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -26,7 +26,6 @@ import com.plotsquared.core.events.PlotDoneEvent;
import com.plotsquared.core.events.PlotFlagAddEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.generator.HybridUtils;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -61,8 +60,7 @@ public class Done extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if ((plot == null) || !plot.hasOwner()) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -73,7 +73,7 @@ public class Download extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
String world = player.getLocation().getWorldName();
String world = player.getCurrentPlot().getWorldName();
if (!this.plotAreaManager.hasPlotArea(world)) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
return false;

View File

@@ -27,7 +27,6 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlotFlagAddEvent;
import com.plotsquared.core.events.PlotFlagRemoveEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -179,8 +178,7 @@ public final class FlagCommand extends Command {
* @return {@code true} if the player is allowed to modify the flags at their current location
*/
private static boolean checkRequirements(final @NonNull PlotPlayer<?> player) {
final Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -344,7 +342,7 @@ public final class FlagCommand extends Command {
if (plotFlag == null) {
return;
}
Plot plot = player.getLocation().getPlotAbs();
Plot plot = player.getCurrentPlot();
PlotFlagAddEvent event = eventDispatcher.callFlagAdd(plotFlag, plot);
if (event.getEventResult() == Result.DENY) {
player.sendMessage(
@@ -409,7 +407,7 @@ public final class FlagCommand extends Command {
if (plotFlag == null) {
return;
}
Plot plot = player.getLocation().getPlotAbs();
Plot plot = player.getCurrentPlot();
PlotFlagAddEvent event = eventDispatcher.callFlagAdd(plotFlag, plot);
if (event.getEventResult() == Result.DENY) {
player.sendMessage(
@@ -419,7 +417,7 @@ public final class FlagCommand extends Command {
return;
}
boolean force = event.getEventResult() == Result.FORCE;
final PlotFlag localFlag = player.getLocation().getPlotAbs().getFlagContainer()
final PlotFlag localFlag = player.getCurrentPlot().getFlagContainer()
.getFlag(event.getFlag().getClass());
if (!force) {
for (String entry : args[1].split(",")) {
@@ -444,7 +442,7 @@ public final class FlagCommand extends Command {
return;
}
boolean result =
player.getLocation().getPlotAbs().setFlag(localFlag.merge(parsed.getValue()));
player.getCurrentPlot().setFlag(localFlag.merge(parsed.getValue()));
if (!result) {
player.sendMessage(TranslatableCaption.of("flag.flag_not_added"));
return;
@@ -484,7 +482,7 @@ public final class FlagCommand extends Command {
if (flag == null) {
return;
}
final Plot plot = player.getLocation().getPlotAbs();
final Plot plot = player.getCurrentPlot();
final PlotFlag<?, ?> flagWithOldValue = plot.getFlagContainer().getFlag(flag.getClass());
PlotFlagRemoveEvent event = eventDispatcher.callFlagRemove(flag, plot);
if (event.getEventResult() == Result.DENY) {
@@ -687,7 +685,7 @@ public final class FlagCommand extends Command {
.build()
);
// Default value
final String defaultValue = player.getLocation().getPlotArea().getFlagContainer()
final String defaultValue = player.getCurrentPlot().getArea().getFlagContainer()
.getFlagErased(plotFlag.getClass()).toString();
player.sendMessage(
TranslatableCaption.of("flag.flag_info_default_value"),

View File

@@ -177,8 +177,14 @@ public class Grant extends Command {
commands.addAll(TabCompletions.completePlayers(player, args[0], Collections.emptyList()));
}
return commands;
} else if (args.length == 2) {
final String subcommand = args[0].toLowerCase();
if ((subcommand.equals("add") && player.hasPermission(Permission.PERMISSION_GRANT_ADD)) ||
(subcommand.equals("check") && player.hasPermission(Permission.PERMISSION_GRANT_CHECK))) {
return TabCompletions.completePlayers(player, args[1], Collections.emptyList());
}
}
return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList());
return Collections.emptyList();
}
}

View File

@@ -65,8 +65,7 @@ public class Kick extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot = location.getPlot();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -124,7 +123,7 @@ public class Kick extends SubCommand {
);
return;
}
Location spawn = this.worldUtil.getSpawn(location.getWorldName());
Location spawn = this.worldUtil.getSpawn(plot.getWorldName());
player2.sendMessage(TranslatableCaption.of("kick.you_got_kicked"));
if (plot.equals(spawn.getPlot())) {
Location newSpawn = this.worldUtil.getSpawn(this.plotAreaManager.getAllWorlds()[0]);
@@ -148,8 +147,7 @@ public class Kick extends SubCommand {
@Override
public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
return Collections.emptyList();
}

View File

@@ -150,8 +150,8 @@ public class ListCmd extends SubCommand {
page = 0;
}
String world = player.getLocation().getWorldName();
PlotArea area = player.getApplicablePlotArea();
String world = player.getCurrentPlot().getWorldName();
PlotArea area = player.getCurrentPlot().getArea();
String arg = args[0].toLowerCase();
final boolean[] sort = new boolean[]{true};

View File

@@ -68,7 +68,7 @@ public class Load extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, final String[] args) {
final String world = player.getLocation().getWorldName();
final String world = player.getCurrentPlot().getWorldName();
if (!this.plotAreaManager.hasPlotArea(world)) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world"));
return false;

View File

@@ -275,7 +275,7 @@ public class MainCommand extends Command {
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]);
Plot newPlot = Plot.fromString(area, data.args()[0], data.player());
return preparePlotArgument(newPlot, data, area)
.thenApply(d -> d.flatMap(x -> prepareFlagArgument(x, area)));
} else {
@@ -296,7 +296,7 @@ public class MainCommand extends Command {
final boolean isDenied = newPlot.isDenied(player.getUUID());
if (!isAdmin) {
if (isDenied) {
return CompletableFuture.completedFuture(Optional.of(data));
throw new CommandException(TranslatableCaption.of("deny.cannot_interact"));
}
if (area != null && area.equals(newPlot.getArea()) && !player.hasPermission(Permission.PERMISSION_ADMIN_AREA_SUDO)) {
return CompletableFuture.completedFuture(Optional.of(data));

View File

@@ -20,7 +20,6 @@ package com.plotsquared.core.command;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.TeleportCause;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -36,8 +35,7 @@ public class Middle extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] arguments) {
Location location = player.getLocation();
Plot plot = location.getPlot();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -20,7 +20,6 @@ package com.plotsquared.core.command;
import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -55,8 +54,7 @@ public class Move extends SubCommand {
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) {
Location location = player.getLocation();
Plot plot1 = location.getPlotAbs();
Plot plot1 = player.getCurrentPlot();
if (plot1 == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return CompletableFuture.completedFuture(false);

View File

@@ -23,7 +23,6 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlotFlagAddEvent;
import com.plotsquared.core.events.PlotFlagRemoveEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -74,8 +73,7 @@ public class Music extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -21,7 +21,6 @@ package com.plotsquared.core.command;
import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -56,8 +55,7 @@ public class Remove extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -132,8 +130,7 @@ public class Remove extends SubCommand {
@Override
public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
return Collections.emptyList();
}

View File

@@ -22,7 +22,6 @@ import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
@@ -102,8 +101,7 @@ public class SchematicCmd extends SubCommand {
);
break;
}
Location loc = player.getLocation();
final Plot plot = loc.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
@@ -247,8 +245,7 @@ public class SchematicCmd extends SubCommand {
player.sendMessage(TranslatableCaption.of("error.task_in_process"));
return false;
}
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -78,7 +78,7 @@ public class Set extends SubCommand {
@Override
public boolean set(PlotPlayer<?> player, final Plot plot, String value) {
final PlotArea plotArea = player.getLocation().getPlotArea();
final PlotArea plotArea = player.getCurrentPlot().getArea();
if (plotArea == null) {
return false;
}

View File

@@ -19,7 +19,6 @@
package com.plotsquared.core.command;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -32,8 +31,7 @@ public abstract class SetCommand extends SubCommand {
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -19,7 +19,6 @@
package com.plotsquared.core.command;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -44,8 +43,7 @@ public class Swap extends SubCommand {
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) {
Location location = player.getLocation();
Plot plot1 = location.getPlotAbs();
Plot plot1 = player.getCurrentPlot();
if (plot1 == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return CompletableFuture.completedFuture(false);
@@ -79,8 +77,10 @@ public class Swap extends SubCommand {
String p1 = plot1.toString();
String p2 = plot2.toString();
return plot1.getPlotModificationManager().move(plot2, player, () -> {
}, true).thenApply(result -> {
return plot1.getPlotModificationManager().move(
plot2, player, () -> {
}, true
).thenApply(result -> {
if (result) {
player.sendMessage(
TranslatableCaption.of("swap.swap_success"),

View File

@@ -22,7 +22,6 @@ import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlotUnlinkEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
@@ -51,8 +50,7 @@ public class Unlink extends SubCommand {
@Override
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
Location location = player.getLocation();
final Plot plot = location.getPlotAbs();
final Plot plot = player.getCurrentPlot();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;

View File

@@ -0,0 +1,62 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.exception;
import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.configuration.caption.LocaleHolder;
/**
* Internal use only. Used to allow adventure captions to be used in an exception
*
* @since TODO
*/
public final class PlotSquaredException extends RuntimeException {
private final Caption caption;
/**
* Create a new instance with the given caption
*
* @param caption caption
*/
public PlotSquaredException(Caption caption) {
this.caption = caption;
}
/**
* Create a new instance with the given caption and cause
*
* @param caption caption
* @param cause cause
*/
public PlotSquaredException(Caption caption, Exception cause) {
super(cause);
this.caption = caption;
}
@Override
public String getMessage() {
return caption.getComponent(LocaleHolder.console());
}
public Caption getCaption() {
return caption;
}
}

View File

@@ -290,6 +290,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
*
* @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea}
*/
@Nullable
public Plot getCurrentPlot() {
try (final MetaDataAccess<Plot> lastPlotAccess =
this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
@@ -319,7 +320,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
*/
public int getPlotCount() {
if (!Settings.Limit.GLOBAL) {
return getPlotCount(getLocation().getWorldName());
return getPlotCount(getCurrentPlot().getWorldName());
}
final AtomicInteger count = new AtomicInteger(0);
final UUID uuid = getUUID();
@@ -339,7 +340,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
public int getClusterCount() {
if (!Settings.Limit.GLOBAL) {
return getClusterCount(getLocation().getWorldName());
return getClusterCount(getCurrentPlot().getWorldName());
}
final AtomicInteger count = new AtomicInteger(0);
this.plotAreaManager.forEachPlotArea(value -> {
@@ -408,7 +409,11 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
}
public PlotArea getApplicablePlotArea() {
return this.plotAreaManager.getApplicablePlotArea(getLocation());
Plot plot = getCurrentPlot();
if (plot == null) {
return this.plotAreaManager.getApplicablePlotArea(getLocation());
}
return plot.getArea();
}
@Override
@@ -614,16 +619,16 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
PlotId id = plot.getId();
int x = id.getX();
int z = id.getY();
ByteBuffer buffer = ByteBuffer.allocate(13);
ByteBuffer buffer = ByteBuffer.allocate(14);
buffer.putShort((short) x);
buffer.putShort((short) z);
Location location = getLocation();
buffer.putInt(location.getX());
buffer.put((byte) location.getY());
buffer.putShort((short) location.getY());
buffer.putInt(location.getZ());
setPersistentMeta("quitLoc", buffer.array());
} else if (hasPersistentMeta("quitLoc")) {
removePersistentMeta("quitLoc");
setPersistentMeta("quitLocV2", buffer.array());
} else if (hasPersistentMeta("quitLocV2")) {
removePersistentMeta("quitLocV2");
}
if (plot != null) {
this.eventDispatcher.callLeave(this, plot);
@@ -700,11 +705,18 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
return;
}
PlotArea area = ((SinglePlotAreaManager) manager).getArea();
boolean V2 = false;
byte[] arr = PlotPlayer.this.getPersistentMeta("quitLoc");
if (arr == null) {
return;
arr = PlotPlayer.this.getPersistentMeta("quitLocV2");
if (arr == null) {
return;
}
V2 = true;
removePersistentMeta("quitLocV2");
} else {
removePersistentMeta("quitLoc");
}
removePersistentMeta("quitLoc");
if (!getMeta("teleportOnLogin", true)) {
return;
@@ -714,7 +726,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
final int plotZ = quitWorld.getShort();
PlotId id = PlotId.of(plotX, plotZ);
int x = quitWorld.getInt();
int y = quitWorld.get() & 0xFF;
int y = V2 ? quitWorld.getShort() : (quitWorld.get() & 0xFF);
int z = quitWorld.getInt();
Plot plot = area.getOwnedPlot(id);
@@ -748,10 +760,11 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
}
}
} catch (Throwable e) {
e.printStackTrace();
LOGGER.error("Error populating persistent meta for player {}", PlotPlayer.this.getName(), e);
}
}
});
}
);
}
}

View File

@@ -321,7 +321,8 @@ public class Plot {
}
/**
* Get the plot from a string.
* Get the plot from a string. Performs a check to ensure Plot#getBottomAbs is not outside world bounds
* (x/z +/- 30,000,000) to prevent crashes
*
* @param player Provides a context for what world to search in. Prefixing the term with 'world_name;' will override this context.
* @param arg The search term
@@ -332,6 +333,31 @@ public class Plot {
final @Nullable PlotPlayer<?> player,
final @Nullable String arg,
final boolean message
) {
Plot plot = getPlotFromStringUnchecked(player, arg, message);
if (plot != null && !WorldUtil.isValidLocation(plot.getBottomAbs())) {
if (message) {
(player == null ? ConsolePlayer.getConsole() : player).sendMessage(TranslatableCaption.of(
"invalid.world_location_plot"));
}
return null;
}
return plot;
}
/**
* Get the plot from a string. Does not perform a check on world bounds.
*
* @param player Provides a context for what world to search in. Prefixing the term with 'world_name;' will override this context.
* @param arg The search term
* @param message If a message should be sent to the player if a plot cannot be found
* @return The plot if only 1 result is found, or null
* @since 7.5.5
*/
public static @Nullable Plot getPlotFromStringUnchecked(
final @Nullable PlotPlayer<?> player,
final @Nullable String arg,
final boolean message
) {
if (arg == null) {
if (player == null) {
@@ -389,13 +415,51 @@ public class Plot {
}
/**
* Gets a plot from a string e.g. [area];[id]
* Gets a plot from a string e.g. [area];[id]. Performs a check to ensure Plot#getBottomAbs is not outside world bounds
* (x/z +/- 30,000,000) to prevent crashes
*
* @param defaultArea if no area is specified
* @param string plot id/area + id
* @return New or existing plot object
*/
public static @Nullable Plot fromString(final @Nullable PlotArea defaultArea, final @NonNull String string) {
return fromString(defaultArea, string, null);
}
/**
* Gets a plot from a string e.g. [area];[id]. Performs a check to ensure Plot#getBottomAbs is not outside world bounds
* (x/z +/- 30,000,000) to prevent crashes
*
* @param defaultArea if no area is specified
* @param string plot id/area + id
* @param player {@link PlotPlayer} player to notify if plot is invalid (outside bounds)
* @return New or existing plot object
* @since 7.5.5
*/
public static @Nullable Plot fromString(
final @Nullable PlotArea defaultArea,
final @NonNull String string,
final @Nullable PlotPlayer<?> player
) {
Plot plot = fromStringUnchecked(defaultArea, string);
if (plot != null && !WorldUtil.isValidLocation(plot.getBottomAbs())) {
if (player != null) {
player.sendMessage(TranslatableCaption.of("invalid.world_location_plot"));
}
return null;
}
return plot;
}
/**
* Gets a plot from a string e.g. [area];[id]. Does not perform a check on world bounds.
*
* @param defaultArea if no area is specified
* @param string plot id/area + id
* @return New or existing plot object
* @since 7.5.5
*/
public static @Nullable Plot fromStringUnchecked(final @Nullable PlotArea defaultArea, final @NonNull String string) {
final String[] split = string.split("[;,]");
if (split.length == 2) {
if (defaultArea != null) {
@@ -419,7 +483,8 @@ public class Plot {
}
/**
* Return a new/cached plot object at a given location.
* Return a new/cached plot object at a given location. Does not check world bounds for potential crashes, these should be
* performed before (or after) this method is used.
*
* <p>
* Use {@link PlotPlayer#getCurrentPlot()} if a player is expected here.

View File

@@ -371,8 +371,7 @@ public final class PlotModificationManager {
manager.createRoadSouthEast(current, queue);
}
}
}
if (current.isMerged(Direction.SOUTH)) {
} else if (current.isMerged(Direction.SOUTH)) {
manager.createRoadSouth(current, queue);
}
}

View File

@@ -67,7 +67,7 @@ public class PlotTitle {
* Provides a string representation of this plot title value (used in placeholders).
*
* @return the plot title representation in the format {@code "<title>" "<subtitle>"}
* @since TODO
* @since 7.5.5
*/
@Override
public String toString() {

View File

@@ -135,6 +135,7 @@ public abstract class SchematicHandler {
}
final String filename;
final String website;
final @Nullable UUID finalUuid = uuid;
if (uuid == null) {
uuid = UUID.randomUUID();
website = Settings.Web.URL + "upload.php?" + uuid;
@@ -144,10 +145,11 @@ public abstract class SchematicHandler {
filename = file + '.' + extension;
}
final URL url;
String uri = Settings.Web.URL + "?key=" + uuid + "&type=" + extension;
try {
url = URI.create(Settings.Web.URL + "?key=" + uuid + "&type=" + extension).toURL();
url = URI.create(uri).toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
LOGGER.error("Malformed URI `{}`", uri, e);
whenDone.run();
return;
}
@@ -193,7 +195,7 @@ public abstract class SchematicHandler {
}
TaskManager.runTask(whenDone);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error while uploading schematic for UUID {}", finalUuid, e);
TaskManager.runTask(whenDone);
}
});
@@ -388,8 +390,14 @@ public abstract class SchematicHandler {
}
queue.enqueue();
} catch (Exception e) {
e.printStackTrace();
TaskManager.runTask(whenDone);
LOGGER.error(
"Error pasting schematic to plot {};{} for player {}",
plot.getArea(),
plot.getId(),
actor == null ? "null" : actor.getName(),
e
);
}
}
@@ -456,7 +464,7 @@ public abstract class SchematicHandler {
Clipboard clip = reader.read();
return new Schematic(clip);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error reading schematic from file {}", file.getAbsolutePath(), e);
}
} else {
throw new UnsupportedFormatException("This schematic format is not recognised or supported.");
@@ -470,7 +478,7 @@ public abstract class SchematicHandler {
InputStream inputStream = Channels.newInputStream(readableByteChannel);
return getSchematic(inputStream);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error reading schematic from {}", url, e);
}
return null;
}
@@ -486,7 +494,7 @@ public abstract class SchematicHandler {
Clipboard clip = schematicReader.read();
return new Schematic(clip);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error reading schematic", e);
}
}
return null;
@@ -515,7 +523,7 @@ public abstract class SchematicHandler {
}
return schematics;
} catch (JsonParseException | IOException e) {
e.printStackTrace();
LOGGER.error("Error retrieving saves for UUID {}", uuid, e);
}
return null;
}
@@ -532,7 +540,7 @@ public abstract class SchematicHandler {
try (NBTOutputStream nos = new NBTOutputStream(new GZIPOutputStream(output, true))) {
nos.writeNamedTag("Schematic", tag);
} catch (IOException e1) {
e1.printStackTrace();
LOGGER.error("Error uploading schematic for UUID {}", uuid, e1);
}
}
}, whenDone);
@@ -556,9 +564,9 @@ public abstract class SchematicHandler {
nbtStream.writeNamedTag("Schematic", tag);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
LOGGER.error("Error saving schematic at {}", path, e);
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Error saving schematic at {}", path, e);
return false;
}
return true;
@@ -581,7 +589,7 @@ public abstract class SchematicHandler {
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities));
if (biomeBuffer.size() == 0 || biomePalette.size() == 0) {
if (biomeBuffer.size() == 0 || biomePalette.isEmpty()) {
return;
}
@@ -733,10 +741,7 @@ public abstract class SchematicHandler {
}
BaseBlock block = aabb.getWorld().getFullBlock(point);
if (block.getNbtData() != null) {
Map<String, Tag> values = new HashMap<>();
for (Map.Entry<String, Tag> entry : block.getNbtData().getValue().entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
Map<String, Tag> values = new HashMap<>(block.getNbtData().getValue());
// Positions are kept in NBT, we don't want that.
values.remove("x");

View File

@@ -49,10 +49,12 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
/**
* Registry that contains {@link Placeholder placeholders}
@@ -127,6 +129,22 @@ public final class PlaceholderRegistry {
}
return legacyComponent(TranslatableCaption.of("info.unknown"), player);
});
this.createPlaceholder("currentplot_owners", (player, plot) -> {
if (plot.getFlag(ServerPlotFlag.class)) {
return legacyComponent(TranslatableCaption.of("info.server"), player);
}
final Set<UUID> plotOwners = plot.getOwners();
if (plotOwners.isEmpty()) {
return legacyComponent(TranslatableCaption.of("generic.generic_unowned"), player);
}
return plotOwners.stream().map(PlotSquared.platform().playerManager()::getUsernameCaption).map(f -> {
try {
return f.get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS).getComponent(player);
} catch (final Exception ignored) {
return legacyComponent(TranslatableCaption.of("info.unknown"), player);
}
}).collect(Collectors.joining(", "));
});
this.createPlaceholder("currentplot_members", (player, plot) -> {
if (plot.getMembers().isEmpty() && plot.getTrusted().isEmpty()) {
return legacyComponent(TranslatableCaption.of("info.none"), player);

View File

@@ -234,6 +234,7 @@
"invalid.not_valid_number": "<prefix><red>That's not a valid number within the range: </red><gray><value></gray>",
"invalid.not_valid_plot_id": "<prefix><red>That's not a valid plot ID.</red>",
"invalid.origin_cant_be_target": "<prefix><red>The origin and target location cannot be the same.</red>",
"invalid.world_location_plot": "<prefix><red>The target plot is invalid.</red>",
"invalid.found_no_plots": "<prefix><red>Found no plots with your search query.</red>",
"invalid.number_not_in_range": "<prefix><red>That's not a valid number within the range: <gray>(<min>, <max>)</gray></red>",
"invalid.number_not_positive": "<red>That's not a positive number: <gray><value></gray></red>",
@@ -414,6 +415,7 @@
"deny.denied_added": "<prefix><dark_aqua>You successfully denied the player from this plot.</dark_aqua>",
"deny.no_enter": "<prefix><red>You are denied from the plot <red><gold><plot></gold><red> and therefore not allowed to enter.</red>",
"deny.you_got_denied": "<prefix><red>You are denied from the plot you were previously on, and got teleported to spawn.</red>",
"deny.cannot_interact": "<prefix><red>You are denied from the plot <red><gold><plot></gold><red> and therefore cannot interact with it.</red>",
"deny.cant_remove_owner": "<prefix><red>You can't remove the plot owner.</red>",
"kick.player_not_in_plot": "<prefix><red>The player <gray><player></gray> is not on this plot.</red>",
"kick.cannot_kick_player": "<prefix><red>You cannot kick the player <gray><player></gray>.</red>",

View File

@@ -20,7 +20,7 @@ plugins {
}
group = "com.intellectualsites.plotsquared"
version = "7.5.5-SNAPSHOT"
version = "7.5.7-SNAPSHOT"
if (!File("$rootDir/.git").exists()) {
logger.lifecycle("""
@@ -67,8 +67,8 @@ subprojects {
dependencies {
// Tests
testImplementation("org.junit.jupiter:junit-jupiter:5.13.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.3")
testImplementation("org.junit.jupiter:junit-jupiter:5.13.4")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.4")
}
plugins.withId("java") {

View File

@@ -2,21 +2,21 @@
# Platform expectations
paper = "1.20.4-R0.1-SNAPSHOT"
guice = "7.0.0"
spotbugs = "4.9.3"
checkerqual = "3.49.5"
spotbugs = "4.9.4"
checkerqual = "3.50.0"
gson = "2.10"
guava = "31.1-jre"
snakeyaml = "2.0"
adventure = "4.23.0"
adventure-bukkit = "4.4.0"
adventure = "4.24.0"
adventure-bukkit = "4.4.1"
log4j = "2.19.0"
# Plugins
worldedit = "7.2.20"
fawe = "2.13.0"
worldedit = "7.3.16"
fawe = "2.13.1"
placeholderapi = "2.11.6"
luckperms = "5.5"
essentialsx = "2.21.1"
essentialsx = "2.21.2"
mvdwapi = "3.1.1"
# Third party
@@ -33,9 +33,9 @@ vault = "1.7.1"
serverlib = "2.3.7"
# Gradle plugins
shadow = "8.3.8"
shadow = "8.3.9"
grgit = "4.1.1"
spotless = "7.2.0"
spotless = "7.2.1"
publish = "0.34.0"
runPaper = "2.3.1"