refactor: remove legacy .lpschem format (TODO 117)

- Delete schematic/legacy/lpschem/ (LPSchematicLegacy + 5 pojo Gson models)
- Delete schematic/convert/LpschemConverter and /lp schematic convert command
- Remove SchematicClipboardBuilder.fromLegacy, convert branches in dispatcher/
  tab-completer/help, locales (ru/en), SCHEMATICS.md and yml comments
- Kept only .schem (WorldEdit) + .nbt
- Build green: checkstyle 0 errors, PMD 33
This commit is contained in:
loki5512344 2026-08-05 18:58:18 +02:00
parent de47bce56e
commit 9f70e2e586
Signed by: boba
GPG key ID: 253067914055423B
20 changed files with 5 additions and 361 deletions

View file

@ -17,7 +17,7 @@ class CommandTabCompleter {
private static final List<String> SCHEMATIC_DIFFICULTIES = List.of("0.0", "0.25", "0.5", "0.75", "1.0");
private static final List<String> SCHEMATIC_SUBCOMMANDS = List.of(
"wand", "pos1", "pos2", "create", "convert", "paste", "list", "reload"
"wand", "pos1", "pos2", "create", "paste", "list", "reload"
);
private CommandTabCompleter() {

View file

@ -14,7 +14,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* Admin schematic tools: wand, create, convert, list, paste, reload.
* Admin schematic tools: wand, create, list, paste, reload.
*/
public class SchematicCommandHandler {

View file

@ -38,7 +38,6 @@ final class SchematicDispatcher {
LoParkour.getSchematicManager().reload();
SchematicMessenger.send(player, LoParkour.PREFIX + Locales.getString(player, "schematic.reloaded"));
}
case "convert" -> SchematicHandler.convert(sender, player, cooldowns);
default -> SchematicMessenger.sendHelp(player);
}
}

View file

@ -1,9 +1,7 @@
package dev.loki.loparkour.command.schematic;
import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.command.player.PlayerCommandHandler;
import dev.loki.loparkour.config.locale.Locales;
import dev.loki.loparkour.schematic.convert.LpschemConverter;
import dev.loki.loparkour.schematic.core.ParkourSchematic;
import dev.loki.loparkour.schematic.create.SchematicCreator;
import dev.loki.loparkour.util.particle.ParticleUtil;
@ -73,27 +71,6 @@ final class SchematicHandler {
.formatted(name));
}
static void convert(CommandSender sender, Player player, PlayerCommandHandler cooldowns) {
if (!cooldowns.cooldown(sender, "schematic-convert", 5000)) {
return;
}
LpschemConverter.ConvertResult result = LpschemConverter.convertAll();
if (result.converted() > 0) {
LoParkour.getSchematicManager().reload();
}
SchematicMessenger.send(player, LoParkour.PREFIX + Locales.getString(player, "schematic.convert_done")
.formatted(result.converted(), result.failed()));
for (String line : result.messages()) {
if (result.messages().size() <= 12) {
SchematicMessenger.send(player, "&#A0A0A0 " + line);
}
}
if (result.messages().size() > 12) {
SchematicMessenger.send(player, Locales.getString(player, "schematic.convert_truncated")
.formatted(result.messages().size() - 12));
}
}
static void posCommand(Player player, Location[] existing, Location loc, int index) {
SchematicCommandHandler.setPos(player, loc, index);
String label = index == 0 ? "1" : "2";

View file

@ -24,7 +24,6 @@ final class SchematicMessenger {
send(player, Locales.getString(player, "schematic.help.line_pos2"));
send(player, Locales.getString(player, "schematic.help.line_create"));
send(player, Locales.getString(player, "schematic.help.line_create_named"));
send(player, Locales.getString(player, "schematic.help.line_convert"));
send(player, Locales.getString(player, "schematic.help.line_paste"));
send(player, Locales.getString(player, "schematic.help.line_list"));
send(player, Locales.getString(player, "schematic.help.line_reload"));

View file

@ -1,115 +0,0 @@
package dev.loki.loparkour.schematic.convert;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import dev.loki.loparkour.LoParkour;
import dev.loki.loparkour.schematic.config.SchematicDifficultyConfig;
import dev.loki.loparkour.schematic.legacy.lpschem.LPSchematicLegacy;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicMetadata;
import dev.loki.loparkour.schematic.schem.SchematicClipboardBuilder;
import dev.loki.loparkour.schematic.schem.SchemWriter;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Converts legacy {@code .lpschem} files to {@code .schem} in the schematics folder.
*/
public final class LpschemConverter {
private LpschemConverter() {
}
public record ConvertResult(int converted, int failed, @NotNull List<String> messages) {
}
@NotNull
public static ConvertResult convertAll() {
List<File> sources = new ArrayList<>();
collect(LoParkour.getInFolder("schematics"), sources);
collect(LoParkour.getInFolder("schematics-new"), sources);
File outDir = LoParkour.getInFolder("schematics");
if (!outDir.exists()) {
outDir.mkdirs();
}
int ok = 0;
int failed = 0;
List<String> messages = new ArrayList<>();
for (File file : sources) {
try {
String msg = convertFile(file, outDir);
messages.add(msg);
ok++;
} catch (IOException e) {
failed++;
messages.add(file.getName() + ": " + e.getMessage());
LoParkour.getPlugin().getLogger().warning("lpschem convert failed: " + file.getName() + " — " + e.getMessage());
}
}
if (sources.isEmpty()) {
messages.add("No .lpschem files found in schematics/ or schematics-new/");
}
return new ConvertResult(ok, failed, messages);
}
@NotNull
private static String convertFile(@NotNull File lpschemFile, @NotNull File outDir) throws IOException {
LPSchematicLegacy legacy = LPSchematicLegacy.load(lpschemFile);
SchematicMetadata meta = legacy.getMetadata();
String stem = resolveStem(meta, lpschemFile);
File outFile = new File(outDir, stem + ".schem");
double difficulty = meta.getDifficulty() > 0 ? meta.getDifficulty() : 0.5;
boolean wroteFile = false;
if (!outFile.exists()) {
Clipboard clipboard = SchematicClipboardBuilder.fromLegacy(legacy);
SchemWriter.save(clipboard, outFile);
wroteFile = true;
}
SchematicDifficultyConfig.setDifficulty(stem, difficulty);
return wroteFile
? stem + ".schem (" + difficulty + ")"
: stem + " (yaml updated, .schem exists)";
}
@NotNull
private static String resolveStem(@NotNull SchematicMetadata meta, @NotNull File file) {
String name = meta.getName();
if (name != null && !name.isBlank() && name.matches("^[a-zA-Z0-9_-]+$")) {
return name.toLowerCase(Locale.ROOT).startsWith("parkour-")
? name.toLowerCase(Locale.ROOT)
: "parkour-" + name.toLowerCase(Locale.ROOT);
}
String base = file.getName();
if (base.toLowerCase(Locale.ROOT).endsWith(".lpschem")) {
base = base.substring(0, base.length() - 7);
}
if (!base.toLowerCase(Locale.ROOT).startsWith("parkour-")) {
base = "parkour-" + base;
}
return base.toLowerCase(Locale.ROOT);
}
private static void collect(@NotNull File dir, @NotNull List<File> out) {
if (!dir.isDirectory()) {
return;
}
File[] files = dir.listFiles((d, name) -> name.toLowerCase(Locale.ROOT).endsWith(".lpschem"));
if (files != null) {
for (File f : files) {
out.add(f);
}
}
}
}

View file

@ -1,94 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicDimensions;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicLogic;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicMarkers;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicMetadata;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicVisuals;
import java.util.zip.GZIPInputStream;
/**
* Read-only loader for deprecated gzip+JSON {@code .lpschem} files (format v2).
*/
public final class LPSchematicLegacy {
private static final Gson GSON = new GsonBuilder().create();
private static final int FORMAT_VERSION = 2;
private final SchematicMetadata metadata;
private final SchematicDimensions dimensions;
private final List<String> palette;
private final int[] blocks;
private LPSchematicLegacy(
SchematicMetadata metadata,
SchematicDimensions dimensions,
List<String> palette,
int[] blocks
) {
this.metadata = metadata;
this.dimensions = dimensions;
this.palette = palette;
this.blocks = blocks;
}
@NotNull
public static LPSchematicLegacy load(@NotNull File file) throws IOException {
StringBuilder json = new StringBuilder();
try (GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(gzip, java.nio.charset.StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
json.append(line);
}
}
SchematicData data = GSON.fromJson(json.toString(), SchematicData.class);
if (data == null || data.formatVersion != FORMAT_VERSION) {
throw new IOException("Unsupported .lpschem format in " + file.getName());
}
return new LPSchematicLegacy(data.metadata, data.dimensions, data.palette, data.blocks);
}
@NotNull
public SchematicMetadata getMetadata() {
return metadata;
}
@NotNull
public SchematicDimensions getDimensions() {
return dimensions;
}
@NotNull
public List<String> getPalette() {
return palette;
}
@NotNull
public int[] getBlockArray() {
return blocks;
}
private static class SchematicData {
int formatVersion;
SchematicMetadata metadata;
SchematicDimensions dimensions;
List<String> palette;
int[] blocks;
SchematicMarkers markers;
SchematicVisuals visuals;
SchematicLogic logic;
}
}

View file

@ -1,9 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem.pojo;
/** Gson POJO for legacy {@code .lpschem}. */
public class SchematicDimensions {
public int width;
public int height;
public int length;
}

View file

@ -1,5 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem.pojo;
/** Gson POJO for legacy {@code .lpschem} (optional section). */
public class SchematicLogic {
}

View file

@ -1,17 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem.pojo;
import java.util.List;
/** Gson POJO for legacy {@code .lpschem}. */
public class SchematicMarkers {
public Vector3i start;
public Vector3i end;
public List<Vector3i> checkpoints;
public static class Vector3i {
public int x;
public int y;
public int z;
}
}

View file

@ -1,21 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem.pojo;
/** Gson POJO for legacy {@code .lpschem}. */
public class SchematicMetadata {
private String name;
private String author;
private double difficulty;
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public double getDifficulty() {
return difficulty;
}
}

View file

@ -1,5 +0,0 @@
package dev.loki.loparkour.schematic.legacy.lpschem.pojo;
/** Gson POJO for legacy {@code .lpschem} (optional section). */
public class SchematicVisuals {
}

View file

@ -6,16 +6,12 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockState;
import dev.loki.loparkour.schematic.legacy.lpschem.LPSchematicLegacy;
import dev.loki.loparkour.schematic.legacy.lpschem.pojo.SchematicDimensions;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public final class SchematicClipboardBuilder {
private SchematicClipboardBuilder() {
@ -60,45 +56,4 @@ public final class SchematicClipboardBuilder {
}
return clipboard;
}
@NotNull
public static Clipboard fromLegacy(@NotNull LPSchematicLegacy legacy) {
SchematicDimensions dim = legacy.getDimensions();
BlockVector3 min = BlockVector3.at(0, 0, 0);
BlockVector3 max = BlockVector3.at(dim.width - 1, dim.height - 1, dim.length - 1);
CuboidRegion region = new CuboidRegion(min, max);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
List<String> palette = legacy.getPalette();
int[] blocks = legacy.getBlockArray();
int width = dim.width;
int length = dim.length;
for (int y = 0; y < dim.height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
int index = x + (z * width) + (y * width * length);
int paletteIndex = blocks[index];
if (paletteIndex <= 0 || paletteIndex >= palette.size()) {
continue;
}
String blockData = palette.get(paletteIndex);
if (blockData == null || blockData.isBlank()) {
continue;
}
try {
BlockData data = org.bukkit.Bukkit.createBlockData(blockData);
BlockState state = BukkitAdapter.adapt(data);
if (state.getBlockType().getMaterial().isAir()) {
continue;
}
clipboard.setBlock(BlockVector3.at(x, y, z), state);
} catch (IllegalArgumentException ignored) {
// Skip invalid states
}
}
}
}
return clipboard;
}
}