Prepare v0.6.6-alpha release
This commit is contained in:
parent
96df168851
commit
b044d35021
29 changed files with 568 additions and 134 deletions
|
|
@ -109,6 +109,7 @@ func _run() -> void:
|
|||
select_button.button_index = JOY_BUTTON_BACK
|
||||
select_button.pressed = true
|
||||
assert(bool(game_ui.call("_handle_controller_chat_controls", select_button)))
|
||||
await process_frame
|
||||
assert(chat_ui.is_open())
|
||||
assert(chat_panel.mouse_filter == Control.MOUSE_FILTER_STOP)
|
||||
var typed_chat_entry := chat_ui.find_child(
|
||||
|
|
@ -121,6 +122,8 @@ func _run() -> void:
|
|||
accept_button.pressed = true
|
||||
assert(bool(game_ui.call("_handle_controller_chat_controls", accept_button)))
|
||||
assert(typed_chat_entry.virtual_keyboard_enabled)
|
||||
await process_frame
|
||||
assert(typed_chat_entry.has_focus())
|
||||
var left_bumper := InputEventJoypadButton.new()
|
||||
left_bumper.button_index = JOY_BUTTON_LEFT_SHOULDER
|
||||
left_bumper.pressed = true
|
||||
|
|
@ -129,10 +132,8 @@ func _run() -> void:
|
|||
assert(chat_panel.mouse_filter == Control.MOUSE_FILTER_IGNORE)
|
||||
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
||||
assert(bool(game_ui.call("_handle_controller_chat_controls", left_bumper)))
|
||||
assert(chat_ui.is_open())
|
||||
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
||||
assert(bool(game_ui.call("_handle_controller_chat_controls", left_bumper)))
|
||||
assert(not chat_ui.is_open())
|
||||
assert(not typed_chat_entry.virtual_keyboard_enabled)
|
||||
assert(bool(game_ui.call("_handle_controller_chat_controls", select_button)))
|
||||
assert(not chat_ui.is_open())
|
||||
assert(chat_ui.is_collapsed())
|
||||
|
|
@ -315,5 +316,7 @@ func _run() -> void:
|
|||
var session := main.get_node("%NetworkSession") as NetworkSession
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
|
|
|||
|
|
@ -39,6 +39,15 @@ func _run() -> void:
|
|||
standard_button.material != null,
|
||||
"ordinary controller focus receives inversion",
|
||||
)
|
||||
var pointer_motion := InputEventMouseMotion.new()
|
||||
pointer_motion.position = Vector2(4.0, 4.0)
|
||||
presentation._input(pointer_motion)
|
||||
await process_frame
|
||||
_expect(
|
||||
standard_button.material == null,
|
||||
"mouse motion clears controller focus presentation",
|
||||
)
|
||||
presentation._input(controller_event)
|
||||
|
||||
authored_selector.grab_focus()
|
||||
await process_frame
|
||||
|
|
|
|||
|
|
@ -23,14 +23,45 @@ func _run() -> void:
|
|||
var original := _make_button("cute", "cute (show variants)")
|
||||
option_list.add_child(original)
|
||||
await process_frame
|
||||
original.grab_focus()
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"programmatic focus stays pending outside navigation mode",
|
||||
)
|
||||
var keyboard_navigation := InputEventKey.new()
|
||||
keyboard_navigation.keycode = KEY_DOWN
|
||||
keyboard_navigation.pressed = true
|
||||
recovery._input(keyboard_navigation)
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == original,
|
||||
"keyboard navigation restores pending initial focus",
|
||||
)
|
||||
var menu_shortcut := InputEventKey.new()
|
||||
menu_shortcut.physical_keycode = KEY_TAB
|
||||
menu_shortcut.pressed = true
|
||||
recovery._input(menu_shortcut)
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"the menu shortcut does not leave a pseudo-focused option",
|
||||
)
|
||||
|
||||
var controller_event := InputEventJoypadButton.new()
|
||||
controller_event.button_index = JOY_BUTTON_A
|
||||
controller_event.pressed = true
|
||||
recovery._input(controller_event)
|
||||
original.grab_focus()
|
||||
await process_frame
|
||||
_expect(root.gui_get_focus_owner() == original, "original option receives focus")
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == original,
|
||||
"controller navigation restores pending initial focus",
|
||||
)
|
||||
|
||||
option_list.remove_child(original)
|
||||
original.queue_free()
|
||||
|
|
@ -53,6 +84,63 @@ func _run() -> void:
|
|||
root.gui_get_focus_owner() == explicit_target,
|
||||
"explicit focus changes take precedence over recovery",
|
||||
)
|
||||
var pointer_motion := InputEventMouseMotion.new()
|
||||
pointer_motion.position = Vector2(4.0, 4.0)
|
||||
recovery._input(pointer_motion)
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"mouse motion releases controller focus",
|
||||
)
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"mouse motion prevents automatic focus recovery",
|
||||
)
|
||||
recovery._input(controller_event)
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == explicit_target,
|
||||
"controller navigation can resume from pointer mode",
|
||||
)
|
||||
var pointer_press := InputEventMouseButton.new()
|
||||
pointer_press.button_index = MOUSE_BUTTON_LEFT
|
||||
pointer_press.pressed = true
|
||||
recovery._input(pointer_press)
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == explicit_target,
|
||||
"mouse-down preserves focus through button activation",
|
||||
)
|
||||
var pointer_release := InputEventMouseButton.new()
|
||||
pointer_release.button_index = MOUSE_BUTTON_LEFT
|
||||
pointer_release.pressed = false
|
||||
recovery._input(pointer_release)
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"mouse-up clears the completed button focus",
|
||||
)
|
||||
recovery._input(controller_event)
|
||||
await process_frame
|
||||
await process_frame
|
||||
|
||||
var outside_button := _make_button("outside", "outside")
|
||||
stage.add_child(outside_button)
|
||||
option_list.hide()
|
||||
root.gui_release_focus()
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == null,
|
||||
"focus recovery never escapes a hidden menu scope",
|
||||
)
|
||||
option_list.show()
|
||||
explicit_target.grab_focus()
|
||||
await process_frame
|
||||
var leave_world_ui_event := InputEventJoypadButton.new()
|
||||
leave_world_ui_event.button_index = JOY_BUTTON_LEFT_SHOULDER
|
||||
leave_world_ui_event.pressed = true
|
||||
|
|
@ -64,6 +152,14 @@ func _run() -> void:
|
|||
root.gui_get_focus_owner() == null,
|
||||
"LB intentionally leaving world UI is never recovered",
|
||||
)
|
||||
var accessibility_only := Control.new()
|
||||
accessibility_only.focus_mode = Control.FOCUS_ACCESSIBILITY
|
||||
stage.add_child(accessibility_only)
|
||||
await process_frame
|
||||
_expect(
|
||||
not bool(recovery.call("_is_focusable", accessibility_only)),
|
||||
"accessibility-only controls are not recovery targets",
|
||||
)
|
||||
|
||||
stage.queue_free()
|
||||
if _failures.is_empty():
|
||||
|
|
|
|||
|
|
@ -127,7 +127,9 @@ func _run_multiplayer_host() -> void:
|
|||
print("Economy multiplayer host validation: PASS")
|
||||
session.disconnect_session("Economy host validation complete.")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -229,7 +231,9 @@ func _run_multiplayer_client() -> void:
|
|||
print("Economy multiplayer client validation: PASS")
|
||||
session.disconnect_session("Economy client validation complete.")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -408,7 +412,7 @@ func _test_player_menu_sale(
|
|||
assert(sell_action.mouse_filter == Control.MOUSE_FILTER_STOP)
|
||||
assert(sell_action.focus_mode == Control.FOCUS_ALL)
|
||||
assert(ui_viewport != null)
|
||||
await _activate_focused_button(sell_action, ui_viewport)
|
||||
await _activate_pointer_control(sell_action, ui_viewport)
|
||||
await process_frame
|
||||
assert(confirmation.visible)
|
||||
assert(confirm_button.visible and not confirm_button.disabled)
|
||||
|
|
@ -417,7 +421,7 @@ func _test_player_menu_sale(
|
|||
> (player_menu.get_node("%CoolerOuterWall") as Control).z_index
|
||||
)
|
||||
_sale_result.clear()
|
||||
await _activate_focused_button(confirm_button, ui_viewport)
|
||||
await _activate_pointer_control(confirm_button, ui_viewport)
|
||||
await process_frame
|
||||
assert(not _sale_result.is_empty() and bool(_sale_result[1]))
|
||||
assert(not player.inventory.contains_catch_id(fish_catch.catch_id))
|
||||
|
|
@ -436,18 +440,29 @@ func _test_player_menu_sale(
|
|||
await create_timer(2.2).timeout
|
||||
|
||||
|
||||
func _activate_focused_button(
|
||||
button: Button,
|
||||
func _activate_pointer_control(
|
||||
control: Control,
|
||||
ui_viewport: SubViewport,
|
||||
) -> void:
|
||||
button.grab_focus()
|
||||
var presenter := ui_viewport.get_parent() as SubViewportContainer
|
||||
assert(presenter != null)
|
||||
var local_center: Vector2 = control.get_global_transform_with_canvas() * (
|
||||
control.size * 0.5
|
||||
)
|
||||
var center: Vector2 = presenter.position + local_center * presenter.scale
|
||||
var motion := InputEventMouseMotion.new()
|
||||
motion.position = center
|
||||
motion.global_position = center
|
||||
root.push_input(motion, true)
|
||||
await process_frame
|
||||
assert(button.has_focus())
|
||||
assert(ui_viewport.gui_get_hovered_control() == control)
|
||||
for is_pressed: bool in [true, false]:
|
||||
var accept := InputEventAction.new()
|
||||
accept.action = &"ui_accept"
|
||||
accept.pressed = is_pressed
|
||||
ui_viewport.push_input(accept, false)
|
||||
var click := InputEventMouseButton.new()
|
||||
click.button_index = MOUSE_BUTTON_LEFT
|
||||
click.position = center
|
||||
click.global_position = center
|
||||
click.pressed = is_pressed
|
||||
root.push_input(click, true)
|
||||
await process_frame
|
||||
|
||||
|
||||
|
|
@ -560,14 +575,14 @@ func _test_fishing_shop_sale_ui(
|
|||
assert(art_supplies_tab != null and art_supplies_tab.text == "Art Supplies")
|
||||
var sell_mode := shop_tabs[5] as Button
|
||||
assert(sell_mode != null and sell_mode.text == "Sell Fish")
|
||||
await _activate_focused_button(art_supplies_tab, ui_viewport)
|
||||
await _activate_pointer_control(art_supplies_tab, ui_viewport)
|
||||
await process_frame
|
||||
var stock_sections: Array[String] = []
|
||||
for child: Node in shop.get_node("%SuppliesList").get_children():
|
||||
if child is Label:
|
||||
stock_sections.append((child as Label).text)
|
||||
assert(stock_sections == ["art kit", "markers", "brushes", "grids"])
|
||||
await _activate_focused_button(sell_mode, ui_viewport)
|
||||
await _activate_pointer_control(sell_mode, ui_viewport)
|
||||
await process_frame
|
||||
assert(shop.visible and not player_menu.visible)
|
||||
assert(not shop.has_node("ShopPanel/Margin/Layout/Body/FishSales"))
|
||||
|
|
@ -584,6 +599,11 @@ func _test_fishing_shop_sale_ui(
|
|||
var water_surface := player_menu.get("_cooler_water_surface") as ColorRect
|
||||
assert(cooler_outer_wall != null and cooler_outer_wall.visible)
|
||||
assert(water_surface.visible and water_surface.material is ShaderMaterial)
|
||||
var cooler_sort_option := player_menu.get("_cooler_sort_option") as Control
|
||||
await _activate_pointer_control(cooler_sort_option, ui_viewport)
|
||||
var cooler_choice_panel := cooler_sort_option.get("_choice_panel") as Control
|
||||
assert(cooler_choice_panel.visible)
|
||||
cooler_sort_option.call("close_choices")
|
||||
assert(
|
||||
StringName(
|
||||
(player_menu.get("_sale_buyer_override") as FishBuyerProfile).id
|
||||
|
|
@ -594,10 +614,10 @@ func _test_fishing_shop_sale_ui(
|
|||
var reserved_button := fish_nodes.get(reserved_catch.catch_id) as Button
|
||||
assert(fish_button != null and fish_button.visible)
|
||||
assert(reserved_button != null and reserved_button.visible)
|
||||
await _activate_focused_button(fish_button, ui_viewport)
|
||||
await _activate_pointer_control(fish_button, ui_viewport)
|
||||
var sell_button := player_menu.get("_sell_bubble") as Button
|
||||
assert(sell_button.visible and not sell_button.disabled)
|
||||
await _activate_focused_button(sell_button, ui_viewport)
|
||||
await _activate_pointer_control(sell_button, ui_viewport)
|
||||
await process_frame
|
||||
var confirmation := player_menu.get("_sale_confirmation") as Control
|
||||
var confirm_button := player_menu.get("_confirm_sale_button") as Button
|
||||
|
|
@ -607,14 +627,14 @@ func _test_fishing_shop_sale_ui(
|
|||
> cooler_outer_wall.z_index
|
||||
)
|
||||
_sale_result.clear()
|
||||
await _activate_focused_button(confirm_button, ui_viewport)
|
||||
await _activate_pointer_control(confirm_button, ui_viewport)
|
||||
await process_frame
|
||||
assert(not _sale_result.is_empty() and bool(_sale_result[1]))
|
||||
assert(not player.inventory.contains_catch_id(fish_catch.catch_id))
|
||||
assert(player.wallet.get_balance() == balance_before + fish_catch.sale_value)
|
||||
assert(not sale_service.is_local_sale_pending())
|
||||
assert(reservations.release(reservation_id))
|
||||
await _activate_focused_button(shop_tabs[0] as Button, ui_viewport)
|
||||
await _activate_pointer_control(shop_tabs[0] as Button, ui_viewport)
|
||||
await process_frame
|
||||
assert(shop.visible and (shop.get_node("%ShopPanel") as Control).visible)
|
||||
assert(not (shop.get_node("%ShopCoolerPage") as Control).visible)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ extends SceneTree
|
|||
const MainScene = preload("res://main/main.tscn")
|
||||
const FishCatchType = preload("res://fish/fish_catch.gd")
|
||||
const FishDataType = preload("res://fish/fish_data.gd")
|
||||
const FishingSpotType = preload("res://fishing/fishing_spot.gd")
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
|
|
@ -40,7 +39,6 @@ func _run() -> void:
|
|||
var service := main.get_node(
|
||||
"%NetworkFishShowcaseService"
|
||||
) as NetworkFishShowcaseService
|
||||
var fishing_spot := main.get_node("%FishingSpot") as FishingSpotType
|
||||
assert(player != null and fish_catalog != null and service != null)
|
||||
var fish: FishDataType = fish_catalog.get_fish_by_id(&"bluegill")
|
||||
assert(fish != null)
|
||||
|
|
@ -83,22 +81,18 @@ func _run() -> void:
|
|||
assert(player.hotbar.get_selected_fish_catch_id() == fish_catch.catch_id)
|
||||
assert(player.hotbar.get_selected_item_id().is_empty())
|
||||
|
||||
var press := InputEventMouseButton.new()
|
||||
press.button_index = MOUSE_BUTTON_LEFT
|
||||
press.pressed = true
|
||||
fishing_spot.call("_unhandled_input", press)
|
||||
await process_frame
|
||||
assert(service.is_local_showcase_visible())
|
||||
assert(service.get_local_showcase_catch_id() == fish_catch.catch_id)
|
||||
assert((player.get_node("%HeldFishDisplay") as Node3D).visible)
|
||||
fishing_spot.call("_unhandled_input", press)
|
||||
await _wait_for_held_fish_visibility(player, true)
|
||||
assert(service.toggle_selected_fish())
|
||||
await process_frame
|
||||
assert(not service.is_local_showcase_visible())
|
||||
assert(not (player.get_node("%HeldFishDisplay") as Node3D).visible)
|
||||
await _wait_for_held_fish_visibility(player, false)
|
||||
var saved_weather: WorldWeatherService.Weather = (
|
||||
world_weather.get_weather()
|
||||
)
|
||||
var saved_weather_seconds: float = world_weather.get_seconds_remaining()
|
||||
var saved_time_hours: float = world_time.get_time_hours()
|
||||
|
||||
assert(save_manager.save_now())
|
||||
var save_path: String = str(save_manager.get("_save_path"))
|
||||
|
|
@ -116,7 +110,7 @@ func _run() -> void:
|
|||
== 125
|
||||
)
|
||||
assert(absf(
|
||||
float((parsed as Dictionary)["world"]["time_hours"]) - 19.75
|
||||
float((parsed as Dictionary)["world"]["time_hours"]) - saved_time_hours
|
||||
) < 0.01)
|
||||
assert(
|
||||
int((parsed as Dictionary)["world"]["weather"])
|
||||
|
|
@ -149,7 +143,7 @@ func _run() -> void:
|
|||
)
|
||||
assert(save_manager.load_player_data())
|
||||
assert(player.experience.get_total_experience() == 125)
|
||||
assert(absf(world_time.get_time_hours() - 19.75) < 0.01)
|
||||
assert(absf(world_time.get_time_hours() - saved_time_hours) < 0.01)
|
||||
assert(world_weather.get_weather() == saved_weather)
|
||||
assert(absf(
|
||||
world_weather.get_seconds_remaining() - saved_weather_seconds
|
||||
|
|
@ -163,14 +157,13 @@ func _run() -> void:
|
|||
FishQuality.Tier.EXCEPTIONAL,
|
||||
)
|
||||
)
|
||||
assert(not service.is_local_showcase_visible())
|
||||
assert(service.toggle_selected_fish())
|
||||
assert(service.is_local_showcase_visible())
|
||||
await _wait_for_held_fish_visibility(player, true)
|
||||
assert(player.inventory.remove_catch_by_id(fish_catch.catch_id) != null)
|
||||
await process_frame
|
||||
assert(player.hotbar.get_fish_catch_id(1).is_empty())
|
||||
assert(not service.is_local_showcase_visible())
|
||||
assert(not (player.get_node("%HeldFishDisplay") as Node3D).visible)
|
||||
await _wait_for_held_fish_visibility(player, false)
|
||||
|
||||
var valid_state: Dictionary = {
|
||||
"session_id": "session",
|
||||
|
|
@ -202,5 +195,26 @@ func _run() -> void:
|
|||
print("Fish hotbar showcase validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
func _wait_for_held_fish_visibility(
|
||||
player: Player,
|
||||
expected_visible: bool,
|
||||
) -> void:
|
||||
var held_fish_display := player.get("_held_fish_display") as Node3D
|
||||
assert(held_fish_display != null)
|
||||
var deadline_msec: int = Time.get_ticks_msec() + 2000
|
||||
while (
|
||||
held_fish_display.visible != expected_visible
|
||||
and Time.get_ticks_msec() < deadline_msec
|
||||
):
|
||||
await process_frame
|
||||
assert(
|
||||
held_fish_display.visible == expected_visible,
|
||||
"Held fish display did not become %s within the timeout."
|
||||
% expected_visible,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ func _run_host() -> void:
|
|||
var fish_catch: FishCatch = _add_bluegill(main, player)
|
||||
assert(player.hotbar.assign_fish(1, fish_catch.catch_id))
|
||||
assert(player.hotbar.select_slot(1))
|
||||
assert(service.toggle_selected_fish())
|
||||
assert(service.is_local_showcase_visible())
|
||||
await _wait_for_held_fish_visibility(player, true)
|
||||
assert(session.set_host_open(true))
|
||||
|
||||
var remote_peer_id: int = 0
|
||||
|
|
@ -66,7 +66,9 @@ func _run_host() -> void:
|
|||
print("Fish showcase multiplayer host validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -118,8 +120,8 @@ func _run_client() -> void:
|
|||
var fish_catch: FishCatch = _add_bluegill(main, player)
|
||||
assert(player.hotbar.assign_fish(1, fish_catch.catch_id))
|
||||
assert(player.hotbar.select_slot(1))
|
||||
assert(service.toggle_selected_fish())
|
||||
assert((player.get("_held_fish_display") as Node3D).visible)
|
||||
assert(service.is_local_showcase_visible())
|
||||
await _wait_for_held_fish_visibility(player, true)
|
||||
await create_timer(2.0).timeout
|
||||
assert(service.toggle_selected_fish())
|
||||
var held_display := player.get("_held_fish_display") as Node3D
|
||||
|
|
@ -132,7 +134,9 @@ func _run_client() -> void:
|
|||
print("Fish showcase multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -166,3 +170,18 @@ func _create_initialized_main() -> Node:
|
|||
await process_frame
|
||||
assert(bool(main.get("_application_initialized")))
|
||||
return main
|
||||
|
||||
|
||||
func _wait_for_held_fish_visibility(
|
||||
player: Player,
|
||||
expected_visible: bool,
|
||||
) -> void:
|
||||
var held_fish_display := player.get("_held_fish_display") as Node3D
|
||||
assert(held_fish_display != null)
|
||||
var deadline_msec: int = Time.get_ticks_msec() + 2000
|
||||
while (
|
||||
held_fish_display.visible != expected_visible
|
||||
and Time.get_ticks_msec() < deadline_msec
|
||||
):
|
||||
await process_frame
|
||||
assert(held_fish_display.visible == expected_visible)
|
||||
|
|
|
|||
|
|
@ -36,8 +36,14 @@ func _run() -> void:
|
|||
assert(not session.is_open_host())
|
||||
assert(service != null and fishing_spot != null and player != null)
|
||||
assert(player.hotbar.get_selected_item_id() == &"basic_fishing_rod")
|
||||
var pond := main.get_node(
|
||||
"TestWorld/Regions/StarterIslandRegion/WaterBodies/Pond"
|
||||
) as Node3D
|
||||
var pond_region := pond.get_node("FishingRegion") as FishableWaterRegion
|
||||
assert(pond != null and pond_region != null)
|
||||
var pond_surface_y: float = pond_region.get_surface_height()
|
||||
|
||||
player.global_position = Vector3(-0.5, 3.95, 2.1)
|
||||
player.global_position = pond.global_position + Vector3(8.9, 1.44, 0.0)
|
||||
var visuals := player.get_node("Visuals") as Node3D
|
||||
visuals.rotation.y = PI * 0.5
|
||||
for _frame: int in 4:
|
||||
|
|
@ -50,8 +56,8 @@ func _run() -> void:
|
|||
fishing_spot.set("_cast_charge", 0.32)
|
||||
fishing_spot.call("_update_cast_charge", 0.0)
|
||||
var aimed_target: Vector3 = fishing_spot.get("_cast_target")
|
||||
assert(aimed_target.x < -1.35)
|
||||
assert(is_equal_approx(aimed_target.y, 2.51))
|
||||
assert(aimed_target.x < player.global_position.x - 0.85)
|
||||
assert(is_equal_approx(aimed_target.y, pond_surface_y))
|
||||
assert(fishing_spot.is_target_fishable(aimed_target))
|
||||
fishing_spot.call("_confirm_cast")
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.CASTING)
|
||||
|
|
@ -68,7 +74,7 @@ func _run() -> void:
|
|||
var attempts: Dictionary = service.get("_attempts")
|
||||
var attempt: NetworkFishingAttempt = attempts.get(session.get_local_peer_id())
|
||||
assert(attempt != null)
|
||||
assert(is_equal_approx(attempt.target.y, 2.51))
|
||||
assert(is_equal_approx(attempt.target.y, pond_surface_y))
|
||||
assert(attempt.bobber_position.is_equal_approx(attempt.target))
|
||||
|
||||
fishing_spot.set("_withdrawal_input_held", true)
|
||||
|
|
@ -124,29 +130,42 @@ func _run() -> void:
|
|||
fish,
|
||||
)
|
||||
assert(fish_catch != null and fish_catch.is_valid())
|
||||
var baseline_controller := CatchController.new()
|
||||
root.add_child(baseline_controller)
|
||||
baseline_controller.start_authoritative_encounter(
|
||||
var reference_controller := CatchController.new()
|
||||
root.add_child(reference_controller)
|
||||
reference_controller.start_authoritative_encounter(
|
||||
fish.catch_profile,
|
||||
attempt.reel_speed,
|
||||
attempt.barrier_damage,
|
||||
attempt.encounter_seed,
|
||||
FishQuality.Tier.BORING,
|
||||
fish_catch.quality,
|
||||
int(fish.rarity),
|
||||
fish.get_weight_percentile(fish_catch.weight_lb),
|
||||
)
|
||||
var quality_barriers: Array = attempt.controller.get("_barriers")
|
||||
var baseline_barriers: Array = baseline_controller.get("_barriers")
|
||||
assert(quality_barriers.size() == baseline_barriers.size())
|
||||
var reference_barriers: Array = reference_controller.get("_barriers")
|
||||
assert(quality_barriers.size() == reference_barriers.size())
|
||||
for barrier_index: int in quality_barriers.size():
|
||||
var quality_barrier: RefCounted = quality_barriers[barrier_index]
|
||||
var baseline_barrier: RefCounted = baseline_barriers[barrier_index]
|
||||
var reference_barrier: RefCounted = reference_barriers[barrier_index]
|
||||
assert(
|
||||
int(quality_barrier.get("maximum_health"))
|
||||
== FishQuality.apply_barrier_health(
|
||||
int(baseline_barrier.get("maximum_health")),
|
||||
fish_catch.quality,
|
||||
is_equal_approx(
|
||||
float(quality_barrier.get("position")),
|
||||
float(reference_barrier.get("position")),
|
||||
)
|
||||
)
|
||||
baseline_controller.queue_free()
|
||||
assert(
|
||||
int(quality_barrier.get("maximum_health"))
|
||||
== int(reference_barrier.get("maximum_health"))
|
||||
)
|
||||
assert(
|
||||
int(quality_barrier.get("maximum_health"))
|
||||
>= FishQuality.BARRIER_HEALTH_MINIMUMS[fish_catch.quality]
|
||||
)
|
||||
assert(
|
||||
int(quality_barrier.get("maximum_health"))
|
||||
<= FishQuality.BARRIER_HEALTH_MAXIMUMS[fish_catch.quality]
|
||||
)
|
||||
reference_controller.queue_free()
|
||||
service.call("_cancel_attempt", session.get_local_peer_id(), "")
|
||||
await process_frame
|
||||
assert(not service.has_local_attempt())
|
||||
|
|
@ -154,5 +173,7 @@ func _run() -> void:
|
|||
print("Fishing authority validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
|
|
|||
|
|
@ -150,7 +150,9 @@ func _run_host() -> void:
|
|||
print("Fishing multiplayer host validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -325,7 +327,9 @@ func _run_client() -> void:
|
|||
print("Fishing multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -266,11 +266,47 @@ func _validate_bite_wait_distribution() -> void:
|
|||
if wait_seconds >= FishingSpotType.BITE_LONG_MAX_SECONDS:
|
||||
very_long_count += 1
|
||||
var average_wait_seconds: float = total_wait_seconds / 10000.0
|
||||
assert(quick_count >= 2300 and quick_count <= 2700)
|
||||
var quick_ratio: float = float(quick_count) / 10000.0
|
||||
var very_long_ratio: float = float(very_long_count) / 10000.0
|
||||
var very_long_probability: float = 1.0 - (
|
||||
FishingSpotType.BITE_QUICK_PROBABILITY
|
||||
+ FishingSpotType.BITE_TYPICAL_PROBABILITY
|
||||
+ FishingSpotType.BITE_LONG_PROBABILITY
|
||||
)
|
||||
var expected_average_wait_seconds: float = (
|
||||
FishingSpotType.BITE_QUICK_PROBABILITY
|
||||
* (
|
||||
FishingSpotType.BITE_QUICK_MIN_SECONDS
|
||||
+ FishingSpotType.BITE_QUICK_MAX_SECONDS
|
||||
)
|
||||
* 0.5
|
||||
+ FishingSpotType.BITE_TYPICAL_PROBABILITY
|
||||
* (
|
||||
FishingSpotType.BITE_QUICK_MAX_SECONDS
|
||||
+ FishingSpotType.BITE_TYPICAL_MAX_SECONDS
|
||||
)
|
||||
* 0.5
|
||||
+ FishingSpotType.BITE_LONG_PROBABILITY
|
||||
* (
|
||||
FishingSpotType.BITE_TYPICAL_MAX_SECONDS
|
||||
+ FishingSpotType.BITE_LONG_MAX_SECONDS
|
||||
)
|
||||
* 0.5
|
||||
+ very_long_probability
|
||||
* (
|
||||
FishingSpotType.BITE_LONG_MAX_SECONDS
|
||||
+ FishingSpotType.BITE_MAX_SECONDS
|
||||
)
|
||||
* 0.5
|
||||
)
|
||||
assert(absf(
|
||||
quick_ratio - FishingSpotType.BITE_QUICK_PROBABILITY
|
||||
) <= 0.02)
|
||||
assert(typical_or_long_count > quick_count)
|
||||
assert(very_long_count >= 100 and very_long_count <= 300)
|
||||
assert(average_wait_seconds >= 45.0)
|
||||
assert(average_wait_seconds <= 49.0)
|
||||
assert(absf(very_long_ratio - very_long_probability) <= 0.005)
|
||||
assert(absf(
|
||||
average_wait_seconds - expected_average_wait_seconds
|
||||
) <= 1.0)
|
||||
fishing_spot.queue_free()
|
||||
await process_frame
|
||||
|
||||
|
|
@ -305,11 +341,16 @@ func _validate_remote_presentation() -> void:
|
|||
fish_catch.sale_value = 1
|
||||
assert(fish_catch.is_valid())
|
||||
presentation.play_return(fish_catch)
|
||||
await create_timer(0.6).timeout
|
||||
var catch_display := player.find_child(
|
||||
"CatchDisplay", true, false
|
||||
) as Node3D
|
||||
assert(catch_display != null)
|
||||
var showcase_deadline_msec: int = Time.get_ticks_msec() + 2000
|
||||
while (
|
||||
not catch_display.visible
|
||||
and Time.get_ticks_msec() < showcase_deadline_msec
|
||||
):
|
||||
await process_frame
|
||||
assert(catch_display.visible)
|
||||
await presentation.return_completed
|
||||
assert(not catch_display.visible)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ func _run() -> void:
|
|||
await _capture_inventory_pages(player_menu)
|
||||
print("Inventory notepad artwork validation: PASS")
|
||||
presentation_stage.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 10:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,9 @@ func _run_host() -> void:
|
|||
print("Job multiplayer host validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -93,7 +95,9 @@ func _run_client() -> void:
|
|||
print("Job multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -79,10 +79,15 @@ func _run() -> void:
|
|||
"_show_section_immediate", PlayerMenu.Section.PROFILE
|
||||
)
|
||||
await process_frame
|
||||
assert(not bool(
|
||||
assert(bool(
|
||||
player_menu.call("_handle_direct_page_shortcut", shortcut)
|
||||
))
|
||||
await create_timer(0.5).timeout
|
||||
assert(player_menu.visible)
|
||||
assert(logbook.visible)
|
||||
assert(
|
||||
player_menu.get("_current_section") == PlayerMenu.Section.LOGBOOK
|
||||
)
|
||||
player_menu.close_menu(PlayerMenu.CloseReason.TEARDOWN, false)
|
||||
|
||||
print(
|
||||
|
|
@ -90,7 +95,8 @@ func _run() -> void:
|
|||
% [root.size.x, root.size.y]
|
||||
)
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ func _validate_page() -> void:
|
|||
page.activate()
|
||||
await process_frame
|
||||
assert(page.get("_category") == WaterType.Type.FRESH_WATER)
|
||||
assert((page.get("_catalog_grid") as GridContainer).columns == 5)
|
||||
assert((page.get("_catalog_grid") as GridContainer).columns == 4)
|
||||
var initial_detail_body := page.get("_detail_body") as VBoxContainer
|
||||
assert(not initial_detail_body.get_parent() is ScrollContainer)
|
||||
assert(
|
||||
|
|
@ -209,7 +209,7 @@ func _validate_page() -> void:
|
|||
assert(portrait.source_texture == fish.display_texture)
|
||||
assert(
|
||||
portrait.custom_minimum_size
|
||||
== LogbookPortraitType.ENTRY_FRAME_SIZE
|
||||
== LogbookPage.CATALOG_PORTRAIT_SIZE
|
||||
)
|
||||
assert(
|
||||
portrait.expand_mode
|
||||
|
|
|
|||
|
|
@ -12,6 +12,14 @@ func _run() -> void:
|
|||
root.add_child(game_ui)
|
||||
await process_frame
|
||||
game_ui.set("_gameplay_ui_enabled", true)
|
||||
var panel := game_ui.get_node("%ExperienceProgressPanel") as PanelContainer
|
||||
var bubble := game_ui.get_node("%ExperienceBubble") as PanelContainer
|
||||
var bubble_label := game_ui.get_node("%ExperienceBubbleLabel") as Label
|
||||
var award_label := game_ui.get_node("%ExperienceAwardLabel") as Label
|
||||
assert(panel != null and bubble != null)
|
||||
assert(not panel.visible and not bubble.visible)
|
||||
game_ui.call("_on_showcase_changed", "bluegill", "common", 1.0, 0, true)
|
||||
await process_frame
|
||||
game_ui.call(
|
||||
"_on_experience_awarded",
|
||||
50,
|
||||
|
|
@ -20,13 +28,6 @@ func _run() -> void:
|
|||
1,
|
||||
1,
|
||||
)
|
||||
var panel := game_ui.get_node("%ExperienceProgressPanel") as PanelContainer
|
||||
var bubble := game_ui.get_node("%ExperienceBubble") as PanelContainer
|
||||
var bubble_label := game_ui.get_node("%ExperienceBubbleLabel") as Label
|
||||
var award_label := game_ui.get_node("%ExperienceAwardLabel") as Label
|
||||
assert(panel != null and bubble != null)
|
||||
assert(not panel.visible and not bubble.visible)
|
||||
game_ui.call("_on_showcase_changed", "bluegill", "common", 1.0, 0, true)
|
||||
await process_frame
|
||||
assert(not panel.visible and not bubble.visible)
|
||||
game_ui.call("_on_showcase_changed", "", "", 0.0, 0, false)
|
||||
|
|
@ -43,5 +44,8 @@ func _run() -> void:
|
|||
await create_timer(1.2).timeout
|
||||
assert(not panel.visible and not bubble.visible)
|
||||
game_ui.queue_free()
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
print("Player experience UI validation: PASS")
|
||||
quit()
|
||||
|
|
|
|||
|
|
@ -114,7 +114,9 @@ func _run_host() -> void:
|
|||
print("Surface drawing multiplayer host validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -207,7 +209,9 @@ func _run_client() -> void:
|
|||
print("Surface drawing multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ func _run() -> void:
|
|||
print("Surface drawing runtime validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ func _run() -> void:
|
|||
await _validate_blocked_author_visibility()
|
||||
_validate_peer_capability_tracking()
|
||||
print("Surface drawing validation: PASS")
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -118,6 +120,7 @@ func _validate_art_unlocks() -> void:
|
|||
assert(unlocks.is_brush_size_unlocked(4))
|
||||
assert(unlocks.is_grid_size_unlocked(128))
|
||||
assert(not unlocks.restore_mask(PlayerArtUnlocks.ALL_UNLOCK_MASK + 1))
|
||||
unlocks.free()
|
||||
|
||||
|
||||
func _validate_grid_snapping() -> void:
|
||||
|
|
@ -265,6 +268,7 @@ func _validate_blocked_author_visibility() -> void:
|
|||
})
|
||||
var world := Node3D.new()
|
||||
root.add_child(world)
|
||||
world.add_child(relationships)
|
||||
var canvas := SurfaceDrawingCanvas.new()
|
||||
world.add_child(canvas)
|
||||
var state: Dictionary = {
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ func _run() -> void:
|
|||
|
||||
presenter.queue_free()
|
||||
root.size = original_size
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
print("UI scaling runtime validation: PASS")
|
||||
quit()
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ func _run_host() -> void:
|
|||
print("World time multiplayer host validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
@ -195,7 +197,9 @@ func _run_client() -> void:
|
|||
print("World time multiplayer client validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
await process_frame
|
||||
for _frame: int in 4:
|
||||
await process_frame
|
||||
await create_timer(0.1).timeout
|
||||
quit()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue