MarketManager
Wystawianie, zakup ze stanami transakcji, usuwanie ofert, refund i rezerwacje.
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
globalLock—synchronizedwokół zakupu, usuwania, force-expire i refundu.reservedListings(ConcurrentHashMap.newKeySet) — ID oferty w trakciebuyItem.- Reload (
/market reload) jest blokowany, gdyhasReservedListings()jesttrue:Trwają aktywne transakcje — spróbuj ponownie za chwilę.
sellItem(Player, ItemStack, double)
Kolejność sprawdzeń:
- Cena skończona i w zakresie
settings.min-price…settings.max-price. - Cooldown wystawienia (
anti-abuse.listing-cooldown-seconds, domyślnie 5 s). - Limit ofert (
settings.max-listings-per-player, domyślnie 10). - Prowizja wystawienia (
market-fee.listing-fee-percent) — gracz musi mieć kasę. - Item w głównej ręce musi być
isSimilardo 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.
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):
| Krok | Stan | Co się dzieje przy błędzie |
|---|---|---|
| Walidacja | — | brak oferty, własna oferta, anty-abuse, brak kasy, AIR, pełny ekwipunek |
| Utworzenie TX | CREATED | — |
removeListing | LISTING_RESERVED | LISTING_REMOVE_FAILED |
withdraw kupującego | MONEY_WITHDRAWN | restore oferty, WITHDRAW_FAILED |
deposit sprzedawcy (UUID) | SELLER_PAID | zwrot kasy kupującemu + restore, SELLER_DEPOSIT_FAILED |
Prowizja na sink-account (opcjonalnie) | — | tylko warning w logu, zakup idzie dalej |
addItem / overflow → mailbox purchase-overflow | ITEM_DELIVERED | — |
| Persist TX, anty-abuse | COMPLETED | — |
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ątku | Działanie |
|---|---|
ITEM_DELIVERED / COMPLETED | finalizacja — nie cofa ekonomii (unik mintu + itemu) |
SELLER_PAID | withdraw od sprzedawcy; fail = ROLLBACK_SELLER_WITHDRAW_FAILED bez zwrotu kupującemu |
MONEY_WITHDRAWN | depozyt kupującemu + restore oferty → ROLLED_BACK |
LISTING_RESERVED | restore oferty → ROLLED_BACK |
| inny | EXCEPTION_AFTER_<STATE> |
| wyjątek w rollbacku | ROLLBACK_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:
ListingRemovedEventz 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.
- Withdraw
sellerReceivedod sprzedawcy (jeśli > 0). - Deposit tej kwoty (albo
price, gdysellerReceived == 0) kupującemu. - Opcja
reclaim: próbaremoveItemu online kupującego + mailbox sprzedawcy (admin-refund). error = "REFUND:" + timestamp, stanROLLED_BACK.
Komendy: /market admin refund <tx-id> [reclaim].
Logi TX
Gdy transactions.logging: true:
[TX <uuid>] <STAGE> listing=#<id> buyer=... seller=... price=... fee=... item=... state=... error=...Szukaj w konsoli po [TX i ID transakcji.
Inne metody
| Metoda | Rola |
|---|---|
isListingReserved(int) | czy ID jest w trakcie zakupu |
hasReservedListings() | blokada reloadu |
sendInvalidPriceMessage | sell.invalid-price z min/max |
sendPriceHint | min/średnia/max z historii (StatsManager.getPriceSummary) |
getItemName / getPlainItemName | nazwa display albo material |