74public class TradingPost {
76 private static final Logger logger = LoggerFactory.getLogger(TradingPost.class);
78 private static final int OVERVIEW_INTERFACE_ID = 80000;
79 public static final int BUYING_PAGE_INTERFACE_ID = 80174;
80 private static final int HISTORY_PAGE_INTERFACE_ID = 80616;
81 private static final int MAX_LISTINGS_SHOWN = 50;
82 private static final int MAX_LISTING_SIZE = 20;
83 private static final int CURRENCY_ID = 995;
84 private static final int TAX_RATE = 10;
86 private final AhoCorasickDoubleArrayTrie<String> acdat =
new AhoCorasickDoubleArrayTrie<>();
91 private static final List<TradingPostListing> allListings =
new ArrayList<>();
96 private static final Map<String, Coffer> allCoffers = Collections.synchronizedMap(
new HashMap<>());
101 private List<TradingPostListing> myListings =
new ArrayList<>();
116 private TradingPostActiveListingSearch tradingPostSearch;
121 private TradingPostActiveListingSort tradingPostSort;
126 private List<TradingPostListing> searchedListings =
new ArrayList<>();
131 private List<TradingPostListing> displayedPageListings =
new ArrayList<>();
136 private static final Map<String, List<ItemHistory>> itemHistories =
new HashMap<>();
141 private static final List<ItemHistory> recentlySoldItems =
new ArrayList<>();
146 private final List<ItemHistory> playersItemHistory =
new ArrayList<>();
153 private final Player player;
155 public TradingPost(
Player player) {
156 this.player = player;
159 public void openOverviewInterface() {
161 updateExistingListingsList();
162 updateExistingListingsWidgets();
163 updateCofferAmountWidget();
164 toggleSellingOverlayVisibilityAndOpen(
true);
165 player.interfaceManager.open(OVERVIEW_INTERFACE_ID);
168 public void updateCofferAmountWidget() {
169 getOrMakeNewCofferIfNotExists(player.getName(), coffer -> {
170 player.send(new SendString(Utility.formatDigits(coffer.getAmount()), 80005));
174 public boolean handleButtonClick(
int btnId) {
175 if(!player.interfaceManager.hasAnyOpen(OVERVIEW_INTERFACE_ID, BUYING_PAGE_INTERFACE_ID,HISTORY_PAGE_INTERFACE_ID)) {
182 openOverviewInterface();
186 searchItemHistoryInput();
192 displayMostRecentListings();
195 player.dialogueFactory.sendOption(
"Search item", this::searchExistingItemInput,
"Search player", this::searchPlayerInput,
"Nevermind", () -> player.dialogueFactory.clear()).execute();
198 searchExistingItemInput();
201 openSellingOverlay();
204 sendItemHistoryData(playersItemHistory);
207 sendItemHistoryData(recentlySoldItems);
210 toggleSellingOverlayVisibilityAndOpen(
true);
222 withdrawFromCoffer();
234 if(handleBuyingButton(btnId) || handleDismissListingButton(btnId) || handleSellingOverlayButtons(btnId)) {
243 private void searchItemHistoryInput() {
244 player.send(
new SendInputMessage(
"Enter item name to search history for:", 16, input -> {
246 if(Objects.equals(input,
"")) {
247 sendItemHistoryData(recentlySoldItems);
251 List<ItemHistory> historyItems =
new ArrayList<>();
252 TreeMap<String, String> map =
new TreeMap<>();
253 map.put(input,input);
256 for(Map.Entry<String, List<ItemHistory>> lf : itemHistories.entrySet()) {
257 acdat.parseText(lf.getKey().toLowerCase(), (b,e,v) -> {
258 List<ItemHistory> temp = lf.getValue();
260 for(ItemHistory h : temp) {
261 if(!historyItems.contains(h)) {
265 if(historyItems.size() == 50) {
273 sendItemHistoryData(historyItems);
277 public void sendItemHistoryData(List<ItemHistory> itemHistories) {
278 for(
int i = 0; i < MAX_LISTINGS_SHOWN; i++) {
279 if(itemHistories.size() > i) {
283 player.send(
new SendString(ih.getSeller(),80853+i));
284 player.send(
new SendString(ih.getBuyer(),80903+i));
294 player.interfaceManager.open(HISTORY_PAGE_INTERFACE_ID);
297 private void searchExistingItemInput() {
300 protected void execute() {
301 player.send(
new SendInputMessage(
"Enter item name to search for:", 16, input -> {
302 searchExistingListing(
new TradingPostActiveListingSearch(TradingPostActiveListingSearchType.ITEM, String.valueOf(input)));
303 player.interfaceManager.open(BUYING_PAGE_INTERFACE_ID);
310 private void searchPlayerInput() {
313 protected void execute() {
314 player.send(
new SendInputMessage(
"Enter player name to search for:", 16, input -> {
315 searchExistingListing(
new TradingPostActiveListingSearch(TradingPostActiveListingSearchType.PLAYER, String.valueOf(input)));
316 player.interfaceManager.open(BUYING_PAGE_INTERFACE_ID);
323 private void sort() {
324 if(displayedPageListings ==
null)
return;
325 if(tradingPostSort ==
null)
return;
329 searchedListings = searchedListings
331 .sorted(Comparator.comparingInt(
332 (tradingPostSort.postSortType == TradingPostSortType.HIGHEST_PRICE || tradingPostSort.postSortType == TradingPostSortType.LOWEST_PRICE)
333 ? TradingPostListing::getPrice
334 : TradingPostListing::getAmountLeft))
335 .collect(Collectors.toList());
338 if(tradingPostSort.postSortType == TradingPostSortType.HIGHEST_QUANTITY || tradingPostSort.postSortType == TradingPostSortType.HIGHEST_PRICE) {
339 Collections.reverse(searchedListings);
342 updateBuyingPageWidgets(getPageListings(searchedListings));
345 private void sortPrice() {
346 tradingPostSort = tradingPostSort !=
null ? tradingPostSort.setPostSortType(
347 tradingPostSort.postSortType == TradingPostSortType.HIGHEST_PRICE
348 ? TradingPostSortType.LOWEST_PRICE
349 : TradingPostSortType.HIGHEST_PRICE
350 ) :
new TradingPostActiveListingSort(TradingPostSortType.LOWEST_PRICE);
355 public void sortQuantity() {
356 tradingPostSort = tradingPostSort !=
null ? tradingPostSort.setPostSortType(
357 tradingPostSort.postSortType == TradingPostSortType.HIGHEST_QUANTITY
358 ? TradingPostSortType.LOWEST_QUANTITY
359 : TradingPostSortType.HIGHEST_QUANTITY
360 ) :
new TradingPostActiveListingSort(TradingPostSortType.HIGHEST_QUANTITY);
366 private void withdrawFromCoffer() {
367 getOrMakeNewCofferIfNotExists(player.getName(), coffer -> {
368 if (coffer.getAmount() == 0) {
372 player.send(
new SendInputAmount(
"How much gold would you like to withdraw?", 10, input -> {
373 int amount = Integer.parseInt(input);
375 if (amount > coffer.getAmount()) {
376 amount = (int) coffer.getAmount();
379 if (amount > coffer.getAmount()) {
383 if (player.inventory.add(CURRENCY_ID, amount)) {
384 coffer.subtractAmount(amount);
385 updateCofferAmountWidget();
388 player.send(
new SendMessage(
"You do not have enough inventory spaces to withdraw this gold"));
395 private void refresh() {
396 if(tradingPostSearch !=
null) {
397 addSearchResultsAndUpdateInterface(tradingPostSearch);
399 displayMostRecentListings();
403 private void nextPage() {
405 List<TradingPostListing> temp;
406 temp = getPageListings(searchedListings);
409 player.send(
new SendMessage(
"No more results on the next page"));
411 updateBuyingPageWidgets(temp);
415 private void previousPage() {
416 if(page == 0)
return;
418 updateBuyingPageWidgets(getPageListings(searchedListings));
421 private boolean handleSellingOverlayButtons(
int btnId) {
422 if(listingToAdd ==
null)
return false;
426 listingToAdd.addQuantity(player,1);
429 listingToAdd.removeQuantity(player,1);
432 editQuantityInputPrompt();
435 editPriceInputPrompt();
438 confirmToAddListing();
445 private void displayMostRecentListings() {
446 if(!player.interfaceManager.isInterfaceOpen(BUYING_PAGE_INTERFACE_ID)) {
447 player.interfaceManager.open(BUYING_PAGE_INTERFACE_ID);
449 player.send(
new SendString(
"Search: Most recent",80176));
451 tradingPostSearch =
new TradingPostActiveListingSearch(TradingPostActiveListingSearchType.MOST_RECENT,
"");
452 addSearchResultsAndUpdateInterface(tradingPostSearch);
455 private void searchExistingListing(TradingPostActiveListingSearch search) {
456 if(search.text.length() == 0) {
458 displayMostRecentListings();
461 tradingPostSearch = search;
463 addSearchResultsAndUpdateInterface(search);
464 player.send(
new SendString(
"Search: " + tradingPostSearch.text,80176));
467 public void addSearchResultsAndUpdateInterface(TradingPostActiveListingSearch search) {
468 searchedListings.clear();
469 searchedListings.addAll(getSearchResults(search.searchType,search.text));
470 updateBuyingPageWidgets(getPageListings(searchedListings));
473 private List<TradingPostListing> getSearchResults(TradingPostActiveListingSearchType type, String search) {
474 if(type == TradingPostActiveListingSearchType.MOST_RECENT) {
475 return Lists.reverse(allListings);
477 List<TradingPostListing> temp =
new ArrayList<>();
478 TreeMap<String, String> map =
new TreeMap<>();
479 map.put(search,search);
480 tradingPostSearch.acdat.build(map);
481 for(TradingPostListing listing : allListings) {
482 tradingPostSearch.acdat.parseText(type == TradingPostActiveListingSearchType.ITEM ? ItemDefinition.get(listing.getItemId()).getName().toLowerCase() : listing.getSeller().toLowerCase(), (begin, end, value) -> {
483 if(!temp.contains(listing)) {
491 private List<TradingPostListing> getPageListings(List<TradingPostListing> listings) {
492 return listings.subList(
493 Math.min(listings.size(), page * MAX_LISTINGS_SHOWN),
494 Math.min(listings.size(), (page * MAX_LISTINGS_SHOWN + MAX_LISTINGS_SHOWN))).
496 .filter(tradingPostListing -> !tradingPostListing.getSeller().equalsIgnoreCase(player.getName()))
497 .limit(MAX_LISTINGS_SHOWN)
498 .collect(Collectors.toList());
501 private void updateBuyingPageWidgets(List<TradingPostListing> listings) {
502 displayedPageListings = listings;
504 for(
int i = 0; i < MAX_LISTINGS_SHOWN; i++) {
505 if(displayedPageListings.size() > i) {
506 TradingPostListing listing = displayedPageListings.get(i);
507 player.send(
new SendString(ItemDefinition.get(listing.getItemId()).getName(),80214+i));
510 player.send(
new SendString(listing.getSeller(),80364+i));
511 toggleBuyingPageWidgetVisibility(i,
false);
513 toggleBuyingPageWidgetVisibility(i,
true);
517 player.send(
new SendString(
"Page: " + (page+1),80615));
518 player.send(
new SendItemOnInterface(80614, getItemArrayFromActiveListings(displayedPageListings)));
519 player.send(
new SendScrollbar(80211, Math.max(238, displayedPageListings.size()*34)));
522 private void toggleBuyingPageWidgetVisibility(
int i,
boolean isHidden) {
532 private void toggleSellingOverlayVisibilityAndOpen(
boolean isHidden) {
534 player.interfaceManager.close();
536 player.interfaceManager.open(OVERVIEW_INTERFACE_ID);
540 private int getSlotSizeByDonatorRank() {
541 switch (player.right) {
542 case KING_DONATOR -> {
543 return MAX_LISTING_SIZE;
545 case ELITE_DONATOR -> {
549 case EXTREME_DONATOR -> {
552 case SUPER_DONATOR -> {
564 private void openSellingOverlay() {
565 clearSellingOverlay();
566 toggleSellingOverlayVisibilityAndOpen(
false);
572 public void selectItemToList(Item item) {
573 if(!item.isTradeable() || item.getId() == 995) {
574 player.send(
new SendMessage(
"You cannot list this item."));
577 listingToAdd =
new TradingPostListing(item.getId(), player.getName());
579 player.send(
new SendString(item.getDefinition().getName(),80160));
580 updatePriceStrings();
581 updateQuantityString();
584 public void updatePriceStrings() {
585 if(listingToAdd ==
null)
return;
590 public void updateQuantityString() {
591 if(listingToAdd ==
null)
return;
592 player.send(
new SendString(
"Quantity: @gre@" + listingToAdd.getInitialQuantity(), 80162));
593 player.send(
new SendString(listingToAdd.getInitialQuantity(), 80173));
596 private void clearSellingOverlay() {
605 private void editQuantityInputPrompt() {
606 player.send(
new SendInputAmount(
"How many would you like to sell?", 10, input -> listingToAdd.setQuantity(player,Integer.parseInt(input))));
609 private void editPriceInputPrompt() {
610 player.send(
new SendInputAmount(
"How much would you like sell this for?", 10, input -> listingToAdd.setPrice(player, Integer.parseInt(input))));
613 private void confirmToAddListing() {
614 if(listingToAdd.getPrice() == 0) {
615 player.send(
new SendMessage(
"Unable to add listing with a price of zero."));
618 if(myListings.size() > getSlotSizeByDonatorRank()) {
619 player.send(
new SendMessage(
"Unable to add listing with max number listings listed."));
623 if(player.inventory.remove(listingToAdd.getItemId(), listingToAdd.getInitialQuantity())) {
624 allListings.add(listingToAdd);
625 updateExistingListingsList();
626 openSellingOverlay();
627 updateExistingListingsWidgets();
628 saveListings(player.getName(),getListingsByName(player.getName()));
630 player.send(
new SendMessage(
"Unable to list this item. Please try again."));
634 private void updateExistingListingsList() {
635 myListings = getListingsByName(player.getName());
638 private List<TradingPostListing> getListingsByName(String name) {
641 .filter(tradingPostListing -> tradingPostListing.getSeller().equals(name))
642 .collect(Collectors.toList());
645 private Item[] getItemArrayFromActiveListings(List<TradingPostListing> list) {
648 .map(tradingPostListing ->
new Item(ItemDefinition.get(tradingPostListing.getItemId()).isNoted()
649 ? ItemDefinition.get(tradingPostListing.getItemId()).getUnnotedId()
650 : tradingPostListing.getItemId(), tradingPostListing.getAmountLeft()))
651 .toArray(Item[]::new);
654 private Item[] getItemArrayFromItemHistory(List<ItemHistory> list) {
657 .map(ih ->
new Item(ItemDefinition.get(ih.getItemId()).isNoted()
658 ? ItemDefinition.get(ih.getItemId()).getUnnotedId()
659 : ih.getItemId(), ih.getQuantity()))
660 .toArray(Item[]::new);
663 private void updateExistingListingsWidgets() {
666 for(
int i = 0; i < MAX_LISTING_SIZE; i++) {
667 if(myListings.size() > i) {
668 TradingPostListing tradingPostListing = myListings.get(i);
669 sendOverviewWidgetVisibility(i,
false);
670 player.send(
new SendString(tradingPostListing.getAmountSold() +
"/" + tradingPostListing.getInitialQuantity(), 80112+i));
671 player.send(
new SendProgressBar(80032+i, ((tradingPostListing.getAmountSold() * 100) / tradingPostListing.getInitialQuantity())));
673 sendOverviewWidgetVisibility(i,
true);
677 player.send(
new SendScrollbar(80029, Math.max(38*myListings.size(), 157)));
680 private void sendOverviewWidgetVisibility(
int i,
boolean isHidden) {
688 private boolean handleBuyingButton(
int btnId) {
689 if(btnId >= 14878 && btnId <= 14927) {
690 int index = btnId - 14878;
692 if(displayedPageListings.size() < index) {
696 TradingPostListing temp = displayedPageListings.get(index);
702 if(!allListings.contains(temp)) {
708 if(listingToBuy.getAmountLeft() > 1) {
709 player.send(
new SendInputAmount(
"How many of " + ItemDefinition.get(listingToBuy.getItemId()).getName() +
"?", 10, input -> buyingDialogueOptions(Integer.parseInt(input))));
711 buyingDialogueOptions(1);
718 public void buyingDialogueOptions(
int amount) {
719 if((
long)amount + listingToBuy.getPrice() > Integer.MAX_VALUE) {
720 player.send(
new SendMessage(
"Cannot buy this quantity for this price."));
724 if(amount > listingToBuy.getAmountLeft()) {
725 amount = listingToBuy.getAmountLeft();
728 int finalAmount = amount;
729 player.dialogueFactory.sendStatement(
"Purchase " + amount +
" of " + ItemDefinition.get(listingToBuy.getItemId()).getName(),
730 "for <col=A52929>" +
Utility.
formatDigits(listingToBuy.getPrice()*amount) +
" " + ItemDefinition.get(CURRENCY_ID).getName() +
"?")
731 .sendOption(
"Yes", () -> purchase(finalAmount),
"Nevermind", () -> player.dialogueFactory.clear()).execute();
734 private void alertSeller(String sellerName, String item,
int amount) {
735 Optional<Player> playerOptional =
World.
search(sellerName);
737 if(playerOptional.isPresent()) {
738 Player player = playerOptional.get();
740 player.send(
new SendMessage(
"@red@Trading post: " + amount +
" of your " + item +
"s have been sold"));
742 player.tradingPost.updateExistingListingsList();
744 if(player.interfaceManager.hasAnyOpen(OVERVIEW_INTERFACE_ID)) {
745 player.tradingPost.openOverviewInterface();
750 private void purchase(
int amount) {
751 if(listingToBuy ==
null) {
756 int totalPrice = listingToBuy.getPrice()*amount;
758 if(totalPrice > getPlayerCurrencyAmount) {
759 player.send(
new SendMessage(
"Insufficient " + ItemDefinition.get(CURRENCY_ID).getName() +
" to complete your transaction."));
763 if(amount > listingToBuy.getAmountLeft()) {
764 amount = listingToBuy.getAmountLeft();
765 player.send(
new SendMessage(
"Your purchase amount has been lowered to " + amount));
768 if(!allListings.contains(listingToBuy)) {
769 player.send(
new SendMessage(
"This item does not exist in the trading post anymore."));
773 if(player.inventory.
add(listingToBuy.getItemId(), amount)) {
774 player.inventory.
remove(CURRENCY_ID,totalPrice);
775 listingToBuy.addToAmountSold(amount);
777 if(listingToBuy.getAmountLeft() == 0) {
778 allListings.remove(listingToBuy);
779 displayedPageListings.remove(listingToBuy);
780 searchedListings.remove(listingToBuy);
783 if(tradingPostSearch !=
null) {
784 addSearchResultsAndUpdateInterface(tradingPostSearch);
786 displayMostRecentListings();
789 addToCoffer(listingToBuy.getSeller(),listingToBuy.getPrice()*amount);
790 alertSeller(listingToBuy.getSeller(),ItemDefinition.get(listingToBuy.getItemId()).getName(), amount);
792 String seller = listingToBuy.getSeller();
793 saveListings(seller,getListingsByName(seller));
795 addToItemHistory(
new ItemHistory(amount, listingToBuy.getItemId(), listingToBuy.getPrice()*amount, listingToBuy.getSeller(), player.
getName()));
798 player.send(
new SendMessage(
"You do not have enough inventory spaces to complete this transaction"));
803 public void addToItemHistory(ItemHistory itemHistory) {
804 List<ItemHistory> itemHistoryList = itemHistories.computeIfAbsent(ItemDefinition.get(itemHistory.getItemId()).getName(), x ->
new ArrayList<>());
806 if(itemHistoryList.size() == 50) {
807 itemHistoryList.remove(49);
810 itemHistoryList.add(itemHistory);
812 if(recentlySoldItems.size() == 50) {
813 recentlySoldItems.remove(49);
816 recentlySoldItems.add(itemHistory);
818 if(playersItemHistory.size() == 50) {
819 playersItemHistory.remove(49);
822 playersItemHistory.add(itemHistory);
825 public void addToCoffer(String owner,
int amount) {
826 getOrMakeNewCofferIfNotExists(owner, coffer -> {
827 coffer.addAmount((
int) (amount - (TAX_RATE/100.0*amount)));
832 public void getOrMakeNewCofferIfNotExists(
final String owner,
833 final Consumer<Coffer> useCoffer) {
834 getCoffer(owner).thenAccept(coffer -> {
835 if (coffer ==
null) {
836 coffer = allCoffers.compute(owner, (k, v) ->
new Coffer(owner));
840 useCoffer.accept(coffer);
844 private boolean handleDismissListingButton(
int btnId) {
845 if(btnId >= 14516 && btnId <= 14535) {
846 int index = btnId - 14516;
848 if(myListings.isEmpty()) {
852 if(myListings.size() < index) {
856 TradingPostListing listing = myListings.get(index);
858 if(!delist(listing)) {
859 player.send(
new SendMessage(
"Unable to delist this item. Please try again."));
861 saveListings(player.
getName(),getListingsByName(player.
getName()));
862 player.inventory.
addOrBank(
new Item(listing.getItemId(),listing.getAmountLeft()));
863 openOverviewInterface();
872 public boolean delist(TradingPostListing listing) {
873 if(myListings.isEmpty()) {
877 if(!myListings.contains(listing)) {
881 if(!allListings.contains(listing)) {
885 return allListings.remove(listing) && myListings.remove(listing);
888 public void cleanUp() {
889 displayedPageListings.clear();
890 searchedListings.clear();
891 tradingPostSearch =
null;
892 tradingPostSort =
null;
898 public void testData() {
900 for(
int i = 0; i < 1000; i++) {
901 ItemDefinition def = ItemDefinition.DEFINITIONS[
new Random().nextInt(ItemDefinition.DEFINITIONS.length)];
903 TradingPostListing listing =
new TradingPostListing(def.getId(),
"John"+i);
904 listing.setInitialQuantity(i+1);
905 listing.setPrice(i+1);
906 allListings.add(listing);
908 System.out.println(
"Adding listing: " + addCounter);
913 public void saveCoffer(
final Coffer coffer) {
914 Thread.startVirtualThread(() -> {
916 final String json = GsonUtils.JSON_PRETTY_ALLOW_NULL.get().toJson(coffer);
918 final Path path = Path.of(
"./data/profile/save/tradingpost/coffers/", coffer.getOwner(),
".json");
919 Path parent = path.getParent();
920 if (parent ==
null) {
921 throw new UnsupportedOperationException(
"Path must have a parent " + path);
923 if (!Files.exists(parent)) {
924 parent = Files.createDirectories(parent);
927 final Path tempFile = Files.createTempFile(parent, path.getFileName().toString(),
".tmp");
928 Files.writeString(tempFile, json, StandardCharsets.UTF_8);
930 Files.move(tempFile, path, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
931 }
catch (
final Exception ex) {
932 logger.error(String.format(
"Error while saving player=%s", player.
getName()), ex);
937 public CompletableFuture<Coffer> getCoffer(
final String owner) {
938 final Coffer cachedCoffer = allCoffers.get(owner);
939 if (cachedCoffer !=
null) {
940 return CompletableFuture.completedFuture(cachedCoffer);
944 return CompletableFuture.supplyAsync(() -> {
945 final Path path = Path.of(
"./data/profile/save/tradingpost/coffers/", owner,
".json");
946 if (!Files.exists(path)) {
950 final Gson gson = GsonUtils.JSON_ALLOW_NULL.get();
951 try (
final BufferedReader reader = Files.newBufferedReader(path)) {
952 final Coffer coffer = gson.fromJson(reader, Coffer.class);
953 if (coffer !=
null) {
954 allCoffers.put(coffer.getOwner(), coffer);
957 }
catch (
final IOException e) {
958 logger.error(
"Failed reading coffer for \"" + owner +
"\"", e);
964 public void saveListings(
final String owner,
final List<TradingPostListing> listings) {
965 Thread.startVirtualThread(() -> {
967 final String json = GsonUtils.JSON_PRETTY_ALLOW_NULL.get().toJson(listings);
969 final Path path = Path.of(
"./data/profile/save/tradingpost/listings/", owner,
".json");
970 Path parent = path.getParent();
971 if (parent ==
null) {
972 throw new UnsupportedOperationException(
"Path must have a parent " + path);
974 if (!Files.exists(parent)) {
975 parent = Files.createDirectories(parent);
978 final Path tempFile = Files.createTempFile(parent, path.getFileName().toString(),
".tmp");
979 Files.writeString(tempFile, json, StandardCharsets.UTF_8);
981 Files.move(tempFile, path, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
983 }
catch (
final Exception ex) {
984 logger.error(String.format(
"Error while saving player=%s", player.
getName()), ex);
989 public static void loadAllListings() {
991 File folder =
new File(
"./data/profile/save/tradingpost/listings/");
992 File[] files = folder.listFiles();
993 if (files ==
null)
return;
994 for(File f : files) {
996 if(f.isDirectory()) {
997 toRead = Objects.requireNonNull(f.getAbsoluteFile().listFiles())[0];
1000 assert toRead !=
null;
1001 final Gson gson = GsonUtils.JSON_ALLOW_NULL.get();
1002 try (
final BufferedReader reader = Files.newBufferedReader(Path.of(toRead.getPath()))) {
1003 final List<TradingPostListing> listings = List.of(gson.fromJson(reader, TradingPostListing[].class));
1004 allListings.addAll(listings);
1005 }
catch (
final IOException e) {
1006 logger.error(
"Failed reading listings", e);
1008 }
catch (Exception e) {
1009 e.printStackTrace();
1012 }
catch (Exception e) {
1013 e.printStackTrace();
1017 public static void saveAllItemHistory() {
1018 Path path = Paths.get(
"./data/profile/save/tradingpost/itemhistory.json");
1019 File file = path.toFile();
1020 file.getParentFile().setWritable(
true);
1022 if(!file.getParentFile().exists()) {
1024 file.getParentFile().mkdirs();
1025 }
catch (SecurityException e) {
1026 System.out.println(
"Error while creating item history directory");
1029 try(FileWriter writer =
new FileWriter(file)) {
1030 Gson builder =
new GsonBuilder().setPrettyPrinting().create();
1031 JsonObject
object =
new JsonObject();
1032 object.add(
"itemhistory",builder.toJsonTree(itemHistories));
1033 writer.write(builder.toJson(
object));
1034 }
catch (Exception e) {
1035 e.printStackTrace();
1039 public static void saveRecentHistory() {
1040 Path path = Paths.get(
"./data/profile/save/tradingpost/itemhistoryrecent.json");
1041 File file = path.toFile();
1042 file.getParentFile().setWritable(
true);
1044 if(!file.getParentFile().exists()) {
1046 file.getParentFile().mkdirs();
1047 }
catch (SecurityException e) {
1048 System.out.println(
"Error while creating recent item history directory");
1051 try(FileWriter writer =
new FileWriter(file)) {
1052 Gson builder =
new GsonBuilder().setPrettyPrinting().create();
1053 JsonObject
object =
new JsonObject();
1054 object.add(
"recentitemhistory",builder.toJsonTree(recentlySoldItems));
1055 writer.write(builder.toJson(
object));
1056 }
catch (Exception e) {
1057 e.printStackTrace();
1061 public static void loadItemHistory() {
1062 Path path = Paths.get(
"./data/profile/save/tradingpost/itemhistory.json");
1063 File file = path.toFile();
1065 createFileAndDirIfNotExists(file);
1066 if(file.length() == 0)
return;
1068 try (FileReader fileReader =
new FileReader(file)) {
1069 JsonParser fileParser =
new JsonParser();
1070 Gson builder =
new GsonBuilder()
1072 JsonObject reader = (JsonObject) fileParser.parse(fileReader);
1074 HashMap<String, List<ItemHistory>> itemHistory = builder.fromJson(reader.get(
"itemhistory"),
1075 new TypeToken<HashMap<String, List<ItemHistory>>>() {
1077 itemHistories.putAll(itemHistory);
1078 }
catch (Exception e) {
1079 e.printStackTrace();
1083 public static void loadRecentItemHistory() {
1084 Path path = Paths.get(
"./data/profile/save/tradingpost/itemhistoryrecent.json");
1085 File file = path.toFile();
1087 createFileAndDirIfNotExists(file);
1088 if(file.length() == 0)
return;
1090 try (FileReader fileReader =
new FileReader(file)) {
1091 JsonParser fileParser =
new JsonParser();
1092 Gson builder =
new GsonBuilder()
1094 JsonObject reader = (JsonObject) fileParser.parse(fileReader);
1095 ItemHistory[] temp = builder.fromJson(reader.get(
"recentitemhistory").getAsJsonArray(), ItemHistory[].class);
1096 recentlySoldItems.addAll(Arrays.asList(temp));
1097 }
catch (Exception e) {
1098 e.printStackTrace();
1102 public static void createFileAndDirIfNotExists(File file) {
1103 if (!file.getParentFile().exists() || !file.exists()) {
1105 file.getParentFile().mkdirs();
1106 file.createNewFile();
1107 }
catch (SecurityException e) {
1108 System.out.println(
"Unable to create directory");
1109 }
catch (IOException e) {
1110 throw new RuntimeException(e);
1115 public List<ItemHistory> getPlayersItemHistory() {
1116 return playersItemHistory;
1120 static class TradingPostActiveListingSearch {
1121 private final TradingPostActiveListingSearchType searchType;
1122 private final String text;
1123 private final AhoCorasickDoubleArrayTrie<String> acdat =
new AhoCorasickDoubleArrayTrie<>();
1125 TradingPostActiveListingSearch(TradingPostActiveListingSearchType searchType, String text) {
1126 this.searchType = searchType;
1127 this.text = text.toLowerCase();
1131enum TradingPostActiveListingSearchType {
1137 static class TradingPostActiveListingSort {
1138 TradingPostSortType postSortType;
1140 public TradingPostActiveListingSort(TradingPostSortType postSortType) {
1141 this.postSortType = postSortType;
1144 public TradingPostSortType getPostSortType() {
1145 return postSortType;
1148 public TradingPostActiveListingSort setPostSortType(TradingPostSortType postSortType) {
1149 this.postSortType = postSortType;
1154 enum TradingPostSortType {