2014-04-06 19:51:30 +02:00
|
|
|
package com.Acrobot.ChestShop.UUIDs;
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
import com.Acrobot.Breeze.Utils.Encoding.Base62;
|
2014-04-06 19:51:47 +02:00
|
|
|
import com.Acrobot.Breeze.Utils.NameUtil;
|
2017-06-30 22:00:30 +02:00
|
|
|
import com.Acrobot.ChestShop.ChestShop;
|
2014-04-12 16:52:21 +02:00
|
|
|
import com.Acrobot.ChestShop.Configuration.Properties;
|
2014-04-10 21:52:05 +02:00
|
|
|
import com.Acrobot.ChestShop.Database.Account;
|
2015-05-22 13:26:07 +02:00
|
|
|
import com.Acrobot.ChestShop.Database.DaoCreator;
|
2014-04-12 13:57:39 +02:00
|
|
|
import com.Acrobot.ChestShop.Permission;
|
2014-08-13 17:22:52 +02:00
|
|
|
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
2017-06-30 21:28:18 +02:00
|
|
|
import com.google.common.cache.Cache;
|
|
|
|
import com.google.common.cache.CacheBuilder;
|
|
|
|
import com.j256.ormlite.dao.CloseableIterator;
|
2014-04-10 21:52:05 +02:00
|
|
|
import com.j256.ormlite.dao.Dao;
|
2016-09-20 21:45:18 +02:00
|
|
|
|
|
|
|
import org.apache.commons.lang.Validate;
|
2014-04-12 16:52:21 +02:00
|
|
|
import org.bukkit.Bukkit;
|
2016-07-07 18:15:43 +02:00
|
|
|
import org.bukkit.OfflinePlayer;
|
2014-04-06 19:51:47 +02:00
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
|
2014-04-10 21:52:05 +02:00
|
|
|
import java.sql.SQLException;
|
2014-04-06 19:51:47 +02:00
|
|
|
import java.util.UUID;
|
2017-06-30 21:28:18 +02:00
|
|
|
import java.util.concurrent.ExecutionException;
|
2016-07-07 18:15:43 +02:00
|
|
|
import java.util.logging.Level;
|
2014-04-06 19:51:47 +02:00
|
|
|
|
2014-04-06 19:51:30 +02:00
|
|
|
/**
|
2014-04-06 19:51:47 +02:00
|
|
|
* Lets you save/cache username and UUID relations
|
2014-04-11 17:23:04 +02:00
|
|
|
*
|
2014-04-06 19:51:30 +02:00
|
|
|
* @author Andrzej Pomirski (Acrobot)
|
|
|
|
*/
|
2016-07-07 18:15:43 +02:00
|
|
|
@SuppressWarnings("UnusedAssignment") // I deliberately set the variables to null while initializing
|
2014-04-12 13:57:39 +02:00
|
|
|
public class NameManager {
|
2014-04-10 21:52:05 +02:00
|
|
|
private static Dao<Account, String> accounts;
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
private static Cache<String, UUID> usernameToUUID = CacheBuilder.newBuilder().maximumSize(Properties.CACHE_SIZE).build();
|
|
|
|
private static Cache<UUID, String> uuidToUsername = CacheBuilder.newBuilder().maximumSize(Properties.CACHE_SIZE).build();
|
|
|
|
private static Cache<String, String> shortToLongName = CacheBuilder.newBuilder().maximumSize(Properties.CACHE_SIZE).build();
|
2015-03-11 18:02:30 +01:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
/**
|
|
|
|
* Get the UUID from a player's (non-shortened) username
|
|
|
|
* @param username The player's username
|
|
|
|
* @return The UUID or <tt>null</tt> if the UUID can't be found or an error occurred
|
|
|
|
*/
|
2014-04-10 21:52:05 +02:00
|
|
|
public static UUID getUUID(String username) {
|
2017-06-30 21:28:18 +02:00
|
|
|
Validate.notEmpty(username, "username cannot be null or empty!");
|
2014-04-10 21:52:05 +02:00
|
|
|
try {
|
2017-06-30 21:28:18 +02:00
|
|
|
return usernameToUUID.get(username, () -> {
|
|
|
|
UUID uuid = null;
|
|
|
|
Player player = Bukkit.getPlayer(username);
|
|
|
|
if (player != null) {
|
|
|
|
uuid = player.getUniqueId();
|
|
|
|
}
|
|
|
|
if (uuid == null) {
|
|
|
|
try {
|
|
|
|
Account account = accounts.queryBuilder().selectColumns("uuid").where().eq("lastSeenName", username).queryForFirst();
|
|
|
|
if (account != null) {
|
|
|
|
uuid = account.getUuid();
|
|
|
|
}
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting uuid for " + username + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uuid == null) {
|
|
|
|
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username);
|
|
|
|
if (offlinePlayer != null && offlinePlayer.hasPlayedBefore() && offlinePlayer.getUniqueId() != null) {
|
|
|
|
uuid = offlinePlayer.getUniqueId();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uuid != null) {
|
|
|
|
uuidToUsername.put(uuid, username);
|
|
|
|
return uuid;
|
|
|
|
}
|
|
|
|
throw new Exception("Could not find username for " + uuid);
|
|
|
|
});
|
|
|
|
} catch (ExecutionException e) {
|
2014-04-10 21:52:05 +02:00
|
|
|
return null;
|
|
|
|
}
|
2014-04-06 19:51:47 +02:00
|
|
|
}
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
/**
|
|
|
|
* Get the username from a player's UUID
|
|
|
|
* @param uuid The UUID of the player
|
|
|
|
* @return The username that is stored, an empty string if none was found or <tt>null</tt> if an error occurred
|
|
|
|
*/
|
2014-04-10 21:52:05 +02:00
|
|
|
public static String getUsername(UUID uuid) {
|
|
|
|
try {
|
2017-06-30 21:28:18 +02:00
|
|
|
return uuidToUsername.get(uuid, () -> {
|
|
|
|
String name = null;
|
|
|
|
Player player = Bukkit.getPlayer(uuid);
|
|
|
|
if (player != null) {
|
|
|
|
name = player.getName();
|
|
|
|
}
|
|
|
|
if (name == null) {
|
|
|
|
try {
|
|
|
|
Account account = accounts.queryBuilder().selectColumns("lastSeenName").where().eq("uuid", uuid).queryForFirst();
|
|
|
|
if (account != null) {
|
|
|
|
name = account.getLastSeenName();
|
|
|
|
}
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting username for " + uuid + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (name == null) {
|
|
|
|
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
|
|
|
if (offlinePlayer != null && offlinePlayer.hasPlayedBefore() && offlinePlayer.getName() != null) {
|
|
|
|
name = offlinePlayer.getName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (name != null) {
|
|
|
|
usernameToUUID.put(name, uuid);
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
throw new Exception("Could not find username for " + uuid);
|
|
|
|
});
|
|
|
|
} catch (ExecutionException e) {
|
2014-04-12 14:22:34 +02:00
|
|
|
return "";
|
2014-04-11 17:17:20 +02:00
|
|
|
}
|
2014-04-06 19:51:47 +02:00
|
|
|
}
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
/**
|
|
|
|
* Get the full username from another username that might be shortened
|
|
|
|
* @param shortName The name of the player to get the full username for
|
|
|
|
* @return The full username, an empty string if none was found or <tt>null</tt> if an error occurred
|
|
|
|
* @throws IllegalArgumentException if the username is not a shortened name and longer than 15 chars
|
|
|
|
*/
|
|
|
|
public static String getFullUsername(String shortName) {
|
|
|
|
Validate.isTrue(shortName.length() < 16, "Username is not a shortened name and longer than 15 chars!");
|
|
|
|
if (ChestShopSign.isAdminShop(shortName)) {
|
2014-08-13 17:22:52 +02:00
|
|
|
return Properties.ADMIN_SHOP_NAME;
|
|
|
|
}
|
|
|
|
|
2014-04-10 22:52:21 +02:00
|
|
|
try {
|
2017-06-30 21:28:18 +02:00
|
|
|
return shortToLongName.get(shortName, () -> {
|
|
|
|
try {
|
|
|
|
Account account = accounts.queryBuilder().selectColumns("lastSeenName").where().eq("shortName", shortName).queryForFirst();
|
|
|
|
if (account != null) {
|
|
|
|
return account.getLastSeenName();
|
|
|
|
}
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting full name for " + shortName + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
|
|
|
throw new Exception("Could not find full name for " + shortName);
|
|
|
|
});
|
|
|
|
} catch (ExecutionException ignored) {
|
|
|
|
return "";
|
2014-04-06 19:51:47 +02:00
|
|
|
}
|
2014-05-06 11:55:33 +02:00
|
|
|
}
|
2014-04-06 19:51:47 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
/**
|
|
|
|
* Store the username of a player into the database and the username-uuid cache
|
|
|
|
* @param player The data transfer object of the player to store
|
|
|
|
*/
|
2015-07-05 21:56:42 +02:00
|
|
|
public static void storeUsername(final PlayerDTO player) {
|
2014-05-06 11:55:33 +02:00
|
|
|
final UUID uuid = player.getUniqueId();
|
2014-04-06 19:51:47 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
CloseableIterator<Account> existingAccounts = null;
|
2015-03-11 18:02:30 +01:00
|
|
|
try {
|
2017-06-30 21:28:18 +02:00
|
|
|
existingAccounts = accounts.queryBuilder().where().eq("uuid", uuid).ne("lastSeenName", player.getName()).iterator();
|
|
|
|
while (existingAccounts.hasNext()) {
|
|
|
|
Account account = existingAccounts.next();
|
|
|
|
account.setUuid(uuid); //HOW IS IT EVEN POSSIBLE THAT UUID IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
|
|
|
account.setLastSeenName(player.getName());
|
|
|
|
try {
|
|
|
|
accounts.update(account);
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while updating account " + account + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
|
|
|
}
|
2015-03-11 18:02:30 +01:00
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error getting all entries for " + uuid + ":", e);
|
2015-03-11 18:02:30 +01:00
|
|
|
return;
|
2017-06-30 21:28:18 +02:00
|
|
|
} finally {
|
|
|
|
if (existingAccounts != null) {
|
|
|
|
try {
|
|
|
|
existingAccounts.close();
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while closing query iterator for " + uuid + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
|
|
|
}
|
2014-04-10 21:52:05 +02:00
|
|
|
}
|
2014-05-06 11:55:33 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
Account latestAccount = null;
|
|
|
|
try {
|
|
|
|
latestAccount = accounts.queryBuilder().where().eq("uuid", uuid).eq("name", player.getName()).queryForFirst();
|
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while searching for latest account of " + player.getName() + "/" + uuid + ":", e);
|
2017-06-30 21:28:18 +02:00
|
|
|
}
|
2015-07-05 21:56:42 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
if (latestAccount == null) {
|
|
|
|
latestAccount = new Account(player.getName(), player.getUniqueId());
|
|
|
|
latestAccount.setShortName(getNewShortenedName(player));
|
2014-05-06 11:55:33 +02:00
|
|
|
|
2015-03-11 18:02:30 +01:00
|
|
|
try {
|
2017-06-30 21:28:18 +02:00
|
|
|
accounts.create(latestAccount);
|
2015-03-11 18:02:30 +01:00
|
|
|
} catch (SQLException e) {
|
2017-06-30 22:00:30 +02:00
|
|
|
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while updating account " + latestAccount + ":", e);
|
2015-03-11 18:02:30 +01:00
|
|
|
}
|
|
|
|
}
|
2014-05-06 11:55:33 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
usernameToUUID.put(latestAccount.getLastSeenName(), uuid);
|
|
|
|
uuidToUsername.put(uuid, latestAccount.getLastSeenName());
|
2015-03-11 18:02:30 +01:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
shortToLongName.put(latestAccount.getShortName(), latestAccount.getLastSeenName());
|
2014-04-06 19:51:47 +02:00
|
|
|
}
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
/**
|
|
|
|
* Get a new unique shortened name that hasn't been used by another player yet
|
|
|
|
* @param player The player data to get the shortened name for
|
|
|
|
* @return A new shortened name that hasn't been used before and is a maximum of 15 chars long
|
|
|
|
*/
|
|
|
|
private static String getNewShortenedName(PlayerDTO player) {
|
|
|
|
String shortenedName = NameUtil.stripUsername(player.getName());
|
2014-07-03 18:49:12 +02:00
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
String fullName = getFullUsername(shortenedName);
|
|
|
|
if (fullName != null && fullName.isEmpty()) {
|
|
|
|
return shortenedName;
|
2014-07-03 18:49:12 +02:00
|
|
|
}
|
2017-06-30 21:28:18 +02:00
|
|
|
for (int id = 0; fullName != null && !fullName.isEmpty(); id++) {
|
|
|
|
String baseId = Base62.encode(id);
|
|
|
|
shortenedName = NameUtil.stripUsername(player.getName(), 15 - 1 - baseId.length()) + ":" + baseId;
|
|
|
|
fullName = getFullUsername(shortenedName);
|
2014-07-03 18:49:12 +02:00
|
|
|
}
|
2017-06-30 21:28:18 +02:00
|
|
|
|
|
|
|
return shortenedName;
|
2014-07-03 18:49:12 +02:00
|
|
|
}
|
|
|
|
|
2014-04-12 13:57:39 +02:00
|
|
|
public static boolean canUseName(Player player, String name) {
|
|
|
|
String shortenedName = NameUtil.stripUsername(getUsername(player.getUniqueId()));
|
|
|
|
|
2015-03-21 16:11:33 +01:00
|
|
|
if (ChestShopSign.isAdminShop(name)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-30 21:28:18 +02:00
|
|
|
return shortenedName.equals(name) || Permission.otherName(player, name) || (!name.isEmpty() && player.getName().equals(getFullUsername(name)));
|
2014-04-12 13:57:39 +02:00
|
|
|
}
|
|
|
|
|
2014-06-14 20:46:59 +02:00
|
|
|
public static boolean isAdminShop(UUID uuid) {
|
2015-05-22 13:26:07 +02:00
|
|
|
return Properties.ADMIN_SHOP_NAME.equals(getUsername(uuid));
|
2014-06-14 20:46:59 +02:00
|
|
|
}
|
|
|
|
|
2014-04-06 19:51:47 +02:00
|
|
|
public static void load() {
|
|
|
|
try {
|
2015-05-22 13:26:07 +02:00
|
|
|
accounts = DaoCreator.getDaoAndCreateTable(Account.class);
|
2014-04-12 16:52:21 +02:00
|
|
|
|
|
|
|
Account adminAccount = new Account(Properties.ADMIN_SHOP_NAME, Bukkit.getOfflinePlayer(Properties.ADMIN_SHOP_NAME).getUniqueId());
|
2014-07-28 20:51:04 +02:00
|
|
|
accounts.createOrUpdate(adminAccount);
|
2014-04-10 21:52:05 +02:00
|
|
|
} catch (SQLException e) {
|
2014-04-06 19:51:47 +02:00
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
2014-04-06 19:51:30 +02:00
|
|
|
}
|