use of com.almuradev.almura.feature.exchange.listing.ForSaleItem in project Almura by AlmuraDev.
the class ServerExchangeManager method handleForSaleFilter.
public void handleForSaleFilter(final Player player, final String id, @Nullable final String filter, @Nullable final String sorter, final int skip, final int limit) {
checkNotNull(player);
checkNotNull(id);
checkState(skip >= 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 filter for sale items for exchange '{}' but the server has no knowledge of it. Syncing " + "exchange registry...", player.getName(), id);
this.syncExchangeRegistryTo(player);
return;
}
Stream<ForSaleItem> stream = axs.getForSaleItems().values().stream().flatMap(List::stream);
if (filter != null) {
final List<FilterRegistry.FilterElement<ListItem>> elements = FilterRegistry.instance.getFilterElements(filter);
stream = stream.filter(forSaleItem -> elements.stream().allMatch(element -> element.getFilter().test(forSaleItem.getListItem(), element.getValue())));
}
if (sorter != null) {
final List<FilterRegistry.SorterElement<ListItem>> elements = FilterRegistry.instance.getSortingElements(sorter);
final Comparator<ListItem> comparator = FilterRegistry.instance.buildSortingComparator(elements).orElse(null);
if (comparator != null) {
stream = stream.map(ForSaleItem::getListItem).sorted(comparator).map(k -> k.getForSaleItem().orElse(null));
}
}
final List<ForSaleItem> result = stream.collect(Collectors.toList());
final Stream<ForSaleItem> adjustedStream = result.stream().skip(skip);
final List<ForSaleItem> limitedResult;
if (limit > -1) {
limitedResult = adjustedStream.limit(limit).collect(Collectors.toList());
} else {
limitedResult = adjustedStream.collect(Collectors.toList());
}
this.network.sendTo(player, new ClientboundForSaleItemsResponsePacket(axs.getId(), limitedResult, result.size()));
}
use of com.almuradev.almura.feature.exchange.listing.ForSaleItem in project Almura by AlmuraDev.
the class ServerExchangeManager method loadForSaleItems.
/**
* ForSaleItem
*/
private void loadForSaleItems(final Exchange axs) {
checkNotNull(axs);
this.logger.info("Querying for sale items for exchange '{}' ({}), please wait...", axs.getName(), axs.getId());
final List<ForSaleItem> forSaleItems = new ArrayList<>();
final List<ListItem> listItems = axs.getListItems().entrySet().stream().map(Map.Entry::getValue).flatMap(List::stream).collect(Collectors.toList());
try (final DSLContext context = this.databaseManager.createContext(true)) {
final Results results = ExchangeQueries.createFetchForSaleItemsFor(axs.getId(), false).build(context).keepStatement(false).fetchMany();
results.forEach(result -> forSaleItems.addAll(this.parseForSaleItemsFrom(listItems, result)));
axs.clearForSaleItems();
axs.putForSaleItems(forSaleItems.isEmpty() ? null : forSaleItems.stream().collect(Collectors.groupingBy(forSaleItem -> forSaleItem.getListItem().getSeller())));
this.logger.info("Loaded [{}] for sale item(s) for exchange '{}' ({}).", forSaleItems.size(), axs.getName(), axs.getId());
} catch (SQLException e) {
e.printStackTrace();
}
}
use of com.almuradev.almura.feature.exchange.listing.ForSaleItem 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);
}
use of com.almuradev.almura.feature.exchange.listing.ForSaleItem in project Almura by AlmuraDev.
the class ExchangeModule method configure.
@Override
protected void configure() {
this.requestStaticInjection(ExchangeCommandsCreator.class);
this.packet().bind(ClientboundExchangeRegistryPacket.class, binder -> binder.handler(ClientboundExchangesRegistryPacketHandler.class, Platform.Type.CLIENT)).bind(ServerboundExchangeSpecificOfferRequestPacket.class, binder -> binder.handler(ServerboundExchangeSpecificOfferPacketHandler.class, Platform.Type.SERVER)).bind(ClientboundExchangeGuiResponsePacket.class, binder -> binder.handler(ClientboundExchangeGuiResponsePacketHandler.class, Platform.Type.CLIENT)).bind(ServerboundModifyExchangePacket.class, binder -> binder.handler(ServerboundModifyExchangePacketHandler.class, Platform.Type.SERVER)).bind(ClientboundListItemsResponsePacket.class, binder -> binder.handler(ClientboundListItemsResponsePacketHandler.class, Platform.Type.CLIENT)).bind(ClientboundListItemsSaleStatusPacket.class, binder -> binder.handler(ClientboundListItemsSaleStatusPacketHandler.class, Platform.Type.CLIENT)).bind(ServerboundListItemsRequestPacket.class, binder -> binder.handler(ServerboundListItemsRequestPacketHandler.class, Platform.Type.SERVER)).bind(ClientboundForSaleFilterRequestPacket.class, binder -> binder.handler(ClientboundForSaleFilterRequestPacketHandler.class, Platform.Type.CLIENT)).bind(ServerboundForSaleFilterResponsePacket.class, binder -> binder.handler(ServerboundForSaleFilterResponsePacketHandler.class, Platform.Type.SERVER)).bind(ClientboundForSaleItemsResponsePacket.class, binder -> binder.handler(ClientboundForSaleItemsResponsePacketHandler.class, Platform.Type.CLIENT)).bind(ServerboundModifyForSaleItemListStatusRequestPacket.class, binder -> binder.handler(ServerboundModifyForSaleItemListStatusRequestPacketHandler.class, Platform.Type.SERVER)).bind(ServerboundTransactionRequestPacket.class, binder -> binder.handler(ServerboundTransactionRequestPacketHandler.class, Platform.Type.SERVER)).bind(ClientboundTransactionCompletePacket.class, binder -> binder.handler(ClientboundTransactionCompletePacketHandler.class, Platform.Type.CLIENT));
this.facet().add(ServerExchangeManager.class);
this.command().child(ExchangeCommandsCreator.createCommand(), "exchange", "axs");
FilterRegistry.instance.<ListItem>registerFilter(ID + "_item_display_name", (target, value) -> target.asRealStack().getDisplayName().toLowerCase().contains(value.toLowerCase())).<ListItem>registerFilter(ID + "_seller_name", (target, value) -> target.getSellerName().isPresent() && target.getSellerName().get().toLowerCase().contains(value.toLowerCase())).<ListItem>registerComparator(ID + "_item_display_name", Comparator.comparing(k -> k.asRealStack().getDisplayName().toLowerCase())).<ListItem>registerComparator(ID + "_seller_name", Comparator.comparing(v -> v.getSellerName().orElse("").toLowerCase())).<ListItem>registerComparator(ID + "_price", Comparator.comparing(l -> {
final ForSaleItem item = l.getForSaleItem().orElse(null);
if (item == null) {
return null;
}
return item.getPrice();
})).<ListItem>registerComparator(ID + "_created", Comparator.comparing(l -> {
final ForSaleItem item = l.getForSaleItem().orElse(null);
if (item == null) {
return null;
}
return item.getCreated();
}));
this.on(Platform.Type.CLIENT, () -> {
@SideOnly(Side.CLIENT)
final class ClientModule extends AbstractModule implements ClientBinder {
@SideOnly(Side.CLIENT)
@Override
protected void configure() {
this.facet().add(ClientExchangeManager.class);
this.requestStaticInjection(ExchangeBuyQuantityScreen.class);
this.requestStaticInjection(ExchangeListPriceScreen.class);
this.requestStaticInjection(ExchangeOfferScreen.class);
this.requestStaticInjection(ExchangeManagementScreen.class);
this.requestStaticInjection(ExchangeScreen.class);
}
}
this.install(new ClientModule());
});
}
use of com.almuradev.almura.feature.exchange.listing.ForSaleItem in project Almura by AlmuraDev.
the class ClientboundForSaleItemsResponsePacket method readFrom.
@Override
public void readFrom(final ChannelBuf buf) {
this.id = buf.readString();
final int count = buf.readInteger();
if (count > 0) {
this.forSaleItems = new ArrayList<>();
for (int i = 0; i < count; i++) {
final int listItemRecNo = buf.readInteger();
final ResourceLocation location = new ResourceLocation(buf.readString(), buf.readString());
final Item item = ForgeRegistries.ITEMS.getValue(location);
if (item == null) {
new IOException("Unknown item id when receiving for sale item! Id [" + location + "]. Skipping...").printStackTrace();
continue;
}
final int quantity = buf.readInteger();
final int metadata = buf.readInteger();
final Instant listItemCreated;
try {
listItemCreated = SerializationUtil.bytesToObject(buf.readBytes(buf.readInteger()));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
continue;
}
final UUID seller = buf.readUniqueId();
final String sellerName = buf.readBoolean() ? buf.readString() : null;
final int index = buf.readInteger();
BigDecimal lastKnownPrice = null;
if (buf.readBoolean()) {
lastKnownPrice = ByteBufUtil.readBigDecimal((ByteBuf) buf);
}
final int compoundDataLength = buf.readInteger();
NBTTagCompound compound = null;
if (compoundDataLength > 0) {
try {
compound = SerializationUtil.compoundFromBytes(buf.readBytes(compoundDataLength));
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
final BasicListItem basicListItem = new BasicListItem(listItemRecNo, listItemCreated, seller, item, quantity, metadata, index, lastKnownPrice, compound);
if (Sponge.getPlatform().getExecutionType().isClient()) {
basicListItem.setSellerName(sellerName);
}
final int forSaleItemRecNo = buf.readInteger();
// ForSaleItem
final Instant forSaleItemCreated;
try {
forSaleItemCreated = SerializationUtil.bytesToObject(buf.readBytes(buf.readInteger()));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
continue;
}
final BigDecimal price = ByteBufUtil.readBigDecimal((ByteBuf) buf);
final BasicForSaleItem basicForSaleItem = new BasicForSaleItem(basicListItem, forSaleItemRecNo, forSaleItemCreated, price);
this.forSaleItems.add(basicForSaleItem);
}
}
this.preLimitCount = buf.readInteger();
}
Aggregations