Add starter RV progression and fishing feedback

This commit is contained in:
Alexander Sellite 2026-08-31 16:03:55 -04:00
parent eed361681a
commit d8bf59bca0
47 changed files with 2268 additions and 467 deletions

View file

@ -12,9 +12,10 @@ const DecorCatalogType = preload("res://homes/decor_catalog.gd")
const FISHING_SHOP_ID: StringName = &"main_fishing_shop"
const DECOR_SHOP_ID: StringName = &"rv_decor_shop"
const RV_UPGRADE_SHOP_ID: StringName = &"rv_upgrade_shop"
const REEL_PRODUCT_ID: StringName = &"reel_speed_upgrade"
const BARRIER_PRODUCT_ID: StringName = &"barrier_power_upgrade"
const COOLER_PRODUCT_ID: StringName = &"cooler_capacity_upgrade"
const HOME_UPGRADE_PRODUCT_ID: StringName = &"starter_rv_upgrade"
const BACKPACK_PRODUCT_ID: StringName = &"backpack_capacity_upgrade"
const MAX_LEDGER_ENTRIES_PER_PEER: int = 64
@ -34,6 +35,7 @@ var _spawn_service: PlayerSpawnService
var _network_fishing: NetworkFishingService
var _interaction: FishingShopInteraction
var _decor_interaction: DecorShopInteraction
var _rv_upgrade_interaction: FishingShopInteraction
var _wallet: PlayerWallet
var _bag: PlayerBag
var _item_catalog: ItemCatalog
@ -71,6 +73,7 @@ func setup(
home_state: PlayerHomeState = null,
network_home: NetworkHomeService = null,
decor_interaction: DecorShopInteraction = null,
rv_upgrade_interaction: FishingShopInteraction = null,
) -> void:
_session = session
_spawn_service = spawn_service
@ -88,6 +91,7 @@ func setup(
_home_state = home_state
_network_home = network_home
_decor_interaction = decor_interaction
_rv_upgrade_interaction = rv_upgrade_interaction
if not _session.peer_removed.is_connected(_on_peer_removed):
_session.peer_removed.connect(_on_peer_removed)
if not _session.state_changed.is_connected(_on_session_state_changed):
@ -104,6 +108,12 @@ func set_decor_shop_interaction(
_decor_interaction = interaction
func set_rv_upgrade_shop_interaction(
interaction: FishingShopInteraction,
) -> void:
_rv_upgrade_interaction = interaction
func can_request_purchase() -> bool:
return (
_session != null
@ -154,6 +164,19 @@ func can_request_decor_purchase() -> bool:
)
func can_request_home_upgrade() -> bool:
return (
can_request_purchase()
and _home_state != null
and (
_session.is_host()
or _session.supports_server_capability(
NetworkShopProtocol.HOME_UPGRADE_CAPABILITY
)
)
)
func is_local_purchase_pending() -> bool:
return not _pending_local_request.is_empty()
@ -204,12 +227,12 @@ func request_barrier_power_upgrade() -> String:
)
func request_cooler_capacity_upgrade() -> String:
func request_home_upgrade() -> String:
return _request_purchase(
COOLER_PRODUCT_ID,
NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE,
HOME_UPGRADE_PRODUCT_ID,
NetworkShopProtocol.ProductCategory.HOME_UPGRADE,
1,
_cooler_capacity.get_level() if _cooler_capacity != null else 0
_home_state.get_tier() if _home_state != null else 0
)
@ -308,6 +331,15 @@ func _request_purchase(
product_id, category, 0, 0,
)
return ""
if (
category == NetworkShopProtocol.ProductCategory.HOME_UPGRADE
and not can_request_home_upgrade()
):
local_purchase_finished.emit(
"", false, "RV upgrades require a newer server.",
product_id, category, 0, 0,
)
return ""
if (
category == NetworkShopProtocol.ProductCategory.DECOR
and not can_request_decor_purchase()
@ -318,11 +350,7 @@ func _request_purchase(
)
return ""
var request_id: String = _new_id("shop")
var shop_id: StringName = (
DECOR_SHOP_ID
if category == NetworkShopProtocol.ProductCategory.DECOR
else FISHING_SHOP_ID
)
var shop_id: StringName = _shop_id_for_category(category)
var request: Dictionary = {
"request_id": request_id,
"session_id": _session.get_session_id(),
@ -402,9 +430,7 @@ func _handle_purchase_request(peer_id: int, data: Dictionary) -> void:
if not _is_shop_available_for_peer(peer_id, requested_shop_id):
var avatar: Player = _spawn_service.get_avatar(peer_id)
var requested_interaction: FishingShopInteraction = (
_decor_interaction
if requested_shop_id == DECOR_SHOP_ID
else _interaction
_interaction_for_shop(requested_shop_id)
)
var message: String = (
"The shop is unavailable."
@ -416,16 +442,22 @@ func _handle_purchase_request(peer_id: int, data: Dictionary) -> void:
var result: Dictionary = _build_authoritative_result(peer_id, data)
if (
bool(result.get("accepted", false))
and int(result.get("category", -1))
== NetworkShopProtocol.ProductCategory.DECOR
and _network_home != null
):
_network_home.authorize_decor_purchase(
peer_id,
StringName(str(result["product_id"])),
int(result["resulting_state"]),
str(result["result_id"]),
)
match int(result.get("category", -1)):
NetworkShopProtocol.ProductCategory.DECOR:
_network_home.authorize_decor_purchase(
peer_id,
StringName(str(result["product_id"])),
int(result["resulting_state"]),
str(result["result_id"]),
)
NetworkShopProtocol.ProductCategory.HOME_UPGRADE:
_network_home.authorize_home_upgrade(
peer_id,
int(result["resulting_state"]),
str(result["result_id"]),
)
_pending_by_peer[peer_id] = request_id
_record_and_send(peer_id, result)
@ -448,14 +480,19 @@ func _build_authoritative_result(
)
if authoritative_count >= 0:
current_state = authoritative_count
elif (
category == NetworkShopProtocol.ProductCategory.HOME_UPGRADE
and _network_home != null
):
var authoritative_tier: int = (
_network_home.get_authoritative_home_tier(peer_id)
)
if authoritative_tier >= 0:
current_state = authoritative_tier
var cost: int = -1
var resulting_state: int = current_state
var rejection: String = ""
var expected_shop_id: StringName = (
DECOR_SHOP_ID
if category == NetworkShopProtocol.ProductCategory.DECOR
else FISHING_SHOP_ID
)
var expected_shop_id: StringName = _shop_id_for_category(category)
if StringName(str(request["shop_id"])) != expected_shop_id:
rejection = "The shop is unavailable."
elif quantity < 1:
@ -569,18 +606,14 @@ func _build_authoritative_result(
]
)
resulting_state = current_state + 1
NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE:
NetworkShopProtocol.ProductCategory.HOME_UPGRADE:
if (
product_id != COOLER_PRODUCT_ID
or current_state >= PlayerCoolerCapacity.MAX_LEVEL
product_id != HOME_UPGRADE_PRODUCT_ID
or current_state >= PlayerHomeState.MAX_TIER
):
rejection = "Upgrade is already at maximum."
else:
cost = (
PlayerCoolerCapacity.EXPANSION_COSTS[
current_state
]
)
cost = PlayerHomeState.HOME_UPGRADE_COSTS[current_state]
resulting_state = current_state + 1
NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE:
if (
@ -874,10 +907,12 @@ func _validate_local_result(data: Dictionary) -> String:
return "Purchase could not be completed."
if _upgrades.get_next_barrier_power_cost() != cost:
return "Purchase could not be completed."
NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE:
if _cooler_capacity.get_level() != expected_state:
return "Purchase could not be completed."
if _cooler_capacity.get_next_cost() != cost:
NetworkShopProtocol.ProductCategory.HOME_UPGRADE:
if (
product_id != HOME_UPGRADE_PRODUCT_ID
or _home_state.get_tier() != expected_state
or _home_state.get_next_upgrade_cost() != cost
):
return "Purchase could not be completed."
NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE:
if (
@ -947,8 +982,11 @@ func _apply_local_product(data: Dictionary) -> bool:
return _upgrades.purchase_reel_speed(_wallet)
NetworkShopProtocol.ProductCategory.BARRIER_POWER_UPGRADE:
return _upgrades.purchase_barrier_power(_wallet)
NetworkShopProtocol.ProductCategory.COOLER_CAPACITY_UPGRADE:
return _cooler_capacity.purchase(_wallet)
NetworkShopProtocol.ProductCategory.HOME_UPGRADE:
return (
_wallet.debit(int(data["total_cost"]))
and _home_state.upgrade_to_next_tier()
)
NetworkShopProtocol.ProductCategory.BACKPACK_CAPACITY_UPGRADE:
return (
_inventory_layout != null
@ -1061,6 +1099,9 @@ func _handle_acknowledgement(
_network_home.finalize_decor_purchase(
peer_id, result_id, applied
)
_network_home.finalize_home_upgrade(
peer_id, result_id, applied
)
_acknowledged_results[result_id] = true
_bound_dictionary(_acknowledged_results)
if _pending_by_peer.get(peer_id, "") == request_id:
@ -1071,11 +1112,7 @@ func _is_shop_available_for_peer(
peer_id: int,
shop_id: StringName,
) -> bool:
var interaction: FishingShopInteraction = (
_decor_interaction
if shop_id == DECOR_SHOP_ID
else _interaction
)
var interaction: FishingShopInteraction = _interaction_for_shop(shop_id)
if (
_session == null
or not _session.is_host()
@ -1097,6 +1134,24 @@ func _is_shop_available_for_peer(
)
func _shop_id_for_category(category: int) -> StringName:
match category:
NetworkShopProtocol.ProductCategory.DECOR:
return DECOR_SHOP_ID
NetworkShopProtocol.ProductCategory.HOME_UPGRADE:
return RV_UPGRADE_SHOP_ID
return FISHING_SHOP_ID
func _interaction_for_shop(shop_id: StringName) -> FishingShopInteraction:
match shop_id:
DECOR_SHOP_ID:
return _decor_interaction
RV_UPGRADE_SHOP_ID:
return _rv_upgrade_interaction
return _interaction
func _on_peer_removed(peer_id: int) -> void:
_request_ledgers.erase(peer_id)
_pending_by_peer.erase(peer_id)