Get rid of expensive calls to Bukkit#getOfflinePlayer with a username

This changes events to store the database Account instead of an OfflinePlayer and deprecates any event method that uses/returns OfflinePlayer. This is necessary as Bukkit#getOfflinePlayer(String) queries Mojang for the UUID when the user was not found in the local cache. As we already store this information (name to UUID mapping) in our database we should not have no need to rely on querying Mojang. (This might make transactions fail for shop owners that haven't played before but that shouldn't really be an issue in most cases)
This commit is contained in:
Phoenix616 2017-10-29 23:50:24 +01:00
parent 61c08a3b18
commit 2d45dcdac0
11 changed files with 101 additions and 52 deletions

View File

@ -49,7 +49,11 @@ public class Toggle implements CommandExecutor {
}
public static boolean isIgnoring(OfflinePlayer player) {
return player != null && toggledPlayers.contains(player.getName());
return player != null && isIgnoring(player.getName());
}
public static boolean isIgnoring(String playerName) {
return toggledPlayers.contains(playerName);
}
public static boolean setIgnoring(Player player, boolean ignoring) {

View File

@ -1,5 +1,8 @@
package com.Acrobot.ChestShop.Events;
import com.Acrobot.ChestShop.Database.Account;
import com.Acrobot.ChestShop.UUIDs.NameManager;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
@ -20,7 +23,7 @@ public class PreTransactionEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final Player client;
private OfflinePlayer owner;
private Account ownerAccount;
private final TransactionType transactionType;
private final Sign sign;
@ -33,7 +36,7 @@ public class PreTransactionEvent extends Event {
private TransactionOutcome transactionOutcome = TRANSACTION_SUCCESFUL;
public PreTransactionEvent(Inventory ownerInventory, Inventory clientInventory, ItemStack[] items, double price, Player client, OfflinePlayer owner, Sign sign, TransactionType type) {
public PreTransactionEvent(Inventory ownerInventory, Inventory clientInventory, ItemStack[] items, double price, Player client, Account ownerAccount, Sign sign, TransactionType type) {
this.ownerInventory = ownerInventory;
this.clientInventory = (clientInventory == null ? client.getInventory() : clientInventory);
@ -41,7 +44,7 @@ public class PreTransactionEvent extends Event {
this.price = price;
this.client = client;
this.owner = owner;
this.ownerAccount = ownerAccount;
this.sign = sign;
this.transactionType = type;
@ -94,19 +97,39 @@ public class PreTransactionEvent extends Event {
}
/**
* @return Shop's owner
* @return Account of the shop's owner
*/
public Account getOwnerAccount() {
return ownerAccount;
}
/**
* Sets the shop's owner
*
* @param ownerAccount Account of the shop owner
*/
public void setOwnerAccount(Account ownerAccount) {
this.ownerAccount = ownerAccount;
}
/**
* @return Shop's owner
* @deprecated Use {@link #getOwnerAccount}
*/
@Deprecated
public OfflinePlayer getOwner() {
return owner;
return Bukkit.getOfflinePlayer(ownerAccount.getUuid());
}
/**
* Sets the shop's owner
*
* @param owner Shop owner
* @deprecated Use {@link #setOwnerAccount(Account)}
*/
@Deprecated
public void setOwner(OfflinePlayer owner) {
this.owner = owner;
this.ownerAccount = NameManager.getAccount(owner.getUniqueId());
}
/**

View File

@ -1,5 +1,7 @@
package com.Acrobot.ChestShop.Events;
import com.Acrobot.ChestShop.Database.Account;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
@ -21,7 +23,7 @@ public class TransactionEvent extends Event {
private final Inventory clientInventory;
private final Player client;
private final OfflinePlayer owner;
private final Account ownerAccount;
private final ItemStack[] stock;
private final double price;
@ -35,7 +37,7 @@ public class TransactionEvent extends Event {
this.clientInventory = event.getClientInventory();
this.client = event.getClient();
this.owner = event.getOwner();
this.ownerAccount = event.getOwnerAccount();
this.stock = event.getStock();
this.price = event.getPrice();
@ -43,14 +45,14 @@ public class TransactionEvent extends Event {
this.sign = sign;
}
public TransactionEvent(TransactionType type, Inventory ownerInventory, Inventory clientInventory, Player client, OfflinePlayer owner, ItemStack[] stock, double price, Sign sign) {
public TransactionEvent(TransactionType type, Inventory ownerInventory, Inventory clientInventory, Player client, Account ownerAccount, ItemStack[] stock, double price, Sign sign) {
this.type = type;
this.ownerInventory = ownerInventory;
this.clientInventory = clientInventory;
this.client = client;
this.owner = owner;
this.ownerAccount = ownerAccount;
this.stock = stock;
this.price = price;
@ -87,10 +89,19 @@ public class TransactionEvent extends Event {
}
/**
* @return Shop's owner
* @return Account of the shop's owner
*/
public Account getOwnerAccount() {
return ownerAccount;
}
/**
* @return Shop's owner
* @deprecated Use {@link #getOwnerAccount}
*/
@Deprecated
public OfflinePlayer getOwner() {
return owner;
return Bukkit.getOfflinePlayer(ownerAccount.getUuid());
}
/**

View File

@ -1,6 +1,7 @@
package com.Acrobot.ChestShop.Listeners.Economy;
import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Database.Account;
import com.Acrobot.ChestShop.Events.Economy.*;
import com.Acrobot.ChestShop.UUIDs.NameManager;
import org.bukkit.event.EventHandler;
@ -29,7 +30,11 @@ public class ServerAccountCorrector implements Listener {
event.setAdded(true);
return;
} else {
target = NameManager.getUUID(SERVER_ECONOMY_ACCOUNT);
Account account = NameManager.getAccount(SERVER_ECONOMY_ACCOUNT);
if (account == null || account.getUuid() == null) {
return;
}
target = account.getUuid();
}
event.setAdded(true);
@ -53,7 +58,12 @@ public class ServerAccountCorrector implements Listener {
event.setSubtracted(true);
return;
} else {
target = NameManager.getUUID(SERVER_ECONOMY_ACCOUNT);
Account account = NameManager.getAccount(SERVER_ECONOMY_ACCOUNT);
if (account != null) {
target = account.getUuid();
} else {
target = null;
}
}
event.setSubtracted(true);
@ -77,11 +87,12 @@ public class ServerAccountCorrector implements Listener {
event.hasEnough(true);
return;
} else {
target = NameManager.getUUID(SERVER_ECONOMY_ACCOUNT);
if (target == null) {
Account account = NameManager.getAccount(SERVER_ECONOMY_ACCOUNT);
if (account == null || account.getUuid() == null) {
event.hasEnough(true);
return;
}
target = account.getUuid();
}
CurrencyCheckEvent currencyCheckEvent = new CurrencyCheckEvent(event.getAmount(), target, event.getWorld());
@ -106,7 +117,7 @@ public class ServerAccountCorrector implements Listener {
public static void onBalanceCheck(CurrencyAmountEvent event) {
UUID target = event.getAccount();
if (!NameManager.isAdminShop(target) || SERVER_ECONOMY_ACCOUNT.equals(NameManager.getUsername(target))) {
if (!NameManager.isAdminShop(target) || NameManager.isServerEconomyAccount(target)) {
return;
}
@ -114,10 +125,11 @@ public class ServerAccountCorrector implements Listener {
event.setAmount(BigDecimal.valueOf(Double.MAX_VALUE));
return;
} else {
target = NameManager.getUUID(SERVER_ECONOMY_ACCOUNT);
if (target == null) {
Account account = NameManager.getAccount(SERVER_ECONOMY_ACCOUNT);
if (account == null || account.getUuid() == null) {
return;
}
target = account.getUuid();
}
CurrencyAmountEvent currencyAmountEvent = new CurrencyAmountEvent(target, event.getWorld());

View File

@ -17,7 +17,6 @@ import com.Acrobot.ChestShop.Utils.uBlock;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.block.Sign;
@ -117,16 +116,8 @@ public class PlayerInteract implements Listener {
boolean adminShop = ChestShopSign.isAdminShop(sign);
// It seems to forget the username when getting by the offline UUID
// so we get the OfflinePlayer directly by the name in this case.
// We're also getting the OfflinePlayer of the admin shop by its
// name, because it will be also sometimes forgotten.
OfflinePlayer owner = account.getUuid().version() != 4 || adminShop
? Bukkit.getOfflinePlayer(account.getName())
: Bukkit.getOfflinePlayer(account.getUuid());
// check if player exists in economy
if(!adminShop && (owner == null || owner.getName() == null || !VaultListener.getProvider().hasAccount(owner)))
if(!adminShop && !VaultListener.getProvider().hasAccount(account.getName()))
return null;
Action buy = Properties.REVERSE_BUTTONS ? LEFT_CLICK_BLOCK : RIGHT_CLICK_BLOCK;
@ -160,7 +151,7 @@ public class PlayerInteract implements Listener {
ItemStack[] items = InventoryUtil.getItemsStacked(item);
TransactionType transactionType = (action == buy ? BUY : SELL);
return new PreTransactionEvent(ownerInventory, player.getInventory(), items, price, player, owner, sign, transactionType);
return new PreTransactionEvent(ownerInventory, player.getInventory(), items, price, player, account, sign, transactionType);
}
private static boolean isAllowedForShift(boolean buyTransaction) {

View File

@ -23,7 +23,7 @@ public class EconomicModule implements Listener {
}
CurrencyAddEvent currencyAddEvent = new CurrencyAddEvent(BigDecimal.valueOf(event.getPrice()),
event.getOwner().getUniqueId(),
event.getOwnerAccount().getUuid(),
event.getSign().getWorld());
ChestShop.callEvent(currencyAddEvent); // java.lang.StackOverflowError
@ -38,7 +38,7 @@ public class EconomicModule implements Listener {
}
CurrencySubtractEvent currencySubtractEvent = new CurrencySubtractEvent(BigDecimal.valueOf(event.getPrice()),
event.getOwner().getUniqueId(),
event.getOwnerAccount().getUuid(),
event.getSign().getWorld());
ChestShop.callEvent(currencySubtractEvent);

View File

@ -36,7 +36,7 @@ public class TransactionLogger implements Listener {
event.getClient().getName(),
items.toString(),
event.getPrice(),
NameManager.getUsername(event.getOwner().getUniqueId()),
event.getOwnerAccount().getName(),
LocationUtil.locationToString(event.getSign().getLocation()));
ChestShop.getBukkitLogger().info(message);

View File

@ -35,7 +35,7 @@ public class TransactionMessageSender implements Listener {
protected static void sendBuyMessage(TransactionEvent event) {
String itemName = parseItemInformation(event.getStock());
String owner = NameManager.getUsername(event.getOwner().getUniqueId());
String owner = event.getOwnerAccount().getName();
Player player = event.getClient();
@ -48,7 +48,7 @@ public class TransactionMessageSender implements Listener {
player.sendMessage(message);
}
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(event.getOwner())) {
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(event.getOwnerAccount().getName())) {
String message = formatMessage(Messages.SOMEBODY_BOUGHT_FROM_YOUR_SHOP, itemName, price);
message = message.replace("%buyer", player.getName());
@ -58,7 +58,7 @@ public class TransactionMessageSender implements Listener {
protected static void sendSellMessage(TransactionEvent event) {
String itemName = parseItemInformation(event.getStock());
String owner = NameManager.getUsername(event.getOwner().getUniqueId());
String owner = event.getOwnerAccount().getName();
Player player = event.getClient();
@ -71,7 +71,7 @@ public class TransactionMessageSender implements Listener {
player.sendMessage(message);
}
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(event.getOwner())) {
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(owner)) {
String message = formatMessage(Messages.SOMEBODY_SOLD_TO_YOUR_SHOP, itemName, price);
message = message.replace("%seller", player.getName());
@ -92,7 +92,7 @@ public class TransactionMessageSender implements Listener {
}
private static void sendMessageToOwner(String message, TransactionEvent event) {
UUID owner = event.getOwner().getUniqueId();
UUID owner = event.getOwnerAccount().getUuid();
Player player = Bukkit.getPlayer(owner);

View File

@ -52,7 +52,7 @@ public class AmountAndPriceChecker implements Listener {
Inventory clientInventory = event.getClientInventory();
CurrencyCheckEvent currencyCheckEvent = new CurrencyCheckEvent(BigDecimal.valueOf(event.getPrice()),
event.getOwner().getUniqueId(),
event.getOwnerAccount().getUuid(),
event.getSign().getWorld());
ChestShop.callEvent(currencyCheckEvent);

View File

@ -5,9 +5,10 @@ import com.Acrobot.Breeze.Utils.MaterialUtil;
import com.Acrobot.ChestShop.Commands.Toggle;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Database.Account;
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -47,7 +48,7 @@ public class ErrorMessageSender implements Listener {
message = Messages.NOT_ENOUGH_MONEY_SHOP;
break;
case NOT_ENOUGH_SPACE_IN_CHEST:
if (Properties.SHOW_MESSAGE_FULL_SHOP && !Properties.CSTOGGLE_TOGGLES_FULL_SHOP || !Toggle.isIgnoring(event.getOwner())) {
if (Properties.SHOW_MESSAGE_FULL_SHOP && !Properties.CSTOGGLE_TOGGLES_FULL_SHOP || !Toggle.isIgnoring(event.getOwnerAccount().getName())) {
Location loc = event.getSign().getLocation();
String messageNotEnoughSpace = Messages.prefix(NOT_ENOUGH_SPACE_IN_YOUR_SHOP)
.replace("%material", getItemNames(event.getStock()))
@ -56,7 +57,7 @@ public class ErrorMessageSender implements Listener {
.replace("%x", String.valueOf(loc.getBlockX()))
.replace("%y", String.valueOf(loc.getBlockY()))
.replace("%z", String.valueOf(loc.getBlockZ()));
sendMessageToOwner(event.getOwner(), messageNotEnoughSpace);
sendMessageToOwner(event.getOwnerAccount(), messageNotEnoughSpace);
}
message = Messages.NOT_ENOUGH_SPACE_IN_CHEST;
break;
@ -67,7 +68,7 @@ public class ErrorMessageSender implements Listener {
message = Messages.NOT_ENOUGH_ITEMS_TO_SELL;
break;
case NOT_ENOUGH_STOCK_IN_CHEST:
if (Properties.SHOW_MESSAGE_OUT_OF_STOCK && !Properties.CSTOGGLE_TOGGLES_OUT_OF_STOCK || !Toggle.isIgnoring(event.getOwner())) {
if (Properties.SHOW_MESSAGE_OUT_OF_STOCK && !Properties.CSTOGGLE_TOGGLES_OUT_OF_STOCK || !Toggle.isIgnoring(event.getOwnerAccount().getName())) {
Location loc = event.getSign().getLocation();
String messageOutOfStock = Messages.prefix(NOT_ENOUGH_STOCK_IN_YOUR_SHOP)
.replace("%material", getItemNames(event.getStock()))
@ -76,7 +77,7 @@ public class ErrorMessageSender implements Listener {
.replace("%x", String.valueOf(loc.getBlockX()))
.replace("%y", String.valueOf(loc.getBlockY()))
.replace("%z", String.valueOf(loc.getBlockZ()));
sendMessageToOwner(event.getOwner(), messageOutOfStock);
sendMessageToOwner(event.getOwnerAccount(), messageOutOfStock);
}
message = Messages.NOT_ENOUGH_STOCK;
break;
@ -85,7 +86,7 @@ public class ErrorMessageSender implements Listener {
break;
case SHOP_DEPOSIT_FAILED:
String messageDepositFailed = Messages.prefix(CLIENT_DEPOSIT_FAILED);
sendMessageToOwner(event.getOwner(), messageDepositFailed);
sendMessageToOwner(event.getOwnerAccount(), messageDepositFailed);
message = Messages.SHOP_DEPOSIT_FAILED;
break;
case SHOP_IS_RESTRICTED:
@ -115,9 +116,9 @@ public class ErrorMessageSender implements Listener {
return names.toString();
}
private static void sendMessageToOwner(OfflinePlayer owner, String message) {
if (owner.isOnline()) {
Player player = (Player) owner;
private static void sendMessageToOwner(Account ownerAccount, String message) {
Player player = Bukkit.getPlayer(ownerAccount.getUuid());
if (player != null) {
player.sendMessage(message);
}
}

View File

@ -37,6 +37,9 @@ public class NameManager {
private static SimpleLoadingCache<UUID, Account> uuidToAccount = new SimpleLoadingCache<>(Properties.CACHE_SIZE);
private static SimpleLoadingCache<String, Account> shortToAccount = new SimpleLoadingCache<>(Properties.CACHE_SIZE);
private static Account adminAccount;
private static Account serverEconomyAccount;
/**
* Get account info from a UUID
* @param uuid The UUID of the player to get the account info
@ -265,18 +268,22 @@ public class NameManager {
}
public static boolean isAdminShop(UUID uuid) {
return Properties.ADMIN_SHOP_NAME.equals(getUsername(uuid));
return adminAccount != null && uuid.equals(adminAccount.getUuid());
}
public static boolean isServerEconomyAccount(UUID uuid) {
return serverEconomyAccount != null && uuid.equals(serverEconomyAccount.getUuid());
}
public static void load() {
try {
accounts = DaoCreator.getDaoAndCreateTable(Account.class);
Account adminAccount = new Account(Properties.ADMIN_SHOP_NAME, Bukkit.getOfflinePlayer(Properties.ADMIN_SHOP_NAME).getUniqueId());
adminAccount = new Account(Properties.ADMIN_SHOP_NAME, Bukkit.getOfflinePlayer(Properties.ADMIN_SHOP_NAME).getUniqueId());
accounts.createOrUpdate(adminAccount);
if (!Properties.SERVER_ECONOMY_ACCOUNT.isEmpty()) {
Account serverEconomyAccount = getAccount(Properties.SERVER_ECONOMY_ACCOUNT);
serverEconomyAccount = getAccount(Properties.SERVER_ECONOMY_ACCOUNT);
if (serverEconomyAccount == null || serverEconomyAccount.getUuid() == null) {
ChestShop.getBukkitLogger().log(Level.WARNING, "Server economy account setting '" + Properties.SERVER_ECONOMY_ACCOUNT + "' doesn't seem to be the name of a known player! Please log in at least once in order for the server economy account to work.");
}