266 lines
12 KiB
Java
266 lines
12 KiB
Java
/*
|
|
* 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.command;
|
|
|
|
import com.google.inject.Inject;
|
|
import com.plotsquared.core.PlotSquared;
|
|
import com.plotsquared.core.configuration.caption.StaticCaption;
|
|
import com.plotsquared.core.configuration.caption.TranslatableCaption;
|
|
import com.plotsquared.core.configuration.file.YamlConfiguration;
|
|
import com.plotsquared.core.database.DBFunc;
|
|
import com.plotsquared.core.database.Database;
|
|
import com.plotsquared.core.database.MySQL;
|
|
import com.plotsquared.core.database.SQLManager;
|
|
import com.plotsquared.core.database.SQLite;
|
|
import com.plotsquared.core.inject.annotations.WorldConfig;
|
|
import com.plotsquared.core.listener.PlotListener;
|
|
import com.plotsquared.core.player.PlotPlayer;
|
|
import com.plotsquared.core.plot.Plot;
|
|
import com.plotsquared.core.plot.PlotArea;
|
|
import com.plotsquared.core.plot.PlotId;
|
|
import com.plotsquared.core.plot.world.PlotAreaManager;
|
|
import com.plotsquared.core.plot.world.SinglePlotArea;
|
|
import com.plotsquared.core.util.EventDispatcher;
|
|
import com.plotsquared.core.util.FileUtils;
|
|
import com.plotsquared.core.util.query.PlotQuery;
|
|
import com.plotsquared.core.util.task.TaskManager;
|
|
import net.kyori.adventure.text.minimessage.Template;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
|
|
import java.io.File;
|
|
import java.sql.SQLException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map.Entry;
|
|
|
|
@CommandDeclaration(command = "database",
|
|
aliases = {"convert"},
|
|
category = CommandCategory.ADMINISTRATION,
|
|
permission = "plots.database",
|
|
requiredType = RequiredType.CONSOLE,
|
|
usage = "/plot database [area] <sqlite | mysql | import>")
|
|
public class DatabaseCommand extends SubCommand {
|
|
|
|
private final PlotAreaManager plotAreaManager;
|
|
private final EventDispatcher eventDispatcher;
|
|
private final PlotListener plotListener;
|
|
private final YamlConfiguration worldConfiguration;
|
|
|
|
@Inject
|
|
public DatabaseCommand(
|
|
final @NonNull PlotAreaManager plotAreaManager,
|
|
final @NonNull EventDispatcher eventDispatcher,
|
|
final @NonNull PlotListener plotListener,
|
|
@WorldConfig final @NonNull YamlConfiguration worldConfiguration
|
|
) {
|
|
this.plotAreaManager = plotAreaManager;
|
|
this.eventDispatcher = eventDispatcher;
|
|
this.plotListener = plotListener;
|
|
this.worldConfiguration = worldConfiguration;
|
|
}
|
|
|
|
public static void insertPlots(
|
|
final SQLManager manager, final List<Plot> plots,
|
|
final PlotPlayer<?> player
|
|
) {
|
|
TaskManager.runTaskAsync(() -> {
|
|
try {
|
|
ArrayList<Plot> ps = new ArrayList<>(plots);
|
|
player.sendMessage(TranslatableCaption.of("database.starting_conversion"));
|
|
manager.createPlotsAndData(ps, () -> {
|
|
player.sendMessage(TranslatableCaption.of("database.conversion_done"));
|
|
manager.close();
|
|
});
|
|
} catch (Exception e) {
|
|
player.sendMessage(TranslatableCaption.of("database.conversion_failed"));
|
|
e.printStackTrace();
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public boolean onCommand(final PlotPlayer<?> player, String[] args) {
|
|
if (args.length < 1) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "/plot database [area] <sqlite | mysql | import>")
|
|
);
|
|
return false;
|
|
}
|
|
List<Plot> plots;
|
|
PlotArea area = this.plotAreaManager.getPlotAreaByString(args[0]);
|
|
if (area != null) {
|
|
plots = PlotSquared.get().sortPlotsByTemp(area.getPlots());
|
|
args = Arrays.copyOfRange(args, 1, args.length);
|
|
} else {
|
|
plots = PlotSquared.get().sortPlotsByTemp(PlotQuery.newQuery().allPlots().asList());
|
|
}
|
|
if (args.length < 1) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "/plot database [area] <sqlite|mysql|import>")
|
|
);
|
|
player.sendMessage(TranslatableCaption.of("database.arg"));
|
|
return false;
|
|
}
|
|
try {
|
|
Database implementation;
|
|
String prefix = "";
|
|
switch (args[0].toLowerCase()) {
|
|
case "import" -> {
|
|
if (args.length < 2) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "/plot database import <sqlite file> [prefix]")
|
|
);
|
|
return false;
|
|
}
|
|
File file = FileUtils.getFile(
|
|
PlotSquared.platform().getDirectory(),
|
|
args[1].endsWith(".db") ? args[1] : args[1] + ".db"
|
|
);
|
|
if (!file.exists()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("database.does_not_exist"),
|
|
Template.of("value", String.valueOf(file))
|
|
);
|
|
return false;
|
|
}
|
|
player.sendMessage(TranslatableCaption.of("database.starting_conversion"));
|
|
implementation = new SQLite(file);
|
|
SQLManager manager = new SQLManager(implementation, args.length == 3 ? args[2] : "",
|
|
this.eventDispatcher, this.plotListener, this.worldConfiguration
|
|
);
|
|
HashMap<String, HashMap<PlotId, Plot>> map = manager.getPlots();
|
|
plots = new ArrayList<>();
|
|
for (Entry<String, HashMap<PlotId, Plot>> entry : map.entrySet()) {
|
|
String areaName = entry.getKey();
|
|
PlotArea pa = this.plotAreaManager.getPlotAreaByString(areaName);
|
|
if (pa != null) {
|
|
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
|
|
Plot plot = entry2.getValue();
|
|
if (pa.getOwnedPlotAbs(plot.getId()) != null) {
|
|
if (pa instanceof SinglePlotArea) {
|
|
Plot newPlot = pa.getNextFreePlot(null, plot.getId());
|
|
if (newPlot != null) {
|
|
PlotId newId = newPlot.getId();
|
|
PlotId id = plot.getId();
|
|
File worldFile =
|
|
new File(
|
|
PlotSquared.platform().worldContainer(),
|
|
id.toCommaSeparatedString()
|
|
);
|
|
if (worldFile.exists()) {
|
|
File newFile =
|
|
new File(
|
|
PlotSquared.platform().worldContainer(),
|
|
newId.toCommaSeparatedString()
|
|
);
|
|
worldFile.renameTo(newFile);
|
|
}
|
|
plot.setId(newId);
|
|
plot.setArea(pa);
|
|
plots.add(plot);
|
|
continue;
|
|
}
|
|
}
|
|
player.sendMessage(
|
|
TranslatableCaption.of("database.skipping_duplicated_plot"),
|
|
Template.of("plot", String.valueOf(plot)),
|
|
Template.of("id", String.valueOf(plot.temp))
|
|
);
|
|
continue;
|
|
}
|
|
plot.setArea(pa);
|
|
plots.add(plot);
|
|
}
|
|
} else {
|
|
HashMap<PlotId, Plot> plotMap = PlotSquared.get().plots_tmp
|
|
.computeIfAbsent(areaName, k -> new HashMap<>());
|
|
plotMap.putAll(entry.getValue());
|
|
}
|
|
}
|
|
DBFunc.createPlotsAndData(
|
|
plots,
|
|
() -> player.sendMessage(TranslatableCaption.of("database.conversion_done"))
|
|
);
|
|
return true;
|
|
}
|
|
case "mysql" -> {
|
|
if (args.length < 6) {
|
|
player.sendMessage(StaticCaption.of(
|
|
"/plot database mysql [host] [port] [username] [password] [database] {prefix}"));
|
|
return false;
|
|
}
|
|
String host = args[1];
|
|
String port = args[2];
|
|
String username = args[3];
|
|
String password = args[4];
|
|
String database = args[5];
|
|
if (args.length > 6) {
|
|
prefix = args[6];
|
|
}
|
|
implementation = new MySQL(host, port, database, username, password);
|
|
}
|
|
case "sqlite" -> {
|
|
if (args.length < 2) {
|
|
player.sendMessage(StaticCaption.of("/plot database sqlite [file]"));
|
|
return false;
|
|
}
|
|
File sqliteFile =
|
|
FileUtils.getFile(PlotSquared.platform().getDirectory(), args[1] + ".db");
|
|
implementation = new SQLite(sqliteFile);
|
|
}
|
|
default -> {
|
|
player.sendMessage(StaticCaption.of("/plot database [sqlite/mysql]"));
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
SQLManager manager = new SQLManager(
|
|
implementation,
|
|
prefix,
|
|
this.eventDispatcher,
|
|
this.plotListener,
|
|
this.worldConfiguration
|
|
);
|
|
DatabaseCommand.insertPlots(manager, plots, player);
|
|
return true;
|
|
} catch (ClassNotFoundException | SQLException e) {
|
|
player.sendMessage(TranslatableCaption.of("database.failed_to_save_plots"));
|
|
player.sendMessage(TranslatableCaption.of("errors.stacktrace_begin"));
|
|
e.printStackTrace();
|
|
player.sendMessage(TranslatableCaption.of("errors.stacktrace_end"));
|
|
player.sendMessage(TranslatableCaption.of("database.invalid_args"));
|
|
return false;
|
|
}
|
|
} catch (ClassNotFoundException | SQLException e) {
|
|
player.sendMessage(TranslatableCaption.of("database.failed_to_open"));
|
|
player.sendMessage(TranslatableCaption.of("errors.stacktrace_begin"));
|
|
e.printStackTrace();
|
|
player.sendMessage(TranslatableCaption.of("errors.stacktrace_end"));
|
|
player.sendMessage(TranslatableCaption.of("database.invalid_args"));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|