use of com.almuradev.almura.feature.exchange.network.ClientboundListItemsResponsePacket in project Almura by AlmuraDev.
the class ServerExchangeManager method handleTransaction.
/**
* Transaction
*/
public void handleTransaction(final Player player, final String id, final int listItemRecNo, final int quantity) {
checkNotNull(player);
checkNotNull(id);
checkState(listItemRecNo >= 0);
checkState(quantity > 0);
final Exchange axs = this.getExchange(id).orElse(null);
if (axs == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("Critical error encountered, check the " + "server console for more details!"));
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' but the server has no knowledge of it. Syncing exchange " + "registry...", player.getName(), id);
this.syncExchangeRegistryTo(player);
return;
}
final EconomyService economyService = this.serviceManager.provide(EconomyService.class).orElse(null);
if (economyService == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("Critical error encountered, check the " + "server console for more details!"));
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' but the economy service no longer exists. This is a " + "critical error that should be reported to your economy plugin ASAP.", player.getName(), id);
return;
}
final UniqueAccount buyerAccount = economyService.getOrCreateAccount(player.getUniqueId()).orElse(null);
if (buyerAccount == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("Critical error encountered, check the " + "server console for more details!"));
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' but the economy service returned no account for them. " + "This is a critical error that should be reported to your economy plugin ASAP.", player.getName(), id);
return;
}
ListItem found = null;
for (final Map.Entry<UUID, List<ListItem>> kv : axs.getListItems().entrySet()) {
final ListItem listItem = kv.getValue().stream().filter(item -> item.getRecord() == listItemRecNo).findAny().orElse(null);
if (listItem != null) {
found = listItem;
break;
}
}
if (found == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("This item is no longer for sale!"));
this.network.sendTo(player, new ClientboundForSaleFilterRequestPacket(axs.getId()));
return;
}
final UUID seller = found.getSeller();
final UUID buyer = player.getUniqueId();
if (buyer.equals(seller)) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("You cannot purchase your own items."));
return;
}
final UniqueAccount sellerAccount = economyService.getOrCreateAccount(seller).orElse(null);
if (sellerAccount == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("Critical error encountered, check the " + "server console for more details!"));
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' but the economy service returned no account for seller" + " '{}'. This is a critical error that should be reported to your economy plugin ASAP.", player.getName(), id, seller);
return;
}
final ForSaleItem forSaleItem = found.getForSaleItem().orElse(null);
if (forSaleItem == null) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("This item is no longer for sale!"));
this.network.sendTo(player, new ClientboundForSaleFilterRequestPacket(axs.getId()));
return;
}
if (found.getQuantity() < quantity) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("There is not enough quantity left to " + "purchase this item!"));
this.network.sendTo(player, new ClientboundForSaleFilterRequestPacket(axs.getId()));
return;
}
final BigDecimal balance = buyerAccount.getBalance(economyService.getDefaultCurrency());
final BigDecimal price = forSaleItem.getPrice();
final double total = price.doubleValue() * quantity;
if (total > balance.doubleValue()) {
final String formattedTotal = FeatureConstants.CURRENCY_DECIMAL_FORMAT.format(total);
final String formattedBalance = FeatureConstants.CURRENCY_DECIMAL_FORMAT.format(balance.doubleValue());
final String formattedDifference = FeatureConstants.CURRENCY_DECIMAL_FORMAT.format(total - balance.doubleValue());
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("You attempted to purchase items totaling to ", TextColors.RED, formattedTotal, TextColors.RESET, " while you only have ", TextColors.GREEN, formattedBalance, TextColors.RESET, ".", Text.NEW_LINE, Text.NEW_LINE, "You need ", TextColors.LIGHT_PURPLE, formattedDifference, TextColors.RESET, " more!"));
return;
}
EntityPlayerMP serverPlayer = (EntityPlayerMP) player;
final IItemHandler inventory = serverPlayer.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.UP);
final ListItem copyStack = found.copy();
copyStack.setQuantity(quantity);
final ItemStack simulatedResultStack = ItemHandlerHelper.insertItemStacked(inventory, copyStack.asRealStack(), true);
if (!simulatedResultStack.isEmpty()) {
this.notificationManager.sendWindowMessage(player, Text.of("Exchange"), Text.of("You lack sufficient inventory space to " + "purchase these item(s)!"));
return;
}
final int originalQuantity = found.getQuantity();
final int quantityRemaining = originalQuantity - (quantity - simulatedResultStack.getCount());
final int forSaleItemRecord = forSaleItem.getRecord();
// Charge the buyer
try (final CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
frame.pushCause(axs);
buyerAccount.transfer(sellerAccount, economyService.getDefaultCurrency(), BigDecimal.valueOf(total), frame.getCurrentCause());
}
this.scheduler.createTaskBuilder().async().execute(() -> {
try (final DSLContext context = this.databaseManager.createContext(true)) {
// Update listed quantity
int result = ExchangeQueries.createUpdateListItemQuantity(listItemRecNo, quantityRemaining, true).build(context).execute();
if (result == 0) {
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' to the database but it failed. Discarding " + "changes...", player.getName(), id);
return;
}
if (quantityRemaining == 0) {
result = ExchangeQueries.createUpdateForSaleItemIsHidden(forSaleItemRecord, true).build(context).execute();
if (result == 0) {
this.logger.error("Player '{}' attempted to make a transaction in-which was the entire listing for exchange '{}' to the " + "database but it failed. Discarding changes...", player.getName(), id);
ExchangeQueries.createUpdateListItemQuantity(listItemRecNo, originalQuantity, true).build(context).execute();
return;
}
}
// Issue a transaction
result = ExchangeQueries.createInsertTransaction(Instant.now(), forSaleItemRecord, buyer, price, quantity).build(context).execute();
if (result == 0) {
this.logger.error("Player '{}' attempted to make a transaction for exchange '{}' to the database but it failed. Discarding " + "changes...", player.getName(), id);
ExchangeQueries.createUpdateListItemQuantity(listItemRecNo, originalQuantity, false).build(context).execute();
ExchangeQueries.createUpdateForSaleItemIsHidden(forSaleItemRecord, false).build(context).execute();
return;
}
final Results listItemResults = ExchangeQueries.createFetchListItemsAndDataFor(seller, false).build(context).keepStatement(false).fetchMany();
final Results forSaleItemResults = ExchangeQueries.createFetchForSaleItemsFor(seller, false).build(context).keepStatement(false).fetchMany();
this.scheduler.createTaskBuilder().execute(() -> {
final List<ListItem> listItems = new ArrayList<>();
listItemResults.forEach(r -> listItems.addAll(this.parseListItemsFrom(r)));
final List<ForSaleItem> forSaleItems = new ArrayList<>();
forSaleItemResults.forEach(r -> forSaleItems.addAll(this.parseForSaleItemsFrom(listItems, r)));
axs.putListItemsFor(seller, listItems);
axs.putForSaleItemsFor(seller, forSaleItems);
final ItemStack resultStack = ItemHandlerHelper.insertItemStacked(inventory, copyStack.asRealStack(), false);
if (!resultStack.isEmpty()) {
// TODO Inventory changed awaiting DB and now we're full...could drop it on the ground? It is an off-case
}
// If the seller is online, send them a list item update
final Player sellerPlayer = Sponge.getServer().getPlayer(seller).orElse(null);
if (sellerPlayer != null) {
this.network.sendTo(sellerPlayer, new ClientboundListItemsResponsePacket(axs.getId(), listItems));
this.network.sendTo(sellerPlayer, new ClientboundListItemsSaleStatusPacket(axs.getId(), forSaleItems, null));
}
this.network.sendToAll(new ClientboundForSaleFilterRequestPacket(axs.getId()));
Sponge.getServer().getPlayer(buyer).ifPresent(buyerPlayer -> this.network.sendTo(buyerPlayer, new ClientboundTransactionCompletePacket()));
}).submit(this.container);
} catch (SQLException e) {
e.printStackTrace();
}
}).submit(this.container);
}
Aggregations