Add multi-select batch fish selling

This commit is contained in:
Alexander Sellite 2026-07-26 23:18:51 -04:00
parent 9277326164
commit e560cc0b3e
9 changed files with 747 additions and 272 deletions

View file

@ -8,12 +8,15 @@ enum Status {
INVALID_VALUE,
INVALID_BUYER,
INVALID_OFFER,
INVALID_SELECTION,
TRANSACTION_FAILED,
}
var success: bool = false
var status: Status = Status.TRANSACTION_FAILED
var catch_id: StringName
var catch_ids: Array[StringName] = []
var fish_count: int = 0
var fish_name: String = ""
var buyer_id: StringName
var buyer_display_name: String = ""
@ -32,14 +35,16 @@ func get_message() -> String:
Status.SUCCESS:
return sale_message
Status.NOT_FOUND:
return "Fish no longer exists."
return "fish no longer exists."
Status.FAVORITED:
return "Favorited fish cannot be sold."
return "favorited fish cannot be sold."
Status.INVALID_VALUE:
return "Invalid sale value."
return "invalid sale value."
Status.INVALID_BUYER:
return "Buyer is unavailable."
return "buyer is unavailable."
Status.INVALID_OFFER:
return "Invalid buyer offer."
return "invalid buyer offer."
Status.INVALID_SELECTION:
return "the fish selection is invalid."
_:
return "Transaction failed."
return "transaction failed."

View file

@ -25,24 +25,53 @@ func can_sell(
catch_id: StringName,
buyer: FishBuyerProfileType,
) -> bool:
return _validate_sale(catch_id, buyer).is_success()
return preview_batch([catch_id], buyer).is_success()
func can_sell_batch(
catch_ids: Array[StringName],
buyer: FishBuyerProfileType,
) -> bool:
return preview_batch(catch_ids, buyer).is_success()
func preview_batch(
catch_ids: Array[StringName],
buyer: FishBuyerProfileType,
) -> FishSaleResultType:
return _validate_batch(catch_ids, buyer)
func sell(
catch_id: StringName,
buyer: FishBuyerProfileType,
) -> FishSaleResultType:
var result: FishSaleResultType = _validate_sale(catch_id, buyer)
return sell_batch([catch_id], buyer)
func sell_batch(
catch_ids: Array[StringName],
buyer: FishBuyerProfileType,
) -> FishSaleResultType:
var result: FishSaleResultType = _validate_batch(catch_ids, buyer)
if not result.is_success():
return result
var removed_catch: FishCatchType = _inventory.remove_catch_by_id(catch_id)
if removed_catch == null:
var inventory_snapshot: Array[FishCatchType] = _inventory.get_all_catches()
var next_sequence_snapshot: int = _inventory.get_next_catch_sequence()
var removed_catches: Array[FishCatchType] = (
_inventory.remove_catches_by_ids(result.catch_ids)
)
if removed_catches.size() != result.catch_ids.size():
result.success = false
result.status = FishSaleResultType.Status.NOT_FOUND
result.status = FishSaleResultType.Status.TRANSACTION_FAILED
return result
if not _wallet.credit(result.payout):
_inventory.add_catch(removed_catch)
if not _inventory.replace_all_catches(
inventory_snapshot,
next_sequence_snapshot
):
push_error("Unable to roll back a failed fish batch sale.")
result.success = false
result.status = FishSaleResultType.Status.TRANSACTION_FAILED
return result
@ -50,27 +79,22 @@ func sell(
return result
func _validate_sale(
catch_id: StringName,
func _validate_batch(
catch_ids: Array[StringName],
buyer: FishBuyerProfileType,
) -> FishSaleResultType:
var result := FishSaleResultType.new()
result.catch_id = catch_id
if (
catch_id.is_empty()
or _inventory == null
or _wallet == null
):
result.status = FishSaleResultType.Status.NOT_FOUND
result.catch_ids = catch_ids.duplicate()
result.fish_count = catch_ids.size()
if _inventory == null or _wallet == null:
result.status = FishSaleResultType.Status.TRANSACTION_FAILED
return result
if catch_ids.is_empty():
result.status = FishSaleResultType.Status.INVALID_SELECTION
return result
if buyer == null or not buyer.is_valid():
result.status = FishSaleResultType.Status.INVALID_BUYER
return result
var fish_catch: FishCatchType = _inventory.get_catch_by_id(catch_id)
if fish_catch == null:
result.status = FishSaleResultType.Status.NOT_FOUND
return result
result.fish_name = fish_catch.fish.display_name
result.buyer_id = buyer.id
result.buyer_display_name = buyer.display_name
result.buyer_animal_name = (
@ -78,21 +102,55 @@ func _validate_sale(
if not buyer.animal_name_plural.is_empty()
else buyer.display_name
)
result.base_value = fish_catch.sale_value
result.payout = buyer.get_offer(result.base_value)
if fish_catch.is_favorited:
var seen_ids: Dictionary[StringName, bool] = {}
var contains_favorite: bool = false
const MAX_SAFE_TOTAL: int = 9223372036854775807
for catch_id: StringName in catch_ids:
if catch_id.is_empty() or seen_ids.has(catch_id):
result.status = FishSaleResultType.Status.INVALID_SELECTION
return result
seen_ids[catch_id] = true
var fish_catch: FishCatchType = _inventory.get_catch_by_id(catch_id)
if fish_catch == null:
result.status = FishSaleResultType.Status.NOT_FOUND
return result
if fish_catch.is_favorited:
contains_favorite = true
if fish_catch.sale_value < 0:
result.status = FishSaleResultType.Status.INVALID_VALUE
return result
var offer: int = buyer.get_offer(fish_catch.sale_value)
if offer < 0:
result.status = FishSaleResultType.Status.INVALID_OFFER
return result
if (
result.base_value > MAX_SAFE_TOTAL - fish_catch.sale_value
or result.payout > MAX_SAFE_TOTAL - offer
):
result.status = FishSaleResultType.Status.TRANSACTION_FAILED
return result
result.base_value += fish_catch.sale_value
result.payout += offer
if result.fish_count == 1:
result.catch_id = fish_catch.catch_id
result.fish_name = fish_catch.fish.display_name
if contains_favorite:
result.status = FishSaleResultType.Status.FAVORITED
elif fish_catch.sale_value < 0:
result.status = FishSaleResultType.Status.INVALID_VALUE
elif result.payout < 0:
result.status = FishSaleResultType.Status.INVALID_OFFER
elif not _wallet.can_credit(result.payout):
return result
if not _wallet.can_credit(result.payout):
result.status = FishSaleResultType.Status.TRANSACTION_FAILED
else:
result.status = FishSaleResultType.Status.SUCCESS
result.success = true
return result
result.status = FishSaleResultType.Status.SUCCESS
result.success = true
if result.fish_count == 1:
result.sale_message = buyer.get_sale_message(
result.fish_name,
result.payout
)
else:
result.sale_message = "you sold %d fish to the %s for $%d." % [
result.fish_count,
result.buyer_animal_name,
result.payout,
]
return result