Prepare v0.6.8-alpha release

This commit is contained in:
Alexander Sellite 2026-08-13 18:59:19 -04:00
parent dbe0a7b313
commit 12ce0b68ce
15 changed files with 139 additions and 41 deletions

View file

@ -1,6 +1,6 @@
NETfishing
v0.6.7-alpha
Alpha 0.6.7
v0.6.8-alpha
Alpha 0.6.8
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.7-alpha/windows-x86_64/NETfishing.exe"
export_path="builds/v0.6.8-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.7.0"
application/product_version="0.6.7.0"
application/file_version="0.6.8.0"
application/product_version="0.6.8.0"
application/company_name="Woofmeow"
application/product_name="NETfishing"
application/file_description="NETfishing v0.6.7-alpha"
application/file_description="NETfishing v0.6.8-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.7-alpha/linux-arm64/NETfishing.arm64"
export_path="builds/v0.6.8-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.7-alpha/macos/NETfishing.zip"
export_path="builds/v0.6.8-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.7"
application/version="0.6.7"
application/short_version="0.6.8"
application/version="0.6.8"
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.7-alpha/server-linux-x86_64/NETfishingServer.x86_64"
export_path="builds/v0.6.8-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.7-alpha/android/NETfishing.apk"
export_path="builds/v0.6.8-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=60700
version/name="v0.6.7-alpha"
version/code=60800
version/name="v0.6.8-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.7-alpha/linux-x86_64/NETfishing.x86_64"
export_path="builds/v0.6.8-alpha/linux-x86_64/NETfishing.x86_64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""

View file

@ -1078,6 +1078,8 @@ func _confirm_server_trust() -> void:
_server_trust_dialog.ok_button_text = "Replace Pin"
_server_trust_dialog.popup_centered(Vector2i(520, 260))
return
if _server_trust_dialog != null:
_server_trust_dialog.hide()
_network_session.resolve_server_trust(true)

View file

@ -11,7 +11,7 @@ config_version=5
[application]
config/name="NETFISHING"
config/version="0.6.7-alpha"
config/version="0.6.8-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.7-alpha"
readonly BUILD_ROOT="${PROJECT_ROOT}/builds/v0.6.8-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.7-alpha-windows-x86_64.zip"
readonly LINUX_ZIP="${BUILD_ROOT}/NETfishing-v0.6.7-alpha-linux-x86_64.zip"
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 GODOT_BIN="${GODOT_BIN:-godot}"
if [[ ! -f "${PROJECT_ROOT}/project.godot" ]]; then

View file

@ -84,6 +84,37 @@ run_test() {
--headless --path "${PROJECT_ROOT}" --script "${script}"
}
wait_for_network_host() {
local script="$1"
local host_pid="$2"
local test_port="7777"
local declared_port
declared_port="$(
sed -n -E \
's/^const TEST_PORT(: int)? = ([0-9]+)$/\2/p' \
"${PROJECT_ROOT}/${script}"
)"
if [[ -n "${declared_port}" ]]; then
test_port="${declared_port}"
fi
if ! command -v ss >/dev/null 2>&1; then
sleep 2
return 0
fi
for _attempt in {1..100}; do
if ! kill -0 "${host_pid}" 2>/dev/null; then
return 1
fi
if ss -H -lun "sport = :${test_port}" | grep -q .; then
return 0
fi
sleep 0.1
done
return 1
}
run_network_test() {
local script="$1"
local name="${script#tests/}"
@ -99,7 +130,17 @@ run_network_test() {
--headless --path "${PROJECT_ROOT}" --script "${script}" -- host \
>"${host_root}/output.log" 2>&1 &
host_pid=$!
sleep 0.75
if ! wait_for_network_host "${script}" "${host_pid}"; then
set +e
wait "${host_pid}"
host_status=$?
set -e
printf '%s\n' '-- host output --'
sed -n '1,240p' "${host_root}/output.log"
printf 'error: host did not become ready (exit %d)\n' \
"${host_status}" >&2
return 1
fi
set +e
XDG_DATA_HOME="${client_root}/data" \
XDG_CONFIG_HOME="${client_root}/config" \

View file

@ -168,14 +168,14 @@ func _run() -> void:
"error": {
"code": "game_version_mismatch",
"message": "generic mismatch",
"required_game_version": "0.6.8-alpha",
"required_game_version": "99.0.0-alpha",
},
}
var outdated_message: String = str(
discovery.call("_request_failure", outdated_discovery_error)
)
assert("out of date" in outdated_message)
assert("0.6.8-alpha" in outdated_message)
assert("99.0.0-alpha" in outdated_message)
assert("will not be listed" in outdated_message)
discovery.set(
"_host_request_kind",
@ -196,7 +196,7 @@ func _run() -> void:
"error": {
"code": "game_version_mismatch",
"message": "generic mismatch",
"required_game_version": "0.6.6-alpha",
"required_game_version": "0.0.0-alpha",
},
}
var newer_message: String = str(

View file

@ -84,6 +84,7 @@ func _run() -> void:
main.queue_free()
for _frame: int in 4:
await process_frame
await create_timer(0.1).timeout
quit()
@ -97,7 +98,10 @@ func _run_multiplayer_host() -> void:
var session := main.get_node("%NetworkSession") as NetworkSession
assert(session.set_host_open(true))
var client_connected := false
var connection_deadline: int = Time.get_ticks_msec() + 30000
# Loading the full client world can take longer on a cold import. Keep the
# host available until the client has completed authentication rather than
# timing out while the client is still starting.
var connection_deadline: int = Time.get_ticks_msec() + 60000
while Time.get_ticks_msec() < connection_deadline:
await process_frame
if session.get_authenticated_peer_ids().size() >= 2:

View file

@ -32,7 +32,7 @@ func _run_host() -> void:
"%NetworkFishingService"
) as NetworkFishingService
var join_deadline: int = Time.get_ticks_msec() + 20000
var join_deadline: int = Time.get_ticks_msec() + 60000
while (
Time.get_ticks_msec() < join_deadline
and session.get_authenticated_peer_ids().size() < 2
@ -55,7 +55,7 @@ func _run_host() -> void:
var remote_visuals := remote_avatar.get_node("Visuals") as Node3D
remote_visuals.rotation.y = PI * 0.5
session.publish_authoritative_teleport(remote_peer_id)
var aiming_deadline: int = Time.get_ticks_msec() + 5000
var aiming_deadline: int = Time.get_ticks_msec() + 15000
while (
Time.get_ticks_msec() < aiming_deadline
and int(remote_avatar.get("_fishing_visual_phase"))
@ -110,7 +110,7 @@ func _run_host() -> void:
Player.FishingVisualPhase.FISHING,
]
)
var sitting_deadline: int = Time.get_ticks_msec() + 3000
var sitting_deadline: int = Time.get_ticks_msec() + 10000
while Time.get_ticks_msec() < sitting_deadline and not remote_avatar.is_sitting():
await process_frame
assert(remote_avatar.is_sitting())
@ -139,6 +139,12 @@ func _run_host() -> void:
int(remote_avatar.get("_fishing_visual_phase"))
== Player.FishingVisualPhase.RETRACT
)
var retract_animation_deadline: int = Time.get_ticks_msec() + 3000
while (
Time.get_ticks_msec() < retract_animation_deadline
and remote_animation_player.current_animation != &"retract_sit"
):
await process_frame
assert(remote_animation_player.current_animation == &"retract_sit")
var completion_deadline: int = Time.get_ticks_msec() + 12000
@ -209,7 +215,7 @@ func _run_client() -> void:
for _frame: int in 30:
await physics_frame
player.set_fishing_visual(false)
player.call("_set_sitting", true)
player.call("_set_sitting", true, true)
assert(player.is_sitting())
for _frame: int in 15:
await physics_frame
@ -303,6 +309,12 @@ func _run_client() -> void:
int(player.get("_fishing_visual_phase"))
== Player.FishingVisualPhase.RETRACT
)
var retract_animation_deadline: int = Time.get_ticks_msec() + 3000
while (
Time.get_ticks_msec() < retract_animation_deadline
and character_animation_player.current_animation != &"retract_sit"
):
await process_frame
assert(character_animation_player.current_animation == &"retract_sit")
var bobber := fishing_spot.get_node(
"FishingPresentation/Bobber"

View file

@ -162,6 +162,34 @@ func _validate_portable_water_body() -> void:
func _validate_starter_region_surfaces() -> void:
var region := StarterRegionScene.instantiate() as Node3D
root.add_child(region)
var ocean_region := region.get_node(
"WaterBodies/Ocean/FishingRegions/OceanFishingRegion"
) as FishableWaterRegionType
var minimum_x: float = INF
var maximum_x: float = -INF
var minimum_z: float = INF
var maximum_z: float = -INF
for child: Node in ocean_region.get_children():
var shape_node := child as CollisionShape3D
assert(shape_node != null and shape_node.shape is BoxShape3D)
var box := shape_node.shape as BoxShape3D
assert(is_equal_approx(box.size.y, 2.0))
minimum_x = minf(minimum_x, shape_node.position.x - box.size.x * 0.5)
maximum_x = maxf(maximum_x, shape_node.position.x + box.size.x * 0.5)
minimum_z = minf(minimum_z, shape_node.position.z - box.size.z * 0.5)
maximum_z = maxf(maximum_z, shape_node.position.z + box.size.z * 0.5)
var ocean_footprint := Vector2(
maximum_x - minimum_x,
maximum_z - minimum_z,
)
assert(is_equal_approx(
ocean_footprint.x * ocean_footprint.y,
12840.0,
))
assert(is_equal_approx(
ocean_footprint.x / 107.0,
ocean_footprint.y / 80.0,
))
var fishing_spot := FishingSpotScene.instantiate() as FishingSpotType
root.add_child(fishing_spot)
await physics_frame
@ -179,6 +207,14 @@ func _validate_starter_region_surfaces() -> void:
)
assert(ocean.is_fishable())
assert(is_equal_approx(ocean.position.y, -0.45))
var expanded_ocean: FishingSurfaceSampleType = (
fishing_spot.resolve_fishing_surface(
Vector3(72.0, -0.45, 0.0),
4.0,
)
)
assert(expanded_ocean.is_fishable())
assert(is_equal_approx(expanded_ocean.position.y, -0.45))
var covered_ocean: FishingSurfaceSampleType = (
fishing_spot.resolve_fishing_surface(
Vector3(20.0, -0.45, 0.0),

View file

@ -97,6 +97,7 @@ func _run() -> void:
main.queue_free()
for _frame: int in 4:
await process_frame
await create_timer(0.1).timeout
quit()

View file

@ -1517,7 +1517,9 @@ func _refresh_gameplay_hud_visibility() -> void:
and not _shop_open
)
_gameplay_transient_hud.visible = show_world_hud
_experience_presentation.visible = show_world_hud
_experience_presentation.visible = (
_gameplay_ui_enabled and not _gameplay_hud_hidden
)
func set_system_menu_open(is_open: bool) -> void:

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.7-alpha"
text = "v0.6.8-alpha"
horizontal_alignment = 1
[node name="Spacer" type="Control" parent="ResponsiveTitleStage/TitlePresentationScaleRoot/Center/MainContent"]

View file

@ -1,4 +1,4 @@
[gd_resource type="ArrayMesh" format=4]
[gd_resource type="ArrayMesh" format=4 uid="uid://dmgps6rhbdjlw"]
[resource]
_surfaces = [{

View file

@ -37,23 +37,23 @@ size = Vector2(10000, 10000)
[sub_resource type="BoxShape3D" id="OceanWestShape"]
resource_local_to_scene = true
size = Vector3(17, 2, 80)
size = Vector3(20.820662814, 2, 97.979589711)
[sub_resource type="BoxShape3D" id="OceanEastShape"]
resource_local_to_scene = true
size = Vector3(42, 2, 80)
size = Vector3(51.439284598, 2, 97.979589711)
[sub_resource type="BoxShape3D" id="OceanNorthShape"]
resource_local_to_scene = true
size = Vector3(48, 2, 18)
size = Vector3(58.787753827, 2, 22.045407685)
[sub_resource type="BoxShape3D" id="OceanSouthShape"]
resource_local_to_scene = true
size = Vector3(48, 2, 18)
size = Vector3(58.787753827, 2, 22.045407685)
[sub_resource type="BoxShape3D" id="OceanCenterShape"]
resource_local_to_scene = true
size = Vector3(48, 2, 44)
size = Vector3(58.787753827, 2, 53.888774341)
[sub_resource type="BoxShape3D" id="OceanWestRecoveryShape"]
resource_local_to_scene = true
@ -180,23 +180,23 @@ fish_pool = ExtResource("4_pool")
surface_height_mode = 1
[node name="WestShape" type="CollisionShape3D" parent="WaterBodies/Ocean/FishingRegions/OceanFishingRegion" unique_id=357406062]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -45.5, -1, 0)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -55.613519213, -1, 0)
shape = SubResource("OceanWestShape")
[node name="EastShape" type="CollisionShape3D" parent="WaterBodies/Ocean/FishingRegions/OceanFishingRegion" unique_id=772224738]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 32, -1, 0)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 39.30420832, -1, 0)
shape = SubResource("OceanEastShape")
[node name="NorthShape" type="CollisionShape3D" parent="WaterBodies/Ocean/FishingRegions/OceanFishingRegion" unique_id=646147646]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, -1, 31)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15.809310892, -1, 37.967091013)
shape = SubResource("OceanNorthShape")
[node name="SouthShape" type="CollisionShape3D" parent="WaterBodies/Ocean/FishingRegions/OceanFishingRegion" unique_id=894083854]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13, -1, -31)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15.809310892, -1, -37.967091013)
shape = SubResource("OceanSouthShape")
[node name="CenterShape" type="CollisionShape3D" parent="WaterBodies/Ocean/FishingRegions/OceanFishingRegion"]
position = Vector3(-13, -1, 0)
position = Vector3(-15.809310892, -1, 0)
shape = SubResource("OceanCenterShape")
[node name="RecoveryRegions" type="Node3D" parent="WaterBodies/Ocean" unique_id=463706703]