Search in sources :

Example 1 with ClientboundTransactionCompletePacket

use of com.almuradev.almura.feature.exchange.network.ClientboundTransactionCompletePacket 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);
}
Also used : UniqueAccount(org.spongepowered.api.service.economy.account.UniqueAccount) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) ClientboundListItemsResponsePacket(com.almuradev.almura.feature.exchange.network.ClientboundListItemsResponsePacket) EconomyService(org.spongepowered.api.service.economy.EconomyService) BasicForSaleItem(com.almuradev.almura.feature.exchange.basic.listing.BasicForSaleItem) AxsForSaleItem(com.almuradev.generated.axs.tables.AxsForSaleItem) ForSaleItem(com.almuradev.almura.feature.exchange.listing.ForSaleItem) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ClientboundListItemsSaleStatusPacket(com.almuradev.almura.feature.exchange.network.ClientboundListItemsSaleStatusPacket) List(java.util.List) ArrayList(java.util.ArrayList) UUID(java.util.UUID) ClientboundTransactionCompletePacket(com.almuradev.almura.feature.exchange.network.ClientboundTransactionCompletePacket) Player(org.spongepowered.api.entity.living.player.Player) IItemHandler(net.minecraftforge.items.IItemHandler) DSLContext(org.jooq.DSLContext) BigDecimal(java.math.BigDecimal) BasicExchange(com.almuradev.almura.feature.exchange.basic.BasicExchange) Results(org.jooq.Results) ClientboundForSaleFilterRequestPacket(com.almuradev.almura.feature.exchange.network.ClientboundForSaleFilterRequestPacket) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) AxsListItem(com.almuradev.generated.axs.tables.AxsListItem) BasicListItem(com.almuradev.almura.feature.exchange.basic.listing.BasicListItem) ListItem(com.almuradev.almura.feature.exchange.listing.ListItem) ItemStack(net.minecraft.item.ItemStack) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

BasicExchange (com.almuradev.almura.feature.exchange.basic.BasicExchange)1 BasicForSaleItem (com.almuradev.almura.feature.exchange.basic.listing.BasicForSaleItem)1 BasicListItem (com.almuradev.almura.feature.exchange.basic.listing.BasicListItem)1 ForSaleItem (com.almuradev.almura.feature.exchange.listing.ForSaleItem)1 ListItem (com.almuradev.almura.feature.exchange.listing.ListItem)1 ClientboundForSaleFilterRequestPacket (com.almuradev.almura.feature.exchange.network.ClientboundForSaleFilterRequestPacket)1 ClientboundListItemsResponsePacket (com.almuradev.almura.feature.exchange.network.ClientboundListItemsResponsePacket)1 ClientboundListItemsSaleStatusPacket (com.almuradev.almura.feature.exchange.network.ClientboundListItemsSaleStatusPacket)1 ClientboundTransactionCompletePacket (com.almuradev.almura.feature.exchange.network.ClientboundTransactionCompletePacket)1 AxsForSaleItem (com.almuradev.generated.axs.tables.AxsForSaleItem)1 AxsListItem (com.almuradev.generated.axs.tables.AxsListItem)1 BigDecimal (java.math.BigDecimal)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 UUID (java.util.UUID)1 EntityPlayerMP (net.minecraft.entity.player.EntityPlayerMP)1 ItemStack (net.minecraft.item.ItemStack)1