Minepacks/Minepacks/src/at/pcgamingfreaks/Minepacks/Bukkit/Database/Database.java

297 lines
9.4 KiB
Java
Raw Normal View History

2014-08-02 18:06:45 +02:00
/*
2023-06-02 21:17:11 +02:00
* Copyright (C) 2023 GeorgH93
2014-08-02 18:06:45 +02:00
*
* 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
2023-06-15 20:07:38 +02:00
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2014-08-02 18:06:45 +02:00
*/
2016-12-19 22:06:08 +01:00
package at.pcgamingfreaks.Minepacks.Bukkit.Database;
2014-08-02 18:06:45 +02:00
import at.pcgamingfreaks.ConsoleColor;
import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider;
2016-12-19 22:06:08 +01:00
import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback;
import at.pcgamingfreaks.Minepacks.Bukkit.Backpack;
import at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies.OnDisconnect;
2023-06-03 21:22:23 +02:00
import at.pcgamingfreaks.Minepacks.Bukkit.Database.UnCacheStrategies.UnCacheStrategy;
2016-12-19 22:06:08 +01:00
import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks;
2014-08-02 18:06:45 +02:00
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
2016-12-19 22:06:08 +01:00
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
2018-07-25 18:49:54 +02:00
import org.bukkit.inventory.ItemStack;
2016-12-19 22:06:08 +01:00
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
2018-06-07 23:43:33 +02:00
import java.io.File;
import java.io.FileOutputStream;
2018-12-21 18:06:59 +01:00
import java.util.ArrayList;
2016-12-19 22:06:08 +01:00
import java.util.Collection;
import java.util.Locale;
2016-12-19 22:06:08 +01:00
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class Database implements Listener
2014-08-02 18:06:45 +02:00
{
2016-11-06 18:09:23 +01:00
protected static final String START_UUID_UPDATE = "Start updating database to UUIDs ...", UUIDS_UPDATED = "Updated %d accounts to UUIDs.";
public static final String MESSAGE_UNKNOWN_DB_TYPE = ConsoleColor.RED + "Unknown database type \"%s\"!" + ConsoleColor.RESET;
2016-12-19 22:06:08 +01:00
protected final Minepacks plugin;
2018-08-10 18:05:58 +02:00
protected final InventorySerializer itsSerializer;
2023-06-02 21:17:11 +02:00
protected final boolean onlineUUIDs, bungeeCordMode, forceSaveOnUnload;
protected boolean useUUIDSeparators, asyncSave = true;
2015-06-08 01:07:33 +02:00
protected long maxAge;
2016-12-19 22:06:08 +01:00
private final Map<OfflinePlayer, Backpack> backpacks = new ConcurrentHashMap<>();
2023-06-03 21:22:23 +02:00
private final UnCacheStrategy unCacheStrategie;
2018-06-07 23:43:33 +02:00
private final File backupFolder;
2016-11-23 21:06:45 +01:00
public Database(Minepacks mp)
2014-08-02 18:06:45 +02:00
{
plugin = mp;
2018-08-10 18:05:58 +02:00
itsSerializer = new InventorySerializer(plugin.getLogger());
useUUIDSeparators = plugin.getConfiguration().getUseUUIDSeparators();
2020-01-07 21:27:27 +01:00
onlineUUIDs = plugin.getConfiguration().useOnlineUUIDs();
bungeeCordMode = plugin.getConfiguration().isBungeeCordModeEnabled();
2023-06-02 21:17:11 +02:00
forceSaveOnUnload = plugin.getConfiguration().isForceSaveOnUnloadEnabled();
maxAge = plugin.getConfiguration().getAutoCleanupMaxInactiveDays();
2023-06-03 21:22:23 +02:00
unCacheStrategie = bungeeCordMode ? new OnDisconnect(this) : UnCacheStrategy.getUnCacheStrategie(this);
2018-06-07 23:43:33 +02:00
backupFolder = new File(this.plugin.getDataFolder(), "backups");
if(!backupFolder.exists() && !backupFolder.mkdirs()) mp.getLogger().info("Failed to create backups folder.");
2016-12-19 22:06:08 +01:00
}
public void init()
{
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public void close()
{
HandlerList.unregisterAll(this);
asyncSave = false;
2018-06-04 13:14:15 +02:00
backpacks.forEach((key, value) -> value.closeAll());
backpacks.clear();
2016-12-19 22:06:08 +01:00
unCacheStrategie.close();
2014-08-02 18:06:45 +02:00
}
public static @Nullable Database getDatabase(Minepacks plugin)
2015-03-29 00:03:24 +01:00
{
try
{
String dbType = plugin.getConfiguration().getDatabaseType();
ConnectionProvider connectionProvider = null;
if(dbType.equals("shared") || dbType.equals("external") || dbType.equals("global"))
{
/*if[STANDALONE]
plugin.getLogger().warning(ConsoleColor.RED + "The shared database connection option is not available in standalone mode!" + ConsoleColor.RESET);
return null;
else[STANDALONE]*/
at.pcgamingfreaks.PluginLib.Database.DatabaseConnectionPool pool = at.pcgamingfreaks.PluginLib.Bukkit.PluginLib.getInstance().getDatabaseConnectionPool();
if(pool == null)
{
plugin.getLogger().warning(ConsoleColor.RED + "The shared connection pool is not initialized correctly!" + ConsoleColor.RESET);
return null;
}
dbType = pool.getDatabaseType().toLowerCase(Locale.ROOT);
connectionProvider = pool.getConnectionProvider();
/*end[STANDALONE]*/
}
Database database;
switch(dbType)
{
case "mysql": database = new MySQL(plugin, connectionProvider); break;
case "sqlite": database = new SQLite(plugin, connectionProvider); break;
case "flat":
case "file":
case "files":
database = new Files(plugin); break;
default: plugin.getLogger().warning(String.format(MESSAGE_UNKNOWN_DB_TYPE, plugin.getConfiguration().getDatabaseType())); return null;
}
database.init();
return database;
}
catch(IllegalStateException ignored) {}
catch(Exception e)
2015-03-29 00:03:24 +01:00
{
e.printStackTrace();
2015-03-29 00:03:24 +01:00
}
return null;
2015-03-29 00:03:24 +01:00
}
2018-07-25 18:49:54 +02:00
public void backup(@NotNull Backpack backpack)
2018-06-07 23:43:33 +02:00
{
writeBackup(backpack.getOwner().getName(), getPlayerFormattedUUID(backpack.getOwner()), itsSerializer.getUsedSerializer(), itsSerializer.serialize(backpack.getInventory()));
2018-06-07 23:43:33 +02:00
}
protected void writeBackup(@Nullable String userName, @NotNull String userIdentifier, final int usedSerializer, final @NotNull byte[] data)
2018-06-07 23:43:33 +02:00
{
2018-07-25 18:49:54 +02:00
if(userIdentifier.equalsIgnoreCase(userName)) userName = null;
if(userName != null) userIdentifier = userName + "_" + userIdentifier;
final File save = new File(backupFolder, userIdentifier + "_" + System.currentTimeMillis() + Files.EXT);
2018-06-07 23:43:33 +02:00
try(FileOutputStream fos = new FileOutputStream(save))
{
fos.write(usedSerializer);
fos.write(data);
plugin.getLogger().info("Backup of the backpack has been created: " + save.getAbsolutePath());
}
2018-07-25 18:49:54 +02:00
catch(Exception e)
{
plugin.getLogger().warning(ConsoleColor.RED + "Failed to write backup! Error: " + e.getMessage() + ConsoleColor.RESET);
2018-07-25 18:49:54 +02:00
}
}
public @Nullable ItemStack[] loadBackup(final String backupName)
{
File backup = new File(backupFolder, backupName + Files.EXT);
return Files.readFile(itsSerializer, backup, plugin.getLogger());
}
2018-12-21 18:06:59 +01:00
public ArrayList<String> getBackups()
2018-07-25 18:49:54 +02:00
{
File[] files = backupFolder.listFiles((dir, name) -> name.endsWith(Files.EXT));
if(files != null)
2018-06-07 23:43:33 +02:00
{
2018-12-21 18:06:59 +01:00
ArrayList<String> backups = new ArrayList<>(files.length);
2018-07-25 18:49:54 +02:00
for(File file : files)
{
if(!file.isFile()) continue;
backups.add(file.getName().replaceAll(Files.EXT_REGEX, ""));
}
2018-12-21 18:06:59 +01:00
return backups;
2018-06-07 23:43:33 +02:00
}
2018-12-21 18:06:59 +01:00
return new ArrayList<>();
2018-06-07 23:43:33 +02:00
}
protected String getPlayerFormattedUUID(OfflinePlayer player)
2014-08-02 18:06:45 +02:00
{
return (useUUIDSeparators) ? player.getUniqueId().toString() : player.getUniqueId().toString().replace("-", "");
2014-08-02 18:06:45 +02:00
}
2016-12-19 22:06:08 +01:00
public @NotNull Collection<Backpack> getLoadedBackpacks()
{
return backpacks.values();
}
/**
* Gets a backpack for a player. This only includes backpacks that are cached! Do not use it unless you are sure that you only want to use cached data!
*
* @param player The player who's backpack should be retrieved.
* @return The backpack for the player. null if the backpack is not in the cache.
*/
2016-12-19 22:06:08 +01:00
public @Nullable Backpack getBackpack(@Nullable OfflinePlayer player)
{
return (player == null) ? null : backpacks.get(player);
}
public void getBackpack(final OfflinePlayer player, final Callback<at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack> callback, final boolean createNewOnFail)
{
if(player == null || player.getClass().getName().contains("NPC"))
{
return;
}
Backpack lbp = backpacks.get(player);
if(lbp == null)
{
loadBackpack(player, new Callback<Backpack>()
{
@Override
public void onResult(Backpack backpack)
{
2015-11-03 18:31:12 +01:00
backpacks.put(player, backpack);
callback.onResult(backpack);
}
@Override
public void onFail()
{
2018-12-21 18:06:59 +01:00
if(createNewOnFail)
{
Backpack backpack = new Backpack(player);
backpacks.put(player, backpack);
callback.onResult(backpack);
}
else
{
callback.onFail();
}
}
});
}
else
{
callback.onResult(lbp);
}
}
public void getBackpack(final OfflinePlayer player, final Callback<at.pcgamingfreaks.Minepacks.Bukkit.API.Backpack> callback)
2018-12-21 18:06:59 +01:00
{
getBackpack(player, callback, true);
}
public void unloadBackpack(Backpack backpack)
2014-08-02 18:06:45 +02:00
{
2023-06-02 21:17:11 +02:00
if (forceSaveOnUnload)
{
backpack.forceSave();
}
else
{
backpack.save();
}
backpacks.remove(backpack.getOwner());
}
public void asyncLoadBackpack(final OfflinePlayer player)
{
if(player != null && backpacks.get(player) == null)
{
loadBackpack(player, new Callback<Backpack>()
{
@Override
public void onResult(Backpack backpack)
{
backpacks.put(player, backpack);
}
2015-11-03 18:31:12 +01:00
@Override
public void onFail()
{
backpacks.put(player, new Backpack(player));
}
});
}
2014-08-02 18:06:45 +02:00
}
2016-12-19 22:06:08 +01:00
@EventHandler
public void onPlayerLoginEvent(PlayerJoinEvent event)
{
updatePlayerAndLoadBackpack(event.getPlayer());
}
2016-12-19 22:06:08 +01:00
// DB Functions
public void updatePlayerAndLoadBackpack(Player player)
{
updatePlayer(player);
if(!bungeeCordMode) asyncLoadBackpack(player);
}
public abstract void updatePlayer(Player player);
public abstract void saveBackpack(Backpack backpack);
public void syncCooldown(Player player, long time) {}
public void getCooldown(final Player player, final Callback<Long> callback) {}
protected abstract void loadBackpack(final OfflinePlayer player, final Callback<Backpack> callback);
2014-08-02 18:06:45 +02:00
}