Compare commits

..

7 Commits

Author SHA1 Message Date
Pierre Maurice Schwang
12c56b3973 fix: compile against 1.20.4 2025-09-05 23:16:01 +02:00
Pierre Maurice Schwang
190c73493d fix: missing continue and license header 2025-09-03 23:10:06 +02:00
Pierre Maurice Schwang
58492ef59e fix: signs with component lines 2025-09-03 23:00:55 +02:00
Pierre Maurice Schwang
2dad3c2fe1 feat: sign contents 2025-09-03 00:34:29 +02:00
Pierre Maurice Schwang
44e024df5e feat: use NMS to populate tile entities 2025-08-31 01:27:28 +02:00
Pierre Maurice Schwang
5ed4dee99e fix: block nbt population 2025-08-24 02:07:16 +02:00
Pierre Maurice Schwang
c592a2ecc8 chore: 1.17 is not supported anymore 2025-08-24 02:06:51 +02:00
42 changed files with 577 additions and 543 deletions

View File

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

View File

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

View File

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

View File

@@ -41,6 +41,7 @@ dependencies {
compileOnly(libs.luckperms) compileOnly(libs.luckperms)
compileOnly(libs.essentialsx) { compileOnly(libs.essentialsx) {
exclude(group = "org.spigotmc") exclude(group = "org.spigotmc")
exclude(group = "io.papermc.paper")
} }
compileOnly(libs.mvdwapi) { isTransitive = false } compileOnly(libs.mvdwapi) { isTransitive = false }
@@ -74,7 +75,7 @@ tasks.named<ShadowJar>("shadowJar") {
relocate("net.kyori.examination", "com.plotsquared.core.configuration.examination") relocate("net.kyori.examination", "com.plotsquared.core.configuration.examination")
relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib")
relocate("org.bstats", "com.plotsquared.metrics") relocate("org.bstats", "com.plotsquared.metrics")
relocate("org.enginehub", "com.plotsquared.squirrelid") relocate("org.enginehub.squirrelid", "com.plotsquared.squirrelid")
relocate("org.khelekore.prtree", "com.plotsquared.prtree") relocate("org.khelekore.prtree", "com.plotsquared.prtree")
relocate("com.google.inject", "com.plotsquared.google") relocate("com.google.inject", "com.plotsquared.google")
relocate("org.aopalliance", "com.plotsquared.core.aopalliance") relocate("org.aopalliance", "com.plotsquared.core.aopalliance")

View File

@@ -90,12 +90,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
this.plotGenerator = generator; this.plotGenerator = generator;
this.platformGenerator = this; this.platformGenerator = this;
this.populators = new ArrayList<>(); this.populators = new ArrayList<>();
int minecraftMinorVersion = PlotSquared.platform().serverVersion()[1];
if (minecraftMinorVersion >= 17) {
this.populators.add(new BlockStatePopulator(this.plotGenerator)); this.populators.add(new BlockStatePopulator(this.plotGenerator));
} else {
this.populators.add(new LegacyBlockStatePopulator(this.plotGenerator));
}
this.full = true; this.full = true;
this.useNewGenerationMethods = PlotSquared.platform().serverVersion()[1] >= 19; this.useNewGenerationMethods = PlotSquared.platform().serverVersion()[1] >= 19;
this.biomeProvider = new BukkitPlotBiomeProvider(); this.biomeProvider = new BukkitPlotBiomeProvider();

View File

@@ -36,6 +36,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Random; import java.util.Random;
@Deprecated(since = "TODO")
final class LegacyBlockStatePopulator extends BlockPopulator { final class LegacyBlockStatePopulator extends BlockPopulator {
private final IndependentPlotGenerator plotGenerator; private final IndependentPlotGenerator plotGenerator;

View File

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

View File

@@ -0,0 +1,80 @@
/*
* 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.bukkit.schematic;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongArrayTag;
import com.sk89q.jnbt.Tag;
import java.lang.reflect.Type;
final class NbtGsonSerializer implements JsonSerializer<Tag> {
@Override
public JsonElement serialize(final Tag src, final Type typeOfSrc, final JsonSerializationContext context) {
if (src instanceof CompoundTag compoundTag) {
JsonObject object = new JsonObject();
compoundTag.getValue().forEach((s, tag) -> object.add(s, context.serialize(tag)));
return object;
}
if (src instanceof ListTag listTag) {
JsonArray array = new JsonArray();
listTag.getValue().forEach(tag -> array.add(context.serialize(tag)));
return array;
}
if (src instanceof ByteArrayTag byteArrayTag) {
JsonArray array = new JsonArray();
for (final byte b : byteArrayTag.getValue()) {
array.add(b);
}
return array;
}
if (src instanceof IntArrayTag intArrayTag) {
JsonArray array = new JsonArray();
for (final int i : intArrayTag.getValue()) {
array.add(i);
}
return array;
}
if (src instanceof LongArrayTag longArrayTag) {
JsonArray array = new JsonArray();
for (final long l : longArrayTag.getValue()) {
array.add(l);
}
return array;
}
if (src.getValue() instanceof Number number) {
return new JsonPrimitive(number);
}
if (src.getValue() instanceof String string) {
return new JsonPrimitive(string);
}
throw new IllegalArgumentException("Don't know how to serialize " + src);
}
}

View File

@@ -18,158 +18,93 @@
*/ */
package com.plotsquared.bukkit.schematic; package com.plotsquared.bukkit.schematic;
import com.destroystokyo.paper.profile.PlayerProfile; import com.google.gson.Gson;
import com.destroystokyo.paper.profile.ProfileProperty; import com.google.gson.GsonBuilder;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.sk89q.jnbt.ByteTag; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.extension.platform.NoCapablePlatformException;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Banner;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Container; import org.bukkit.block.BlockState;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.block.Skull; import org.bukkit.block.sign.Side;
import org.bukkit.block.banner.Pattern; import org.bukkit.block.sign.SignSide;
import org.bukkit.block.banner.PatternType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList; import java.lang.invoke.MethodHandle;
import java.util.HashMap; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Locale;
import java.util.Map.Entry; import java.util.function.Consumer;
import java.util.Objects;
import java.util.UUID;
/**
* This class (attempts to) restore block tile entity data, after the underlying block state has been placed.
* This is used on chunk population (world generation) and in the platforms queue handler (as a fallback for WorldEdit placement).
* <br />
* This class relies heavily on reflective access, native minecraft methods and non-standardized WorldEdit / FAWE methods. It's
* extremely prone to breakage between versions (Minecraft and/or (FA)WE), but supports most if not all possible tile entities.
* Given the previous logic of this class was also non-reliable between version updates, and did only support a small subset of
* tile entities, it's a fair trade-off.
*/
@ApiStatus.Internal
public class StateWrapper { public class StateWrapper {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + StateWrapper.class.getSimpleName());
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final Gson GSON = new GsonBuilder().registerTypeHierarchyAdapter(Tag.class, new NbtGsonSerializer()).create();
private static final String CRAFTBUKKIT_PACKAGE = Bukkit.getServer().getClass().getPackageName();
private static final boolean FORCE_UPDATE_STATE = true;
private static final boolean UPDATE_TRIGGER_PHYSICS = false;
private static final boolean SUPPORTED = PlotSquared.platform().serverVersion()[1] > 20 ||
(PlotSquared.platform().serverVersion()[1] == 20 && PlotSquared.platform().serverVersion()[2] >= 4);
private static final String INITIALIZATION_ERROR_TEMPLATE = """
Failed to initialize StateWrapper: {}
Block-/Tile-Entities, pasted by schematics for example, won't be updated with their respective block data. This affects things like sign text, banner patterns, skulls, etc.
Try updating your Server Software, PlotSquared and WorldEdit / FastAsyncWorldEdit first. If the issue persists, report it on the issue tracker.
""";
private static boolean NOT_SUPPORTED_NOTIFIED = false;
private static boolean FAILED_INITIALIZATION = false;
private static BukkitImplAdapter ADAPTER = null;
private static Class<?> LIN_TAG_CLASS = null;
private static Class<?> JNBT_TAG_CLASS = null;
private static Class<?> CRAFT_BLOCK_ENTITY_STATE_CLASS = null;
private static MethodHandle PAPERWEIGHT_ADAPTER_FROM_NATIVE = null;
private static MethodHandle CRAFT_BLOCK_ENTITY_STATE_LOAD_DATA = null;
private static MethodHandle CRAFT_BLOCK_ENTITY_STATE_UPDATE = null;
private static MethodHandle TO_LIN_TAG = null;
// SIGN HACK
private static boolean PAPER_SIGN_NOTIFIED = false;
private static boolean FAILED_SIGN_INITIALIZATION = false;
private static Object KYORI_GSON_SERIALIZER = null;
private static MethodHandle GSON_SERIALIZER_DESERIALIZE_TREE = null;
private static MethodHandle BUKKIT_SIGN_SIDE_LINE_SET = null;
public CompoundTag tag; public CompoundTag tag;
private boolean paperErrorTextureSent = false;
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + StateWrapper.class.getSimpleName());
public StateWrapper(CompoundTag tag) { public StateWrapper(CompoundTag tag) {
this.tag = tag; this.tag = tag;
} }
public static String jsonToColourCode(String str) {
str = str.replace("{\"extra\":", "").replace("],\"text\":\"\"}", "]")
.replace("[{\"color\":\"black\",\"text\":\"", "&0")
.replace("[{\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("[{\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("[{\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("[{\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("[{\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("[{\"color\":\"gold\",\"text\":\"", "&6")
.replace("[{\"color\":\"gray\",\"text\":\"", "&7")
.replace("[{\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("[{\"color\":\"blue\",\"text\":\"", "&9")
.replace("[{\"color\":\"green\",\"text\":\"", "&a")
.replace("[{\"color\":\"aqua\",\"text\":\"", "&b")
.replace("[{\"color\":\"red\",\"text\":\"", "&c")
.replace("[{\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("[{\"color\":\"yellow\",\"text\":\"", "&e")
.replace("[{\"color\":\"white\",\"text\":\"", "&f")
.replace("[{\"obfuscated\":true,\"text\":\"", "&k")
.replace("[{\"bold\":true,\"text\":\"", "&l")
.replace("[{\"strikethrough\":true,\"text\":\"", "&m")
.replace("[{\"underlined\":true,\"text\":\"", "&n")
.replace("[{\"italic\":true,\"text\":\"", "&o").replace("[{\"color\":\"black\",", "&0")
.replace("[{\"color\":\"dark_blue\",", "&1")
.replace("[{\"color\":\"dark_green\",", "&2")
.replace("[{\"color\":\"dark_aqua\",", "&3").replace("[{\"color\":\"dark_red\",", "&4")
.replace("[{\"color\":\"dark_purple\",", "&5").replace("[{\"color\":\"gold\",", "&6")
.replace("[{\"color\":\"gray\",", "&7").replace("[{\"color\":\"dark_gray\",", "&8")
.replace("[{\"color\":\"blue\",", "&9").replace("[{\"color\":\"green\",", "&a")
.replace("[{\"color\":\"aqua\",", "&b").replace("[{\"color\":\"red\",", "&c")
.replace("[{\"color\":\"light_purple\",", "&d").replace("[{\"color\":\"yellow\",", "&e")
.replace("[{\"color\":\"white\",", "&f").replace("[{\"obfuscated\":true,", "&k")
.replace("[{\"bold\":true,", "&l").replace("[{\"strikethrough\":true,", "&m")
.replace("[{\"underlined\":true,", "&n").replace("[{\"italic\":true,", "&o")
.replace("{\"color\":\"black\",\"text\":\"", "&0")
.replace("{\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("{\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("{\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("{\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("{\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("{\"color\":\"gold\",\"text\":\"", "&6")
.replace("{\"color\":\"gray\",\"text\":\"", "&7")
.replace("{\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("{\"color\":\"blue\",\"text\":\"", "&9")
.replace("{\"color\":\"green\",\"text\":\"", "&a")
.replace("{\"color\":\"aqua\",\"text\":\"", "&b")
.replace("{\"color\":\"red\",\"text\":\"", "&c")
.replace("{\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("{\"color\":\"yellow\",\"text\":\"", "&e")
.replace("{\"color\":\"white\",\"text\":\"", "&f")
.replace("{\"obfuscated\":true,\"text\":\"", "&k")
.replace("{\"bold\":true,\"text\":\"", "&l")
.replace("{\"strikethrough\":true,\"text\":\"", "&m")
.replace("{\"underlined\":true,\"text\":\"", "&n")
.replace("{\"italic\":true,\"text\":\"", "&o").replace("{\"color\":\"black\",", "&0")
.replace("{\"color\":\"dark_blue\",", "&1").replace("{\"color\":\"dark_green\",", "&2")
.replace("{\"color\":\"dark_aqua\",", "&3").replace("{\"color\":\"dark_red\",", "&4")
.replace("{\"color\":\"dark_purple\",", "&5").replace("{\"color\":\"gold\",", "&6")
.replace("{\"color\":\"gray\",", "&7").replace("{\"color\":\"dark_gray\",", "&8")
.replace("{\"color\":\"blue\",", "&9").replace("{\"color\":\"green\",", "&a")
.replace("{\"color\":\"aqua\",", "&b").replace("{\"color\":\"red\",", "&c")
.replace("{\"color\":\"light_purple\",", "&d").replace("{\"color\":\"yellow\",", "&e")
.replace("{\"color\":\"white\",", "&f").replace("{\"obfuscated\":true,", "&k")
.replace("{\"bold\":true,", "&l").replace("{\"strikethrough\":true,", "&m")
.replace("{\"underlined\":true,", "&n").replace("{\"italic\":true,", "&o")
.replace("\"color\":\"black\",\"text\":\"", "&0")
.replace("\"color\":\"dark_blue\",\"text\":\"", "&1")
.replace("\"color\":\"dark_green\",\"text\":\"", "&2")
.replace("\"color\":\"dark_aqua\",\"text\":\"", "&3")
.replace("\"color\":\"dark_red\",\"text\":\"", "&4")
.replace("\"color\":\"dark_purple\",\"text\":\"", "&5")
.replace("\"color\":\"gold\",\"text\":\"", "&6")
.replace("\"color\":\"gray\",\"text\":\"", "&7")
.replace("\"color\":\"dark_gray\",\"text\":\"", "&8")
.replace("\"color\":\"blue\",\"text\":\"", "&9")
.replace("\"color\":\"green\",\"text\":\"", "&a")
.replace("\"color\":\"aqua\",\"text\":\"", "&b")
.replace("\"color\":\"red\",\"text\":\"", "&c")
.replace("\"color\":\"light_purple\",\"text\":\"", "&d")
.replace("\"color\":\"yellow\",\"text\":\"", "&e")
.replace("\"color\":\"white\",\"text\":\"", "&f")
.replace("\"obfuscated\":true,\"text\":\"", "&k")
.replace("\"bold\":true,\"text\":\"", "&l")
.replace("\"strikethrough\":true,\"text\":\"", "&m")
.replace("\"underlined\":true,\"text\":\"", "&n")
.replace("\"italic\":true,\"text\":\"", "&o").replace("\"color\":\"black\",", "&0")
.replace("\"color\":\"dark_blue\",", "&1").replace("\"color\":\"dark_green\",", "&2")
.replace("\"color\":\"dark_aqua\",", "&3").replace("\"color\":\"dark_red\",", "&4")
.replace("\"color\":\"dark_purple\",", "&5").replace("\"color\":\"gold\",", "&6")
.replace("\"color\":\"gray\",", "&7").replace("\"color\":\"dark_gray\",", "&8")
.replace("\"color\":\"blue\",", "&9").replace("\"color\":\"green\",", "&a")
.replace("\"color\":\"aqua\",", "&b").replace("\"color\":\"red\",", "&c")
.replace("\"color\":\"light_purple\",", "&d").replace("\"color\":\"yellow\",", "&e")
.replace("\"color\":\"white\",", "&f").replace("\"obfuscated\":true,", "&k")
.replace("\"bold\":true,", "&l").replace("\"strikethrough\":true,", "&m")
.replace("\"underlined\":true,", "&n").replace("\"italic\":true,", "&o")
.replace("[{\"text\":\"", "&0").replace("{\"text\":\"", "&0").replace("\"},", "")
.replace("\"}]", "").replace("\"}", "");
str = ChatColor.translateAlternateColorCodes('&', str);
return str;
}
/** /**
* Restore the TileEntity data to the given world at the given coordinates. * Restore the TileEntity data to the given world at the given coordinates.
* *
@@ -193,157 +128,264 @@ public class StateWrapper {
* @param block Block to restore to * @param block Block to restore to
* @return true if successful * @return true if successful
*/ */
@SuppressWarnings("deprecation") // #setLine is needed for Spigot compatibility
public boolean restoreTag(@NonNull Block block) { public boolean restoreTag(@NonNull Block block) {
if (this.tag == null) { if (this.tag == null || FAILED_INITIALIZATION) {
return false; return false;
} }
org.bukkit.block.BlockState state = block.getState(); if (!SUPPORTED) {
switch (getId()) { if (!NOT_SUPPORTED_NOTIFIED) {
case "chest", "beacon", "brewingstand", "dispenser", "dropper", "furnace", "hopper", "shulkerbox" -> { NOT_SUPPORTED_NOTIFIED = true;
if (!(state instanceof Container container)) { LOGGER.error(INITIALIZATION_ERROR_TEMPLATE, "Your server version is not supported. 1.20.4 or later is required");
}
return false; return false;
} }
List<Tag> itemsTag = this.tag.getListTag("Items").getValue(); if (ADAPTER == null) {
Inventory inv = container.getSnapshotInventory(); try {
for (Tag itemTag : itemsTag) { findNbtCompoundClassType(clazz -> LIN_TAG_CLASS = clazz, clazz -> JNBT_TAG_CLASS = clazz);
CompoundTag itemComp = (CompoundTag) itemTag; ReflectionUtils.RefClass worldEditPluginRefClass = ReflectionUtils.getRefClass(WorldEditPlugin.class);
ItemType type = ItemType.REGISTRY.get(itemComp.getString("id").toLowerCase()); WorldEditPlugin worldEditPlugin = (WorldEditPlugin) worldEditPluginRefClass
if (type == null) { .getMethod("getInstance")
.of(null)
.call();
ADAPTER = (BukkitImplAdapter) worldEditPluginRefClass
.getMethod("getBukkitImplAdapter")
.of(worldEditPlugin)
.call();
PAPERWEIGHT_ADAPTER_FROM_NATIVE = findPaperweightAdapterFromNativeMethodHandle(
ADAPTER.getClass(), LIN_TAG_CLASS, JNBT_TAG_CLASS
);
TO_LIN_TAG = findToLinTagMethodHandle(LIN_TAG_CLASS);
} catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException | NoCapablePlatformException e) {
LOGGER.error(INITIALIZATION_ERROR_TEMPLATE, "Failed to access required WorldEdit methods", e);
FAILED_INITIALIZATION = true;
return false;
}
try {
CRAFT_BLOCK_ENTITY_STATE_CLASS = Class.forName(CRAFTBUKKIT_PACKAGE + ".block.CraftBlockEntityState");
CRAFT_BLOCK_ENTITY_STATE_LOAD_DATA = findCraftBlockEntityStateLoadDataMethodHandle(CRAFT_BLOCK_ENTITY_STATE_CLASS);
CRAFT_BLOCK_ENTITY_STATE_UPDATE = findCraftBlockEntityStateUpdateMethodHandle(CRAFT_BLOCK_ENTITY_STATE_CLASS);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
LOGGER.error(INITIALIZATION_ERROR_TEMPLATE, "Failed to initialize required native method accessors", e);
FAILED_INITIALIZATION = true;
return false;
}
}
try {
final BlockState blockState = block.getState();
if (!CRAFT_BLOCK_ENTITY_STATE_CLASS.isAssignableFrom(blockState.getClass())) {
return false;
}
// get native tag
Object nativeTag = PAPERWEIGHT_ADAPTER_FROM_NATIVE.invoke(
ADAPTER,
LIN_TAG_CLASS == null ? this.tag : TO_LIN_TAG.invoke(this.tag)
);
CRAFT_BLOCK_ENTITY_STATE_LOAD_DATA.invoke(blockState, nativeTag);
if (blockState instanceof Sign sign) {
Object text;
if ((text = tag.getValue().get("front_text")) != null && text instanceof CompoundTag textTag) {
setSignTextHack(sign, textTag, true);
}
if ((text = tag.getValue().get("back_text")) != null && text instanceof CompoundTag textTag) {
setSignTextHack(sign, textTag, false);
}
}
CRAFT_BLOCK_ENTITY_STATE_UPDATE.invoke(blockState, FORCE_UPDATE_STATE, UPDATE_TRIGGER_PHYSICS);
} catch (Throwable e) {
LOGGER.error("Failed to update tile entity", e);
}
return false;
}
/**
* Set sign content on the bukkit tile entity. The server does not load sign content applied via the main logic
* (CraftBlockEntity#load), as the SignEntity needs to have a valid ServerLevel assigned to it.
* That's not possible on worldgen; therefore, this hack has to be used additionally.
* <br />
* Modern sign content (non-plain-text sign lines) require Paper.
*
* @param sign The sign to apply data onto.
* @param text The compound tag containing the data for the sign side ({@code front_text} / {@code back_text})
* @param front If the compound tag contains the data for the front side.
* @throws Throwable if something went wrong when reflectively updating the sign.
*/
private static void setSignTextHack(Sign sign, CompoundTag text, boolean front) throws Throwable {
final SignSide side = sign.getSide(front ? Side.FRONT : Side.BACK);
if (text.containsKey("color")) {
//noinspection UnstableApiUsage
side.setColor(DyeColor.legacyValueOf(text.getString("color").toUpperCase(Locale.ROOT)));
}
if (text.containsKey("has_glowing_text")) {
side.setGlowingText(text.getByte("has_glowing_text") == 1);
}
List<Tag> lines = text.getList("messages");
if (lines != null) {
for (int i = 0; i < Math.min(lines.size(), 3); i++) {
Tag line = lines.get(i);
if (line instanceof StringTag stringTag) {
//noinspection deprecation - Paper deprecatiom
side.setLine(i, stringTag.getValue());
continue; continue;
} }
int count = itemComp.getByte("Count"); if (line instanceof ListTag || line instanceof CompoundTag) {
int slot = itemComp.getByte("Slot"); if (!initializeSignHack()) {
CompoundTag tag = (CompoundTag) itemComp.getValue().get("tag"); continue;
BaseItemStack baseItemStack = new BaseItemStack(type, tag, count);
ItemStack itemStack = BukkitAdapter.adapt(baseItemStack);
inv.setItem(slot, itemStack);
} }
container.update(true, false); // Minecraft uses mixed lists / arrays in their sign texts. One line can be a complex component, whereas
return true; // the following line could simply be a string. Those simpler lines are represented as `{"": ""}` (only in
// SNBT those will be shown as a standard string). Adventure can't parse those, so we handle these lines as
// plaintext lines (can't contain any other extra data either way).
if (line instanceof CompoundTag compoundTag && compoundTag.getValue().containsKey("")) {
//noinspection deprecation - Paper deprecatiom
side.setLine(i, compoundTag.getString(""));
continue;
} }
case "sign" -> { // serializes the line content from JNBT to Gson JSON objects, passes that to adventure and deserializes
if (state instanceof Sign sign) { // into an adventure component.
sign.setLine(0, jsonToColourCode(tag.getString("Text1"))); BUKKIT_SIGN_SIDE_LINE_SET.invoke(
sign.setLine(1, jsonToColourCode(tag.getString("Text2"))); side, i, GSON_SERIALIZER_DESERIALIZE_TREE.invoke(
sign.setLine(2, jsonToColourCode(tag.getString("Text3"))); KYORI_GSON_SERIALIZER,
sign.setLine(3, jsonToColourCode(tag.getString("Text4"))); GSON.toJsonTree(line.getValue())
state.update(true); )
return true; );
} }
return false;
} }
case "skull" -> {
if (state instanceof Skull skull) {
CompoundTag skullOwner = ((CompoundTag) this.tag.getValue().get("SkullOwner"));
if (skullOwner == null) {
return true;
} }
String player = skullOwner.getString("Name");
if (player != null && !player.isEmpty()) {
try {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(player));
skull.update(true);
} catch (Exception e) {
e.printStackTrace();
}
return true;
} }
final CompoundTag properties = (CompoundTag) skullOwner.getValue().get("Properties"); private static boolean initializeSignHack() {
if (properties == null) { if (FAILED_SIGN_INITIALIZATION) {
return false; return false;
} }
final ListTag textures = properties.getListTag("textures"); if (KYORI_GSON_SERIALIZER != null) {
if (textures.getValue().isEmpty()) { return true; // already initialized
return false;
}
final CompoundTag textureCompound = (CompoundTag) textures.getValue().get(0);
if (textureCompound == null) {
return false;
}
String textureValue = textureCompound.getString("Value");
if (textureValue == null) {
return false;
} }
if (!PaperLib.isPaper()) { if (!PaperLib.isPaper()) {
if (!paperErrorTextureSent) { if (!PAPER_SIGN_NOTIFIED) {
paperErrorTextureSent = true; PAPER_SIGN_NOTIFIED = true;
LOGGER.error("Failed to populate skull data in your road schematic - This is a Spigot limitation."); LOGGER.error("Can't populate non-plain sign line. To load modern sign content, use Paper.");
} }
return false; return false;
} }
final PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID()); try {
profile.setProperty(new ProfileProperty("textures", textureValue)); char[] dontObfuscate = new char[]{
skull.setPlayerProfile(profile); 'n', 'e', 't', '.', 'k', 'y', 'o', 'r', 'i', '.', 'a', 'd', 'v', 'e', 'n', 't', 'u', 'r', 'e', '.',
skull.update(true); 't', 'e', 'x', 't', '.', 's', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'e', 'r', '.', 'g', 's', 'o', 'n', '.',
'G', 's', 'o', 'n', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 'S', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'e', 'r'
};
Class<?> gsonComponentSerializerClass = Class.forName(new String(dontObfuscate));
KYORI_GSON_SERIALIZER = Arrays.stream(gsonComponentSerializerClass.getMethods())
.filter(method -> method.getName().equals("gson"))
.findFirst()
.orElseThrow().invoke(null);
GSON_SERIALIZER_DESERIALIZE_TREE = LOOKUP.unreflect(Arrays
.stream(gsonComponentSerializerClass.getMethods())
.filter(method -> method.getName().equals("deserializeFromTree") && method.getParameterCount() == 1)
.findFirst()
.orElseThrow());
BUKKIT_SIGN_SIDE_LINE_SET = LOOKUP.unreflect(Arrays.stream(SignSide.class.getMethods())
.filter(method -> method.getName().equals("line") && method.getParameterCount() == 2)
.findFirst()
.orElseThrow());
return true; return true;
} catch (Throwable e) {
FAILED_SIGN_INITIALIZATION = true;
LOGGER.error("Failed to initialize sign-hack. Signs populated by schematics might not have their line contents.", e);
return false;
}
}
/**
* Initialize the used NBT tag class. For modern FAWE and WE that'll be Lin - for older ones JNBT.
*
* @throws ClassNotFoundException if neither can be found.
*/
private static void findNbtCompoundClassType(Consumer<Class<?>> linClass, Consumer<Class<?>> jnbtClass) throws
ClassNotFoundException {
try {
linClass.accept(Class.forName("org.enginehub.linbus.tree.LinTag"));
} catch (ClassNotFoundException e) {
jnbtClass.accept(Class.forName("com.sk89q.jnbt.Tag"));
} }
return false;
} }
case "banner" -> {
if (state instanceof Banner banner) { /**
List<Tag> patterns = this.tag.getListTag("Patterns").getValue(); * Finds the {@code toLinTag} method on the {@code ToLinTag} interface, if lin-bus is available in the classpath.
if (patterns == null || patterns.isEmpty()) { * <br />
return false; * Required to access the underlying lin tag of the used JNBT tag by PlotSquared, so it can be converted into the platforms
} * native tag later.
banner.setPatterns(patterns.stream().map(t -> (CompoundTag) t).map(compoundTag -> { *
DyeColor color = DyeColor.getByWoolData((byte) compoundTag.getInt("Color")); * @param linTagClass {@code Tag} class of lin-bus, or {@code null} if not available.
PatternType patternType = PatternType.getByIdentifier(compoundTag.getString("Pattern")); * @return the MethodHandle for {@code toLinTag}, or {@code null} if lin-bus is not available in the classpath.
if (color == null || patternType == null) { * @throws ClassNotFoundException if the {@code ToLinTag} class could not be found.
* @throws NoSuchMethodException if no {@code toLinTag} method exists.
* @throws IllegalAccessException shouldn't happen.
*/
private static MethodHandle findToLinTagMethodHandle(Class<?> linTagClass) throws ClassNotFoundException,
NoSuchMethodException, IllegalAccessException {
if (linTagClass == null) {
return null; return null;
} }
return new Pattern(color, patternType); return LOOKUP.findVirtual(
}).filter(Objects::nonNull).toList()); Class.forName("org.enginehub.linbus.tree.ToLinTag"),
banner.update(true); "toLinTag",
return true; MethodType.methodType(linTagClass)
} );
return false;
}
}
return false;
} }
public String getId() { /**
String tileid = this.tag.getString("id").toLowerCase(); * Find the method (handle) to convert from native (= WE/FAWE) NBT tags to minecraft NBT tags.
if (tileid.startsWith("minecraft:")) { * <br />
tileid = tileid.replace("minecraft:", ""); * Depending on the used version of WE/FAWE, this differs:
* <ul>
* <li>On WE/FAWE version pre LinBus introduction: {@code fromNative(org.sk89q.jnbt.Tag)}</li>
* <li>On WE versions post LinBus introduction: {@code fromNative(org.enginehub.linbus.tree.LinTag)}</li>
* <li>On FAWE versions post LinBus introduction: {@code fromNativeLin(org.enginehub.linbus.tree.LinTag)}</li>
* </ul>
*
* @param adapterClass The bukkit adapter implementation class
* @param linTagClass The lin-bus {@code Tag} class, if existing - otherwise {@code null}
* @param jnbtTagClass The jnbt {@code Tag} class, if lin-bus was not found in classpath - otherwise {@code null}
* @return the method.
* @throws IllegalAccessException shouldn't happen as private lookup is used.
* @throws NoSuchMethodException if the method couldn't be found.
*/
private static MethodHandle findPaperweightAdapterFromNativeMethodHandle(
Class<?> adapterClass, Class<?> linTagClass, Class<?> jnbtTagClass
) throws IllegalAccessException, NoSuchMethodException {
final MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(adapterClass, LOOKUP);
if (jnbtTagClass != null) {
// usage of JNBT = identical method signatures for WE and FAWE
return lookup.findVirtual(adapterClass, "fromNative", MethodType.methodType(Object.class, jnbtTagClass));
}
try {
// FAWE
return lookup.findVirtual(adapterClass, "fromNativeLin", MethodType.methodType(Object.class, linTagClass));
} catch (NoSuchMethodException e) {
// WE
return lookup.findVirtual(adapterClass, "fromNative", MethodType.methodType(Object.class, linTagClass));
} }
return tileid;
} }
public List<CompoundTag> serializeInventory(ItemStack[] items) { private static MethodHandle findCraftBlockEntityStateLoadDataMethodHandle(Class<?> craftBlockEntityStateClass) throws
List<CompoundTag> tags = new ArrayList<>(); NoSuchMethodException, IllegalAccessException, ClassNotFoundException {
for (int i = 0; i < items.length; ++i) { for (final Method method : craftBlockEntityStateClass.getMethods()) {
if (items[i] != null) { if (method.getName().equals("loadData") && method.getParameterCount() == 1) {
Map<String, Tag> tagData = serializeItem(items[i]); return LOOKUP.unreflect(method);
tagData.put("Slot", new ByteTag((byte) i));
tags.add(new CompoundTag(tagData));
} }
} }
return tags; throw new NoSuchMethodException("Couldn't find #loadData(CompoundTag) in " + craftBlockEntityStateClass.getName());
} }
public Map<String, Tag> serializeItem(ItemStack item) { private static MethodHandle findCraftBlockEntityStateUpdateMethodHandle(Class<?> craftBlockEntityStateClass) throws
Map<String, Tag> data = new HashMap<>(); NoSuchMethodException, IllegalAccessException, ClassNotFoundException {
data.put("id", new StringTag(item.getType().name())); for (final Method method : craftBlockEntityStateClass.getMethods()) {
data.put("Damage", new ShortTag(item.getDurability())); if (method.getReturnType().equals(Boolean.TYPE) && method.getParameterCount() == 2 &&
data.put("Count", new ByteTag((byte) item.getAmount())); method.getParameterTypes()[0] == Boolean.TYPE && method.getParameterTypes()[1] == Boolean.TYPE) {
if (!item.getEnchantments().isEmpty()) { return LOOKUP.unreflect(method);
List<CompoundTag> enchantmentList = new ArrayList<>();
for (Entry<Enchantment, Integer> entry : item.getEnchantments().entrySet()) {
Map<String, Tag> enchantment = new HashMap<>();
enchantment.put("id", new StringTag(entry.getKey().toString()));
enchantment.put("lvl", new ShortTag(entry.getValue().shortValue()));
enchantmentList.add(new CompoundTag(enchantment));
} }
Map<String, Tag> auxData = new HashMap<>();
auxData.put("ench", new ListTag(CompoundTag.class, enchantmentList));
data.put("tag", new CompoundTag(auxData));
} }
return data; throw new NoSuchMethodException("Couldn't find method for #update(boolean, boolean) in " + craftBlockEntityStateClass.getName());
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,7 +20,7 @@ plugins {
} }
group = "com.intellectualsites.plotsquared" group = "com.intellectualsites.plotsquared"
version = "7.5.7" version = "7.5.7-SNAPSHOT"
if (!File("$rootDir/.git").exists()) { if (!File("$rootDir/.git").exists()) {
logger.lifecycle(""" logger.lifecycle("""

View File

@@ -3,7 +3,7 @@
paper = "1.20.4-R0.1-SNAPSHOT" paper = "1.20.4-R0.1-SNAPSHOT"
guice = "7.0.0" guice = "7.0.0"
spotbugs = "4.9.4" spotbugs = "4.9.4"
checkerqual = "3.50.0" checkerqual = "3.49.5"
gson = "2.10" gson = "2.10"
guava = "31.1-jre" guava = "31.1-jre"
snakeyaml = "2.0" snakeyaml = "2.0"