Compare commits

..

2 Commits

Author SHA1 Message Date
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
10 changed files with 299 additions and 271 deletions

View File

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

View File

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

View File

@@ -21,6 +21,7 @@ package com.plotsquared.bukkit.schematic;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.PlotSquared;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
@@ -36,6 +37,8 @@ import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.World;
import org.bukkit.block.Banner;
import org.bukkit.block.Block;
@@ -44,25 +47,35 @@ import org.bukkit.block.Sign;
import org.bukkit.block.Skull;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.block.sign.Side;
import org.bukkit.block.sign.SignSide;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;
// TODO: somehow unbreak this class so it doesn't fuck up the whole schematic population system due to MC updates
@ApiStatus.Internal
public class StateWrapper {
public CompoundTag tag;
private boolean paperErrorTextureSent = false;
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + StateWrapper.class.getSimpleName());
private static final boolean MODERN_SIGNS = PlotSquared.platform().serverVersion()[1] > 19;
private final Registry<PatternType> PATTERN_TYPE_REGISTRY = Objects.requireNonNull(Bukkit.getRegistry(PatternType.class));
private static boolean paperErrorTextureSent = false;
public CompoundTag tag;
public StateWrapper(CompoundTag tag) {
this.tag = tag;
@@ -212,9 +225,9 @@ public class StateWrapper {
if (type == null) {
continue;
}
int count = itemComp.getByte("Count");
int count = itemComp.containsKey("count") ? itemComp.getInt("count") : itemComp.getByte("Count");
int slot = itemComp.getByte("Slot");
CompoundTag tag = (CompoundTag) itemComp.getValue().get("tag");
CompoundTag tag = (CompoundTag) itemComp.getValue().get(itemComp.containsKey("tag") ? "tag" : "components");
BaseItemStack baseItemStack = new BaseItemStack(type, tag, count);
ItemStack itemStack = BukkitAdapter.adapt(baseItemStack);
inv.setItem(slot, itemStack);
@@ -223,82 +236,62 @@ public class StateWrapper {
return true;
}
case "sign" -> {
if (state instanceof Sign sign) {
sign.setLine(0, jsonToColourCode(tag.getString("Text1")));
sign.setLine(1, jsonToColourCode(tag.getString("Text2")));
sign.setLine(2, jsonToColourCode(tag.getString("Text3")));
sign.setLine(3, jsonToColourCode(tag.getString("Text4")));
state.update(true);
if (state instanceof Sign sign && this.restoreSign(sign)) {
state.update(true, false);
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");
if (properties == null) {
return false;
}
final ListTag textures = properties.getListTag("textures");
if (textures.getValue().isEmpty()) {
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 (!paperErrorTextureSent) {
paperErrorTextureSent = true;
LOGGER.error("Failed to populate skull data in your road schematic - This is a Spigot limitation.");
}
return false;
}
final PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID());
profile.setProperty(new ProfileProperty("textures", textureValue));
skull.setPlayerProfile(profile);
skull.update(true);
if (state instanceof Skull skull && this.restoreSkull(skull)) {
skull.update(true, false);
return true;
}
return false;
}
case "banner" -> {
if (state instanceof Banner banner) {
List<Tag> patterns = this.tag.getListTag("Patterns").getValue();
if (patterns == null || patterns.isEmpty()) {
return false;
List<CompoundTag> patterns;
// "old" format
if ((patterns = this.tag.getList("Patterns", CompoundTag.class)) != null && !patterns.isEmpty()) {
banner.setPatterns(patterns.stream().map(compoundTag -> {
DyeColor color = DyeColor.getByWoolData((byte) compoundTag.getInt("Color"));
final PatternType patternType = PATTERN_TYPE_REGISTRY.get(Objects.requireNonNull(
NamespacedKey.fromString(compoundTag.getString("Pattern"))
));
if (color == null || patternType == null) {
return null;
}
return new Pattern(color, patternType);
}).filter(Objects::nonNull).toList());
banner.update(true, false);
return true;
}
banner.setPatterns(patterns.stream().map(t -> (CompoundTag) t).map(compoundTag -> {
DyeColor color = DyeColor.getByWoolData((byte) compoundTag.getInt("Color"));
PatternType patternType = PatternType.getByIdentifier(compoundTag.getString("Pattern"));
if (color == null || patternType == null) {
return null;
// "new" format - since 1.21.3-ish
if ((patterns = this.tag.getList("patterns", CompoundTag.class)) != null && !patterns.isEmpty()) {
for (final CompoundTag patternTag : patterns) {
final String color = patternTag.getString("color");
if (color.isEmpty()) {
continue;
}
final Tag pattern = patternTag.getValue().get("pattern");
if (pattern instanceof StringTag patternString && !patternString.getValue().isEmpty()) {
final PatternType patternType = PATTERN_TYPE_REGISTRY.get(Objects.requireNonNull(
NamespacedKey.fromString(patternString.getValue())
));
if (patternType == null) {
continue;
}
banner.addPattern(new Pattern(
DyeColor.legacyValueOf(color.toUpperCase(Locale.ROOT)),
patternType
));
}
// not supporting banner pattern definitions (no API available)
}
return new Pattern(color, patternType);
}).filter(Objects::nonNull).toList());
banner.update(true);
return true;
banner.update(true, false);
}
}
return false;
}
@@ -346,4 +339,150 @@ public class StateWrapper {
return data;
}
private boolean restoreSkull(Skull skull) {
boolean updated = false;
// can't support custom_name - Spigot does not provide any API for that
if (this.tag.containsKey("note_block_sound")) {
skull.setNoteBlockSound(NamespacedKey.fromString(this.tag.getString("note_block_sound")));
updated = true;
}
// modern format - MC 1.21.3-ish
if (this.tag.containsKey("profile")) {
final Tag profile = this.tag.getValue().get("profile");
if (profile instanceof StringTag stringTag) {
final String name = stringTag.getValue();
if (name != null && !name.isEmpty()) {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(name));
return true;
}
return updated;
}
if (profile instanceof CompoundTag compoundTag) {
final List<Tag> properties = compoundTag.getList("properties");
if (properties != null && !properties.isEmpty()) {
if (!PaperLib.isPaper()) {
if (!paperErrorTextureSent) {
paperErrorTextureSent = true;
LOGGER.error("Failed to populate schematic skull data - this is a Spigot limitation.");
}
return updated;
}
for (final Tag propertyTag : properties) {
if (!(propertyTag instanceof CompoundTag property)) {
continue;
}
if (!property.getString("name").equals("textures")) {
continue;
}
final String value = property.getString("value");
final String signature = property.containsKey("signature") ? property.getString("signature") : null;
final PlayerProfile playerProfile = Bukkit.createProfile(UUID.randomUUID());
playerProfile.setProperty(new ProfileProperty("textures", value, signature));
skull.setPlayerProfile(playerProfile);
return true;
}
return updated;
}
final int[] id = compoundTag.getIntArray("id");
if (id != null && id.length == 4) {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(new UUID(
(long) id[0] << 32 | (id[1] & 0xFFFFFFFFL),
(long) id[2] << 32 | (id[3] & 0xFFFFFFFFL)
)));
return true;
}
final String name = compoundTag.getString("name");
if (name != null && !name.isEmpty()) {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(name));
return true;
}
}
}
// "Old" MC format (idk when it got updated)
if (this.tag.getValue().get("SkullOwner") instanceof CompoundTag skullOwner) {
if (skullOwner.getValue().get("Name") instanceof StringTag ownerName && !ownerName.getValue().isEmpty()) {
skull.setOwningPlayer(Bukkit.getOfflinePlayer(ownerName.getValue()));
skull.update(true);
return true;
}
if (skullOwner.getValue().get("Properties") instanceof CompoundTag properties) {
if (!paperErrorTextureSent) {
paperErrorTextureSent = true;
LOGGER.error("Failed to populate schematic skull data - this is a Spigot limitation.");
return updated;
}
final List<CompoundTag> textures = properties.getList("textures", CompoundTag.class);
if (textures.isEmpty()) {
return updated;
}
final String value = textures.get(0).getString("Value");
if (!value.isEmpty()) {
final PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID());
profile.setProperty(new ProfileProperty("textures", value));
skull.setPlayerProfile(profile);
return true;
}
}
}
return updated;
}
private boolean restoreSign(Sign sign) {
// "old" format (pre 1.20)
if (this.tag.containsKey("Text1") || this.tag.containsKey("Text2")
|| this.tag.containsKey("Text3") || this.tag.containsKey("Text4")) {
if (!MODERN_SIGNS) {
sign.setLine(0, jsonToColourCode(tag.getString("Text1")));
sign.setLine(1, jsonToColourCode(tag.getString("Text2")));
sign.setLine(2, jsonToColourCode(tag.getString("Text3")));
sign.setLine(3, jsonToColourCode(tag.getString("Text4")));
sign.setGlowingText(tag.getByte("GlowingText") == 1);
if (tag.getValue().get("Color") instanceof StringTag colorTag && !colorTag.getValue().isEmpty()) {
sign.setColor(DyeColor.legacyValueOf(colorTag.getValue()));
}
return true;
}
SignSide front = sign.getSide(Side.FRONT);
front.setLine(0, jsonToColourCode(tag.getString("Text1")));
front.setLine(1, jsonToColourCode(tag.getString("Text2")));
front.setLine(2, jsonToColourCode(tag.getString("Text3")));
front.setLine(3, jsonToColourCode(tag.getString("Text4")));
front.setGlowingText(tag.getByte("GlowingText") == 1);
if (tag.getValue().get("Color") instanceof StringTag colorTag && !colorTag.getValue().isEmpty()) {
front.setColor(DyeColor.legacyValueOf(colorTag.getValue()));
}
return true;
}
// "modern" format
if (this.tag.containsKey("front_text") || this.tag.containsKey("back_text") || this.tag.containsKey("is_waxed")) {
// the new format on older servers shouldn't be possible, I hope?
sign.setWaxed(this.tag.getByte("is_waxed") == 1);
BiConsumer<SignSide, CompoundTag> sideSetter = (signSide, compoundTag) -> {
signSide.setGlowingText(compoundTag.getByte("has_glowing_text") == 1);
if (tag.getValue().get("color") instanceof StringTag colorTag && !colorTag.getValue().isEmpty()) {
signSide.setColor(DyeColor.legacyValueOf(colorTag.getValue()));
}
final List<Tag> lines = compoundTag.getList("messages");
for (int i = 0; i < Math.min(lines.size(), 4); i++) {
final Tag line = lines.get(i);
if (line instanceof StringTag stringLine) {
signSide.setLine(i, jsonToColourCode(stringLine.getValue()));
continue;
}
// TODO: how tf support list of components + components - utilize paper + adventure?
}
};
if (this.tag.getValue().get("front_text") instanceof CompoundTag frontText) {
sideSetter.accept(sign.getSide(Side.FRONT), frontText);
}
if (this.tag.getValue().get("back_text") instanceof CompoundTag backText) {
sideSetter.accept(sign.getSide(Side.BACK), backText);
}
return true;
}
return false;
}
}

View File

@@ -18,8 +18,6 @@
*/
package com.plotsquared.core.backup;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.IOException;
@@ -32,14 +30,12 @@ import java.nio.file.Path;
*/
public class Backup {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Backup.class.getSimpleName());
private final BackupProfile owner;
private final long creationTime;
@Nullable
private final Path file;
Backup(final BackupProfile owner, final long creationTime, @Nullable final Path file) {
Backup(final BackupProfile owner, final long creationTime, final Path file) {
this.owner = owner;
this.creationTime = creationTime;
this.file = file;
@@ -53,7 +49,7 @@ public class Backup {
try {
Files.deleteIfExists(file);
} catch (final IOException e) {
LOGGER.error("Error deleting back 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.assistedinject.Assisted;
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.plot.Plot;
import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.task.RunnableVal;
import com.plotsquared.core.util.task.TaskManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -52,7 +51,7 @@ import java.util.concurrent.CompletableFuture;
*/
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 Plot plot;
@@ -88,7 +87,7 @@ public class PlayerBackupProfile implements BackupProfile {
Files.createDirectory(path);
}
} catch (final Exception e) {
LOGGER.error("Error resolving {} from {}", child, parent, e);
e.printStackTrace();
}
return path;
}
@@ -105,7 +104,7 @@ public class PlayerBackupProfile implements BackupProfile {
try {
Files.createDirectories(path);
} catch (IOException e) {
LOGGER.error("Error creating directory {}", path, e);
e.printStackTrace();
return Collections.emptyList();
}
}
@@ -118,11 +117,11 @@ public class PlayerBackupProfile implements BackupProfile {
backups.add(
new Backup(this, basicFileAttributes.creationTime().toMillis(), file));
} catch (IOException e) {
LOGGER.error("Error getting attributes for file {} to create backup", file, e);
e.printStackTrace();
}
});
} catch (IOException e) {
LOGGER.error("Error walking files from {}", path, e);
e.printStackTrace();
}
backups.sort(Comparator.comparingLong(Backup::getCreationTime).reversed());
return (this.backupCache = backups);
@@ -134,7 +133,7 @@ public class PlayerBackupProfile implements BackupProfile {
public void destroy() {
this.listBackups().whenCompleteAsync((backups, error) -> {
if (error != null) {
LOGGER.error("Error while listing backups", error);
error.printStackTrace();
}
backups.forEach(Backup::delete);
this.backupCache = null;
@@ -142,12 +141,10 @@ public class PlayerBackupProfile implements BackupProfile {
}
public @NonNull Path getBackupDirectory() {
return resolve(
resolve(
resolve(backupManager.getBackupPath(), Objects.requireNonNull(plot.getArea().toString(), "plot area id")),
Objects.requireNonNull(plot.getId().toDashSeparatedString(), "plot id")
), Objects.requireNonNull(owner.toString(), "owner")
);
return resolve(resolve(
resolve(backupManager.getBackupPath(), Objects.requireNonNull(plot.getArea().toString(), "plot area id")),
Objects.requireNonNull(plot.getId().toDashSeparatedString(), "plot id")
), Objects.requireNonNull(owner.toString(), "owner"));
}
@Override
@@ -159,8 +156,7 @@ public class PlayerBackupProfile implements BackupProfile {
backups.get(backups.size() - 1).delete();
}
final List<Plot> plots = Collections.singletonList(plot);
final boolean result = this.schematicHandler.exportAll(
plots, getBackupDirectory().toFile(),
final boolean result = this.schematicHandler.exportAll(plots, getBackupDirectory().toFile(),
"%world%-%id%-" + System.currentTimeMillis(), () ->
future.complete(new Backup(this, System.currentTimeMillis(), null))
);
@@ -184,7 +180,7 @@ public class PlayerBackupProfile implements BackupProfile {
try {
schematic = this.schematicHandler.getSchematic(backup.getFile().toFile());
} catch (SchematicHandler.UnsupportedFormatException e) {
LOGGER.error("Unsupported format for backup {}", backup.getFile(), e);
e.printStackTrace();
}
if (schematic == null) {
future.completeExceptionally(new IllegalArgumentException(
@@ -204,9 +200,10 @@ public class PlayerBackupProfile implements BackupProfile {
if (value) {
future.complete(null);
} else {
future.completeExceptionally(new PlotSquaredException(
future.completeExceptionally(new RuntimeException(MINI_MESSAGE.escapeTags(
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.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -49,7 +47,6 @@ import java.util.concurrent.TimeUnit;
@Singleton
public class SimpleBackupManager implements BackupManager {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + SimpleBackupManager.class.getSimpleName());
private final Path backupPath;
private final boolean automaticBackup;
private final int backupLimit;
@@ -115,12 +112,7 @@ public class SimpleBackupManager implements BackupManager {
TagResolver.resolver("reason", Tag.inserting(Component.text(throwable.getMessage())))
);
}
LOGGER.error(
"Error creating backup for plot {};{} and player {}",
plot.getArea(),
plot.getId(),
player == null ? "null" : player.getName(), throwable
);
throwable.printStackTrace();
} else {
if (player != null) {
player.sendMessage(TranslatableCaption.of("backups.backup_automatic_finished"));
@@ -136,7 +128,6 @@ public class SimpleBackupManager implements BackupManager {
return this.automaticBackup;
}
@NonNull
public Path getBackupPath() {
return this.backupPath;
}

View File

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

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 TODO
*/
public final class PlotSquaredException extends RuntimeException {
private final Caption caption;
/**
* Create a new instance with the given caption
*
* @param caption caption
*/
public PlotSquaredException(Caption caption) {
this.caption = caption;
}
/**
* Create a new instance with the given caption and cause
*
* @param caption caption
* @param cause cause
*/
public PlotSquaredException(Caption caption, Exception cause) {
super(cause);
this.caption = caption;
}
@Override
public String getMessage() {
return caption.getComponent(LocaleHolder.console());
}
public Caption getCaption() {
return caption;
}
}

View File

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