/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock 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.
*
* ASkyBlock 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 ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.wasteofplastic.askyblock;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.scheduler.BukkitRunnable;
/**
* Tiny database for a hashmap that is not used very often, but could be very big so I
* don't want it in memory.
* @author tastybento
*
*/
public class TinyDB {
private ASkyBlock plugin;
private ConcurrentHashMap<String,UUID> treeMap;
private boolean dbReady;
private boolean savingFlag;
/**
* Opens the database
* @param plugin
*/
public TinyDB(ASkyBlock plugin) {
this.plugin = plugin;
this.treeMap = new ConcurrentHashMap<String,UUID>();
File database = new File(plugin.getDataFolder(), "name-uuid.txt");
if (!database.exists()) {
// Import from player files. Done async so may take a while
convertFiles();
} else {
// Ready to go...
this.dbReady = true;
}
}
/**
* Async Saving of the DB
*/
public void asyncSaveDB() {
if (!savingFlag) {
new BukkitRunnable() {
@Override
public void run() {
saveDB();
}}.runTaskAsynchronously(plugin);
}
}
/**
* Saves the DB
*/
public void saveDB() {
savingFlag = true;
try {
File oldDB = new File(plugin.getDataFolder(), "name-uuid.txt");
File newDB = new File(plugin.getDataFolder(), "name-uuid-new.txt");
//File backup = new File(plugin.getDataFolder(), "name-uuid.bak");
try(PrintWriter out = new PrintWriter(newDB)) {
// Write the newest entries at the top
for (Entry<String, UUID> entry: treeMap.entrySet()) {
out.println(entry.getKey());
out.println(entry.getValue().toString());
}
if (oldDB.exists()) {
// Go through the old file and remove any
try(BufferedReader br = new BufferedReader(new FileReader(oldDB))){
// Go through the old file and read it line by line and write to the new file
String line = br.readLine();
String uuid = br.readLine();
while (line != null) {
if (!treeMap.containsKey(line)) {
out.println(line);
out.println(uuid);
}
// Read next lines
line = br.readLine();
uuid = br.readLine();
}
br.close();
}
}
out.close();
}
// Move files around
try {
Files.move(newDB.toPath(), oldDB.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
plugin.getLogger().severe("Problem saving name database! Could not rename files!");
}
} catch (IOException e) {
plugin.getLogger().severe("Problem saving name database!");
e.printStackTrace();
}
savingFlag = false;
}
private void convertFiles() {
/** create database */
new BukkitRunnable() {
@Override
public void run() {
try {
// Load all the files from the player folder
FilenameFilter ymlFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".yml")) {
return true;
} else {
return false;
}
}
};
int count = 0;
for (final File file : plugin.getPlayersFolder().listFiles(ymlFilter)) {
if (count % 1000 == 0) {
System.out.println("[ASkyBlock]: Processed " + count + " names to database");
}
count++;
try {
// Get UUID
String uuid = file.getName().substring(0, file.getName().length() - 4);
//System.out.println("DEBUG: UUID is " + uuid);
final UUID playerUUID = UUID.fromString(uuid);
// Get the player's name
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if (lineFromFile.contains("playerName:")) {
// Check against potentialUnowned list
String playerName = lineFromFile.substring(lineFromFile.indexOf(' ')).trim();
//System.out.println("DEBUG: Player name is " + playerName);
treeMap.put(playerName.toLowerCase(), playerUUID);
break;
}
}
scanner.close();
} catch (Exception ex) {
System.err.println("[ASkyBlock/AcidIsland]: Problem reading " + file.getName() + " skipping...");
//ex.printStackTrace();
}
}
// Save files
saveDB();
// Save memory
treeMap.clear();
System.out.println("Complete. Processed " + count + " names to database");
// Set flag
dbReady = true;
} catch (Exception e) {
System.err.println("[ASkyBlock/AcidIsland] : Problem creating database");
}
}}.runTaskAsynchronously(plugin);
}
/**
* @return the dbReady
*/
public boolean isDbReady() {
return dbReady;
}
/**
* Saves the player name to the database. Case insensitive!
* @param playerName
* @param playerUUID
*/
public void savePlayerName(String playerName, UUID playerUUID) {
treeMap.put(playerName.toLowerCase(), playerUUID);
// This will be saved when everything shuts down
}
/**
* Gets the UUID for this player name or null if not known. Case insensitive!
* @param playerName
* @return UUID of player, or null if unknown
*/
public UUID getPlayerUUID(String playerName) {
// Try cache
if (treeMap.containsKey(playerName.toLowerCase())) {
//plugin.getLogger().info("DEBUG: found in UUID cache");
return treeMap.get(playerName.toLowerCase());
}
// Names and UUID's are stored in line pairs.
try(BufferedReader br = new BufferedReader(new FileReader(new File(plugin.getDataFolder(), "name-uuid.txt")))) {
String line = br.readLine();
String uuid = br.readLine();
while (line != null && !line.equalsIgnoreCase(playerName)) {
line = br.readLine();
uuid = br.readLine();
}
if (line == null) {
return null;
}
UUID result = UUID.fromString(uuid);
// Add to cache
treeMap.put(playerName.toLowerCase(), result);
//plugin.getLogger().info("DEBUG: found in UUID database");
return result;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* Gets players name from tiny database
* @param playerUuid
* @return Name or empty string if unknown
*/
public String getPlayerName(UUID playerUuid) {
// Names and UUID's are stored in line pairs.
try(BufferedReader br = new BufferedReader(new FileReader(new File(plugin.getDataFolder(), "name-uuid.txt")))) {
String line = br.readLine();
String uuid = br.readLine();
while (uuid != null && !uuid.equals(playerUuid.toString())) {
line = br.readLine();
uuid = br.readLine();
}
if (line == null) {
return "";
}
// Add to cache
treeMap.put(line.toLowerCase(), playerUuid);
plugin.getLogger().info("DEBUG: found in UUID database - name is " + line);
return line;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}