GrzybcioRynek

MarketManager

Wystawianie, zakup ze stanami transakcji, usuwanie ofert, refund i rezerwacje.

Kompatybilne z: GrzybcioRynek 1.0.3Minecraft 26.2Web 0.1.0

Na podstawie kodu GrzybcioRynek 1.0.3 i web 0.1.0.

MarketManager to jedyna klasa, która mutuje oferty i pieniądze. MarketAPI.sellItem / removeListing delegują tutaj i wymagają głównego wątku.

Blokady

  • globalLocksynchronized wokół zakupu, usuwania, force-expire i refundu.
  • reservedListings (ConcurrentHashMap.newKeySet) — ID oferty w trakcie buyItem.
  • Reload (/market reload) jest blokowany, gdy hasReservedListings() jest true: Trwają aktywne transakcje — spróbuj ponownie za chwilę.

sellItem(Player, ItemStack, double)

Kolejność sprawdzeń:

  1. Cena skończona i w zakresie settings.min-pricesettings.max-price.
  2. Cooldown wystawienia (anti-abuse.listing-cooldown-seconds, domyślnie 5 s).
  3. Limit ofert (settings.max-listings-per-player, domyślnie 10).
  4. Prowizja wystawienia (market-fee.listing-fee-percent) — gracz musi mieć kasę.
  5. Item w głównej ręce musi być isSimilar do przekazanego stacka (nie AIR).

Potem: zdjęcie z ręki → withdraw prowizji (fail = zwrot itemu) → StorageManager.createListing (fail = zwrot itemu + depozyt prowizji) → ListingCreatedEvent + AlertService.checkListing.

Tip

MarketAPI.sellItem i /market sell / /wystaw idą tą samą ścieżką. Item musi być w głównej ręce w momencie wywołania.

buyItem(Player, int)

Jeśli ID jest już w reservedListings: komunikat buy.listing-locked (Oferta jest właśnie kupowana przez kogoś innego.).

W synchronized (globalLock):

KrokStanCo się dzieje przy błędzie
Walidacjabrak oferty, własna oferta, anty-abuse, brak kasy, AIR, pełny ekwipunek
Utworzenie TXCREATED
removeListingLISTING_RESERVEDLISTING_REMOVE_FAILED
withdraw kupującegoMONEY_WITHDRAWNrestore oferty, WITHDRAW_FAILED
deposit sprzedawcy (UUID)SELLER_PAIDzwrot kasy kupującemu + restore, SELLER_DEPOSIT_FAILED
Prowizja na sink-account (opcjonalnie)tylko warning w logu, zakup idzie dalej
addItem / overflow → mailbox purchase-overflowITEM_DELIVERED
Persist TX, anty-abuseCOMPLETED

Po sukcesie: TransactionCompletedEvent i (gdy ratings.enabled) prompt oceny.

Rollback (rollbackBuy)

Wywoływany z catch gdy transakcja nie została scommitowana.

Stan w momencie wyjątkuDziałanie
ITEM_DELIVERED / COMPLETEDfinalizacja — nie cofa ekonomii (unik mintu + itemu)
SELLER_PAIDwithdraw od sprzedawcy; fail = ROLLBACK_SELLER_WITHDRAW_FAILED bez zwrotu kupującemu
MONEY_WITHDRAWNdepozyt kupującemu + restore oferty → ROLLED_BACK
LISTING_RESERVEDrestore oferty → ROLLED_BACK
innyEXCEPTION_AFTER_<STATE>
wyjątek w rollbackuROLLBACK_FAILED:<msg>

Usuwanie i wygaszanie

removeListing(CommandSender, int):

  • właściciel albo market.admin;
  • zarezerwowana oferta → buy.listing-locked;
  • właściciel: item do ekwipunku / mailbox (removed);
  • admin: returnListingToSeller(..., "admin-removed");
  • event: ListingRemovedEvent z powodem "removed" albo "admin-removed".

forceExpire(int): zdejmuje ofertę, mailbox powód "expired", event "force-expire".

Refund

refundTransaction(sender, txId, reclaimItem) — tylko COMPLETED, nie ponawia gdy error zaczyna się od REFUND.

  1. Withdraw sellerReceived od sprzedawcy (jeśli > 0).
  2. Deposit tej kwoty (albo price, gdy sellerReceived == 0) kupującemu.
  3. Opcja reclaim: próba removeItem u online kupującego + mailbox sprzedawcy (admin-refund).
  4. error = "REFUND:" + timestamp, stan ROLLED_BACK.

Komendy: /market admin refund <tx-id> [reclaim].

Logi TX

Gdy transactions.logging: true:

text
[TX <uuid>] <STAGE> listing=#<id> buyer=... seller=... price=... fee=... item=... state=... error=...

Szukaj w konsoli po [TX i ID transakcji.

Inne metody

MetodaRola
isListingReserved(int)czy ID jest w trakcie zakupu
hasReservedListings()blokada reloadu
sendInvalidPriceMessagesell.invalid-price z min/max
sendPriceHintmin/średnia/max z historii (StatsManager.getPriceSummary)
getItemName / getPlainItemNamenazwa display albo material