Compare commits

...

2 commits

Author SHA1 Message Date
5d7c3d7459 Prepare v0.7.1-alpha release 2026-08-13 22:25:55 -04:00
e54ad1332b Fix rain coverage and in-game session switching 2026-08-13 22:20:43 -04:00
13 changed files with 101 additions and 35 deletions

View file

@ -1,6 +1,6 @@
NETfishing
v0.6.8-alpha
Alpha 0.6.8
v0.7.1-alpha
Alpha 0.7.1
Thank you for trying this early private playtest.

View file

@ -9,7 +9,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*"
export_path="builds/v0.6.8-alpha/windows-x86_64/NETfishing.exe"
export_path="builds/v0.7.1-alpha/windows-x86_64/NETfishing.exe"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -35,11 +35,11 @@ application/modify_resources=true
application/icon="res://art/exported/system_icons/netfishing.ico"
application/console_wrapper_icon=""
application/icon_interpolation=4
application/file_version="0.6.8.0"
application/product_version="0.6.8.0"
application/file_version="0.7.1.0"
application/product_version="0.7.1.0"
application/company_name="Woofmeow"
application/product_name="NETfishing"
application/file_description="NETfishing v0.6.8-alpha"
application/file_description="NETfishing v0.7.1-alpha"
application/copyright="Copyright © 2026 Woofmeow"
application/trademarks="NETfishing and Woofmeow branding is reserved; see TRADEMARKS.md"
application/export_angle=0
@ -62,7 +62,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*"
export_path="builds/v0.6.8-alpha/linux-arm64/NETfishing.arm64"
export_path="builds/v0.7.1-alpha/linux-arm64/NETfishing.arm64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -92,7 +92,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*"
export_path="builds/v0.6.8-alpha/macos/NETfishing.zip"
export_path="builds/v0.7.1-alpha/macos/NETfishing.zip"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -108,8 +108,8 @@ custom_template/release=""
application/bundle_identifier="io.woofmeow.netfishing"
application/icon="res://art/exported/system_icons/netfishing_1024.png"
application/icon_interpolation=0
application/short_version="0.6.8"
application/version="0.6.8"
application/short_version="0.7.1"
application/version="0.7.1"
application/architecture="universal"
codesign/enable=false
notarization/enable=false
@ -125,7 +125,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*,tests/*"
export_path="builds/v0.6.8-alpha/server-linux-x86_64/NETfishingServer.x86_64"
export_path="builds/v0.7.1-alpha/server-linux-x86_64/NETfishingServer.x86_64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -155,7 +155,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*"
export_path="builds/v0.6.8-alpha/android/NETfishing.apk"
export_path="builds/v0.7.1-alpha/android/NETfishing.apk"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -176,8 +176,8 @@ architectures/armeabi-v7a=false
architectures/arm64-v8a=true
architectures/x86=false
architectures/x86_64=false
version/code=60800
version/name="v0.6.8-alpha"
version/code=70100
version/name="v0.7.1-alpha"
package/unique_name="io.woofmeow.netfishing"
package/name="NETfishing"
package/signed=true
@ -214,7 +214,7 @@ custom_features=""
export_filter="all_resources"
include_filter="LICENSE,ASSET-LICENSE.md,TRADEMARKS.md,docs/ATTRIBUTION.md,ui/fonts/*LICENSE.txt"
exclude_filter="builds/*,scripts/*"
export_path="builds/v0.6.8-alpha/linux-x86_64/NETfishing.x86_64"
export_path="builds/v0.7.1-alpha/linux-x86_64/NETfishing.x86_64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""

View file

@ -868,7 +868,7 @@ func _on_cast_completed() -> void:
_cast_origin_position.z + _cast_direction.z * withdrawal_cancel_distance
)
_presentation.set_line_mode(FishingPresentationType.LineMode.SLACK)
status_changed.emit("waiting for a bite...")
status_changed.emit("")
func _consume_active_bait() -> void:
@ -1131,10 +1131,7 @@ func _on_catch_escaped() -> void:
return
_stop_fight_audio()
var fish_name: String = "the fish"
if _selected_fish != null and not _selected_fish.display_name.is_empty():
fish_name = "the %s" % _selected_fish.display_name
_cleanup_attempt("%s got away!" % fish_name, &"escape")
_cleanup_attempt("", &"escape")
func _on_outcome_completed(outcome: StringName) -> void:
@ -1597,7 +1594,7 @@ func _on_network_cast_accepted(
_network_input_resend_elapsed = 0.0
_presentation.show_withdrawal_position(_bobber_water_position)
_presentation.set_line_mode(FishingPresentationType.LineMode.SLACK)
status_changed.emit("waiting for a bite...")
status_changed.emit("")
func _on_network_cast_rejected(message: String) -> void:

View file

@ -1555,8 +1555,13 @@ func _on_pause_join_game_requested(endpoint: String) -> void:
_join_requested_from_title = false
_pending_join_endpoint = endpoint
_game_ui.get_pause_menu().close_for_title_transition()
var preserved_public_join: bool = (
_discovery.preserve_public_join_for_session_switch()
)
_network_session.disconnect_session("Connecting to another game.")
if not _network_session.join_direct(endpoint):
if preserved_public_join:
_discovery.cancel_pending_public_join()
_handle_failed_session_switch(
"Could not begin the direct connection."
)

View file

@ -85,6 +85,7 @@ var _join_request_in_flight: bool = false
var _pending_join_endpoint: String = ""
var _pending_join_token: String = ""
var _pending_join_room_id: String = ""
var _preserve_pending_join_on_inactive: bool = false
var _upnp_thread: Thread
var _upnp_mapping_in_progress: bool = false
var _upnp_operation_is_renewal: bool = false
@ -291,6 +292,17 @@ func is_public_join_preparing() -> bool:
return _join_request_in_flight
func preserve_public_join_for_session_switch() -> bool:
_preserve_pending_join_on_inactive = not _pending_join_token.is_empty()
return _preserve_pending_join_on_inactive
func cancel_pending_public_join() -> void:
_preserve_pending_join_on_inactive = false
_set_public_join_state(PublicJoinState.IDLE)
_clear_pending_join()
func prepare_public_join(room: Dictionary) -> bool:
if _join_request_in_flight:
return false
@ -913,18 +925,30 @@ func _discovery_version_mismatch_message(required_version: String) -> String:
func _on_session_state_changed(state: NetworkSession.State) -> void:
if state == NetworkSession.State.CONNECTING and not _pending_join_token.is_empty():
_preserve_pending_join_on_inactive = false
_set_public_join_state(PublicJoinState.CONNECTING)
_join_probe_timer.start()
call_deferred("_send_pending_join_probe")
elif state in [
NetworkSession.State.JOINED_CLIENT,
NetworkSession.State.SERVER_LOST,
NetworkSession.State.INACTIVE,
]:
_preserve_pending_join_on_inactive = false
_set_public_join_state(PublicJoinState.IDLE)
_join_probe_timer.stop()
_clear_pending_join()
elif state == NetworkSession.State.INACTIVE:
if (
_preserve_pending_join_on_inactive
and not _pending_join_token.is_empty()
):
_preserve_pending_join_on_inactive = false
else:
_set_public_join_state(PublicJoinState.IDLE)
_join_probe_timer.stop()
_clear_pending_join()
elif state == NetworkSession.State.CONNECTION_FAILED:
_preserve_pending_join_on_inactive = false
_set_public_join_state(PublicJoinState.ERROR)
_join_probe_timer.stop()
_clear_pending_join()

View file

@ -953,7 +953,7 @@ func _on_attempt_escaped(peer_id: int) -> void:
if attempt == null:
return
attempt.phase = NetworkFishingAttempt.Phase.ESCAPED
_broadcast_public_outcome(attempt, &"escape", "The fish got away!")
_broadcast_public_outcome(attempt, &"escape", "")
_dispose_attempt(peer_id)

View file

@ -11,7 +11,7 @@ config_version=5
[application]
config/name="NETFISHING"
config/version="0.6.8-alpha"
config/version="0.7.1-alpha"
run/main_scene="res://main/main.tscn"
config/features=PackedStringArray("4.7", "GL Compatibility")
config/icon="res://art/exported/system_icons/netfishing_256.png"

View file

@ -4,14 +4,14 @@ set -euo pipefail
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
readonly BUILD_ROOT="${PROJECT_ROOT}/builds/v0.6.8-alpha"
readonly BUILD_ROOT="${PROJECT_ROOT}/builds/v0.7.1-alpha"
readonly WINDOWS_DIR="${BUILD_ROOT}/windows-x86_64"
readonly LINUX_DIR="${BUILD_ROOT}/linux-x86_64"
readonly README_SOURCE="${PROJECT_ROOT}/docs/README-PLAYTEST.txt"
readonly SOURCE_COMMIT="$(git -C "${PROJECT_ROOT}" rev-parse HEAD)"
readonly SOURCE_URL="https://forge.makearmy.io/woofmeow/netfishing"
readonly WINDOWS_ZIP="${BUILD_ROOT}/NETfishing-v0.6.8-alpha-windows-x86_64.zip"
readonly LINUX_ZIP="${BUILD_ROOT}/NETfishing-v0.6.8-alpha-linux-x86_64.zip"
readonly WINDOWS_ZIP="${BUILD_ROOT}/NETfishing-v0.7.1-alpha-windows-x86_64.zip"
readonly LINUX_ZIP="${BUILD_ROOT}/NETfishing-v0.7.1-alpha-linux-x86_64.zip"
readonly GODOT_BIN="${GODOT_BIN:-godot}"
if [[ ! -f "${PROJECT_ROOT}/project.godot" ]]; then

View file

@ -31,6 +31,9 @@ func _run() -> void:
"%NetworkFishingService"
) as NetworkFishingService
var fishing_spot := main.get_node("%FishingSpot") as FishingSpotType
var game_ui := main.get_node("UIPresentation/UIViewport/GameUI")
var fishing_status := game_ui.get_node("%StatusLabel") as Label
var fishing_panel := game_ui.get_node("%FishingPanel") as PanelContainer
var player := main.get("_player") as Player
assert(session.is_host())
assert(not session.is_open_host())
@ -71,6 +74,9 @@ func _run() -> void:
await process_frame
assert(fishing_spot.state == FishingSpotType.FishingState.WAITING_FOR_BITE)
assert(service.has_local_attempt())
assert(fishing_status.text.is_empty())
assert(not fishing_status.visible)
assert(not fishing_panel.visible)
var attempts: Dictionary = service.get("_attempts")
var attempt: NetworkFishingAttempt = attempts.get(session.get_local_peer_id())
assert(attempt != null)
@ -164,9 +170,12 @@ func _run() -> void:
<= FishQuality.BARRIER_HEALTH_MAXIMUMS[fish_catch.quality]
)
reference_controller.queue_free()
service.call("_cancel_attempt", session.get_local_peer_id(), "")
service.call("_on_attempt_escaped", session.get_local_peer_id())
await process_frame
assert(not service.has_local_attempt())
assert(fishing_status.text.is_empty())
assert(not fishing_status.visible)
assert(not fishing_panel.visible)
print("Fishing authority validation: PASS")
session.disconnect_session("")

View file

@ -206,7 +206,7 @@ func _run() -> void:
assert(int(save_data.get("save_version", -1)) == 7)
assert(PlayerJobService.validate_save_data(save_data.get("jobs", {})))
session.disconnect_session("Job system validation complete.")
_validate_pause_session_switch(main, session)
main.queue_free()
for _frame: int in 4:
await process_frame
@ -215,6 +215,28 @@ func _run() -> void:
quit()
func _validate_pause_session_switch(
main: Node,
session: NetworkSession,
) -> void:
var discovery := main.get_node("%DiscoveryClient") as DiscoveryClient
discovery.set("_pending_join_endpoint", "127.0.0.1:18141")
discovery.set("_pending_join_room_id", "session-switch-room")
discovery.set("_pending_join_token", "session-switch-token")
discovery.call(
"_set_public_join_state",
DiscoveryClient.PublicJoinState.CONNECTING,
)
main.call("_on_pause_join_game_requested", "127.0.0.1:18141")
assert(session.state == NetworkSession.State.CONNECTING)
assert(discovery.get("_pending_join_token") == "session-switch-token")
var join_probe_timer := discovery.get("_join_probe_timer") as Timer
assert(join_probe_timer != null and not join_probe_timer.is_stopped())
session.cancel_connection()
assert(session.state == NetworkSession.State.INACTIVE)
assert(str(discovery.get("_pending_join_token")).is_empty())
func _validate_unavailable_fishnet_layout() -> void:
var unavailable_page := TheNetPage.new()
unavailable_page.size = Vector2(1280.0, 720.0)

View file

@ -456,8 +456,14 @@ func _validate_weather_presentation() -> void:
assert(rain.emitting)
assert(rain.amount_ratio > 0.99)
assert(rain.amount == WorldTimeVisualControllerType.RAIN_PARTICLE_AMOUNT)
assert(rain.visibility_aabb == (
WorldTimeVisualControllerType.RAIN_VISIBILITY_AABB
))
var rain_material := rain.process_material as ParticleProcessMaterial
assert(rain_material != null)
assert(rain_material.emission_box_extents.is_equal_approx(
WorldTimeVisualControllerType.RAIN_EMISSION_EXTENTS
))
assert(is_equal_approx(
rain_material.initial_velocity_min,
WorldTimeVisualControllerType.RAIN_VELOCITY_MIN,

View file

@ -221,7 +221,7 @@ unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_color = Color(0.682, 0.733, 0.761, 1)
theme_override_font_sizes/font_size = 22
text = "v0.6.8-alpha"
text = "v0.7.1-alpha"
horizontal_alignment = 1
[node name="Spacer" type="Control" parent="ResponsiveTitleStage/TitlePresentationScaleRoot/Center/MainContent"]

View file

@ -5,7 +5,12 @@ const UPDATE_INTERVAL_SECONDS: float = 0.1
const SUN_YAW_DEGREES: float = -32.0
const WEATHER_TRANSITION_SECONDS: float = 10.0
const RAIN_EMITTER_OFFSET := Vector3(0.0, 7.0, 0.0)
const RAIN_PARTICLE_AMOUNT: int = 560
const RAIN_EMISSION_EXTENTS := Vector3(13.0, 1.0, 13.0)
const RAIN_VISIBILITY_AABB := AABB(
Vector3(-13.5, -9.0, -13.5),
Vector3(27.0, 12.0, 27.0),
)
const RAIN_PARTICLE_AMOUNT: int = 2240
const RAIN_VELOCITY_MIN: float = 16.0
const RAIN_VELOCITY_MAX: float = 20.0
const RAIN_DROP_SIZE := Vector3(0.014, 0.34, 0.014)
@ -187,14 +192,12 @@ func _prepare_rain() -> void:
_rain.lifetime = 1.25
_rain.fixed_fps = 30
_rain.local_coords = false
_rain.visibility_aabb = AABB(
Vector3(-7.0, -9.0, -7.0), Vector3(14.0, 12.0, 14.0)
)
_rain.visibility_aabb = RAIN_VISIBILITY_AABB
var process_material := ParticleProcessMaterial.new()
process_material.emission_shape = (
ParticleProcessMaterial.EMISSION_SHAPE_BOX
)
process_material.emission_box_extents = Vector3(6.5, 1.0, 6.5)
process_material.emission_box_extents = RAIN_EMISSION_EXTENTS
process_material.direction = Vector3.DOWN
process_material.spread = 5.0
process_material.initial_velocity_min = RAIN_VELOCITY_MIN