Compare commits

..

No commits in common. "main" and "v0.18.1-alpha" have entirely different histories.

170 changed files with 1675 additions and 4332 deletions

View file

@ -1,15 +1,15 @@
# straywild Asset License 1.1
# NETfishing Asset License 1.1
Copyright © 2026 Woofmeow. All rights reserved except for the permissions
expressly granted below.
## 1. Scope
This license applies to original straywild artwork, graphics, textures,
This license applies to original NETfishing artwork, graphics, textures,
models, animations, music, sound recordings, narrative content, visual
designs, characters, and other creative assets owned by the straywild owners
designs, characters, and other creative assets owned by the NETfishing owners
or licensed to them with authority to sublicense, publishing as Woofmeow (the
**“straywild Assets”**).
**“NETfishing Assets”**).
It does not apply to:
@ -17,77 +17,77 @@ It does not apply to:
- third-party material identified in the source repository's
`docs/ATTRIBUTION.md` or the packaged `ATTRIBUTION.md` notice;
- material accompanied by a different license; or
- the straywild and Woofmeow names and logos, which are addressed in
- the NETfishing and Woofmeow names and logos, which are addressed in
`TRADEMARKS.md`.
Repository location alone does not change third-party ownership or licensing.
## 2. Definitions
**Official straywild Software** means:
**Official NETfishing Software** means:
- an unmodified binary release published by the straywild owners through an
official straywild distribution channel; or
- a build made from an unmodified official straywild source release or tagged
- an unmodified binary release published by the NETfishing owners through an
official NETfishing distribution channel; or
- a build made from an unmodified official NETfishing source release or tagged
revision.
**Mod** means a non-standalone add-on created to operate with Official
straywild Software. A Mod may add, replace, or alter content loaded by the
Official straywild Software, but it may not redistribute a replacement copy
NETfishing Software. A Mod may add, replace, or alter content loaded by the
Official NETfishing Software, but it may not redistribute a replacement copy
of the game or represent a fork, clone, sequel, or separate game.
**Contribution Fork** means a source-control fork or clone of an official
straywild source repository that is created and maintained in good faith
NETfishing source repository that is created and maintained in good faith
primarily to prepare, test, review, or submit changes for possible inclusion
in Official straywild Software. It does not include a fork presented or
in Official NETfishing Software. It does not include a fork presented or
developed as an independent game, community edition, replacement distribution,
or ongoing product separate from the official straywild project.
or ongoing product separate from the official NETfishing project.
## 3. Permission to use the official game
You may reproduce straywild Assets as technically necessary to install, run,
back up, and privately modify a lawfully obtained copy of Official straywild
You may reproduce NETfishing Assets as technically necessary to install, run,
back up, and privately modify a lawfully obtained copy of Official NETfishing
Software.
You may capture, publish, and monetize screenshots, gameplay videos,
livestreams, reviews, tutorials, and similar commentary showing a lawfully
obtained copy of straywild. This permission does not authorize redistribution
obtained copy of NETfishing. This permission does not authorize redistribution
of the source asset files or imply endorsement.
## 4. Community Mod license
Subject to this license, you may create, modify, and distribute straywild
Assets solely as part of a Mod for Official straywild Software.
Subject to this license, you may create, modify, and distribute NETfishing
Assets solely as part of a Mod for Official NETfishing Software.
This permission is worldwide, nonexclusive, royalty-free, and available for
as long as you comply with this license. It permits only the copies of
straywild Assets reasonably necessary for the Mod to function. It does not
NETfishing Assets reasonably necessary for the Mod to function. It does not
permit distributing the original game, a substantially complete collection of
its assets, or a general-purpose asset pack.
A distributed Mod must:
1. require a separately obtained copy of Official straywild Software;
1. require a separately obtained copy of Official NETfishing Software;
2. be presented as unofficial community content;
3. include the following notice in its documentation or distribution page:
> Contains or adapts straywild assets © 2026 Woofmeow, used under the
> straywild Asset License 1.1. This Mod is unofficial and is not endorsed
> Contains or adapts NETfishing assets © 2026 Woofmeow, used under the
> NETfishing Asset License 1.1. This Mod is unofficial and is not endorsed
> by Woofmeow.
4. identify material created by the Mod author separately from straywild
4. identify material created by the Mod author separately from NETfishing
Assets; and
5. comply with `TRADEMARKS.md`.
Mods may be shared without charge and may accept voluntary donations that do
not purchase access, features, or preferential treatment. Selling a Mod,
charging for access to it, licensing it commercially, or using straywild
charging for access to it, licensing it commercially, or using NETfishing
Assets in paid products requires separate written permission from both
straywild owners.
NETfishing owners.
## 5. Contribution Fork license
Subject to this license, you may reproduce, modify, and distribute straywild
Subject to this license, you may reproduce, modify, and distribute NETfishing
Assets within a Contribution Fork. You may also make the nonpublic builds
reasonably necessary to develop, test, and review its proposed contribution.
@ -99,8 +99,8 @@ fork are permitted distributions.
A Contribution Fork must:
1. remain primarily directed toward preparing changes for possible inclusion
in the official straywild project;
2. preserve this license and the official straywild project's applicable
in the official NETfishing project;
2. preserve this license and the official NETfishing project's applicable
attribution, third-party license, and copyright notices;
3. remain visibly linked to or identified as a fork of the official source
repository and not be presented as official or endorsed;
@ -109,63 +109,63 @@ A Contribution Fork must:
contribution;
5. not publish general-audience binaries, releases, packages, or downloads,
operate a persistent public alternative service, or monetize access;
6. not distribute the straywild Assets as a standalone extraction, archive,
6. not distribute the NETfishing Assets as a standalone extraction, archive,
or general-purpose asset pack; and
7. comply with `TRADEMARKS.md`.
Temporary access-controlled servers may be operated when reasonably necessary
to test a proposed contribution. They may not be promoted or maintained as a
public alternative to Official straywild Software or its services.
public alternative to Official NETfishing Software or its services.
Submitting work from a Contribution Fork is governed separately by
`CONTRIBUTOR-TERMS.md` and does not require the straywild owners to accept the
`CONTRIBUTOR-TERMS.md` and does not require the NETfishing owners to accept the
work. Declining or closing a proposed contribution does not retroactively
invalidate good-faith use under this section. A compliant Contribution Fork
may remain publicly accessible as an archival development record, but it may
not be repurposed for continued development or distribution of a separate
product containing straywild Assets.
product containing NETfishing Assets.
## 6. Uses not permitted
Except as expressly permitted by Sections 3, 4, and 5 or by separate written
permission from both straywild owners, you may not use or distribute
straywild Assets:
permission from both NETfishing owners, you may not use or distribute
NETfishing Assets:
- in a fork, clone, remake, sequel, or standalone game that is not a qualifying
Contribution Fork;
- with a modified distribution of the GPL-covered straywild code that is not
Official straywild Software, except for nonpublic contribution-testing
- with a modified distribution of the GPL-covered NETfishing code that is not
Official NETfishing Software, except for nonpublic contribution-testing
builds permitted by Section 5;
- in another game, application, asset library, template, or merchandise;
- as a substantially complete asset extraction or archive;
- in a way that implies sponsorship, endorsement, or official status;
- to register a confusingly similar trademark, domain, account, or product
identity; or
- under terms that claim ownership of the straywild Assets themselves.
- under terms that claim ownership of the NETfishing Assets themselves.
The GPL permits forks and redistribution of the GPL-covered code. Except for a
qualifying Contribution Fork under Section 5, this asset license does not
permit those forks to carry straywild Assets. A code fork that is not a
Contribution Fork must remove or replace the straywild Assets and reserved
permit those forks to carry NETfishing Assets. A code fork that is not a
Contribution Fork must remove or replace the NETfishing Assets and reserved
branding unless both owners grant separate written permission.
## 7. Ownership of Mods and contribution work
You retain ownership of your original Mod material and original material
created in a Contribution Fork. The straywild owners retain ownership of the
straywild Assets and adaptations of those assets to the extent provided by
created in a Contribution Fork. The NETfishing owners retain ownership of the
NETfishing Assets and adaptations of those assets to the extent provided by
applicable law.
This license does not require you to assign or submit your original material.
It also does not grant you ownership of the underlying straywild Assets. If
you intentionally submit material for inclusion in straywild,
It also does not grant you ownership of the underlying NETfishing Assets. If
you intentionally submit material for inclusion in NETfishing,
`CONTRIBUTOR-TERMS.md` applies separately.
## 8. Termination and cure
Your permissions under this license terminate automatically if you violate
its terms. They are reinstated provisionally when you stop the violation and
permanently if both straywild owners do not notify you of the violation
permanently if both NETfishing owners do not notify you of the violation
within sixty days after it has been cured.
Termination does not limit remedies available for activity outside this
@ -173,15 +173,15 @@ license.
## 9. No warranty
THE straywild ASSETS ARE PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND,
THE NETFISHING ASSETS ARE PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, TITLE, OR NON-INFRINGEMENT. TO THE MAXIMUM EXTENT
PERMITTED BY LAW, THE OWNERS WILL NOT BE LIABLE FOR ANY CLAIM, DAMAGES, OR
OTHER LIABILITY ARISING FROM THIS LICENSE OR USE OF THE straywild ASSETS.
OTHER LIABILITY ARISING FROM THIS LICENSE OR USE OF THE NETFISHING ASSETS.
## 10. Additional permission
Uses not granted here require written permission from both straywild owners.
Uses not granted here require written permission from both NETfishing owners.
A permission granted to one person or project does not amend this license for
others.

View file

@ -1,6 +1,6 @@
# Contribution policy
straywild is an owner-directed Woofmeow project and is not accepting
NETfishing is an owner-directed Woofmeow project and is not accepting
unsolicited contributions. Please do not submit pull requests, patches, code,
artwork, models, audio, writing, documentation, translations, designs, or
other implementation work. Pull requests are disabled for the official
@ -17,7 +17,7 @@ work; it is not a standing invitation to contribute.
## Contribution forks
The [straywild Asset License](ASSET-LICENSE.md) contains limited permissions
The [NETfishing Asset License](ASSET-LICENSE.md) contains limited permissions
for qualifying Contribution Forks. Those permissions do not promise review or
acceptance and do not override the policy above. Keep the hosting platform's
fork relationship visible, preserve all license and attribution notices, and
@ -79,4 +79,4 @@ using display strings as persistent identifiers.
New standalone source files should use `SPDX-License-Identifier:
GPL-3.0-or-later` where the file format permits comments. Do not add that
identifier to asset files governed by the straywild Asset License.
identifier to asset files governed by the NETfishing Asset License.

View file

@ -1,6 +1,6 @@
# straywild contributor terms
# NETfishing contributor terms
straywild does not accept unsolicited contributions. These terms are retained
NETfishing does not accept unsolicited contributions. These terms are retained
as the governing record for contributions previously accepted after their
publication and for specific future work that both Owners expressly invite in
writing before submission. They are not a request or standing invitation for
@ -9,9 +9,9 @@ patches, pull requests, assets, or other material.
These terms do not retroactively change ownership of earlier work or replace a
separately signed agreement.
“Owners” means the two straywild co-owners who publish the Project as
“Owners” means the two NETfishing co-owners who publish the Project as
Woofmeow and are publicly credited as Voyager and Endeavour. “Project” means
the official straywild game, its servers, tools, documentation, websites,
the official NETfishing game, its servers, tools, documentation, websites,
ports, updates, and promotional materials.
## 1. Your ownership and authority
@ -56,8 +56,8 @@ royalty-free, transferable, and sublicensable license to:
- license it to Project users under `ASSET-LICENSE.md` or a later Project asset
license jointly approved by the Owners.
This grant is limited to straywild, its promotion, and official successor or
derived straywild products. It does not transfer your copyright or authorize
This grant is limited to NETfishing, its promotion, and official successor or
derived NETfishing products. It does not transfer your copyright or authorize
the Owners to sell your contribution as an unrelated standalone asset.
## 4. Documentation accompanying code
@ -78,7 +78,7 @@ or release.
## 6. No automatic ownership, employment, or payment
Submitting a contribution does not provide ownership of straywild, create an
Submitting a contribution does not provide ownership of NETfishing, create an
employment, agency, partnership, or fiduciary relationship, or create a right
to compensation. Any payment, ownership, or employment arrangement requires a
separate written agreement signed by the appropriate parties.

View file

@ -1,6 +1,6 @@
# straywild
# NETfishing
straywild is a multiplayer-first fishing game built with Godot 4.7. The
NETfishing is a multiplayer-first fishing game built with Godot 4.7. The
current pre-alpha includes host-authoritative fishing and economy flows,
freshwater and saltwater habitats, persistent player data, social features,
customization, jobs, and a controller-aware interface.
@ -8,39 +8,39 @@ customization, jobs, and a controller-aware interface.
The project is under active development. Interfaces, balance, content, and
save migrations may continue to change before a stable release.
straywild is developed and published by **Woofmeow**, the independent team of
NETfishing is developed and published by **Woofmeow**, the independent team of
co-owners publicly credited as Voyager and Endeavour.
## Links
Patreon: https://www.patreon.com/cw/woofmeowgames
Steam: https://store.steampowered.com/app/5068950/straywild/
Steam: https://store.steampowered.com/app/5068950/NETfishing/
Itch.io: https://sol6-vi.itch.io/straywild
Itch.io: https://sol6-vi.itch.io/netfishing
Discord: https://discord.gg/5gP22447kc
Matrix: https://matrix.to/#/#straywild:matrix.makearmy.io
Matrix: https://matrix.to/#/#netfishing:matrix.makearmy.io
Repo: https://forge.makearmy.io/woofmeow/straywild
Repo: https://forge.makearmy.io/woofmeow/netfishing
Releases: https://forge.makearmy.io/woofmeow/straywild/releases
Releases: https://forge.makearmy.io/woofmeow/netfishing/releases
## Installing release builds
Download and extract the archive for your platform from the official release
page, then run straywild from the extracted platform folder.
page, then run NETfishing from the extracted platform folder.
### macOS
Current macOS builds are not signed or notarized. macOS may block the first
launch because it cannot verify the developer. Control-click the straywild
launch because it cannot verify the developer. Control-click the NETfishing
application, choose **Open**, then confirm **Open**. If that option is not
available, attempt to open the application once, then use **System Settings →
Privacy & Security → Open Anyway**.
Only bypass this warning for a straywild build downloaded from an official
Only bypass this warning for a NETfishing build downloaded from an official
project release.
## Requirements
@ -110,10 +110,10 @@ world and UI authoring, and testing are consolidated in
- Project-owned software code is licensed under
[GPL-3.0-or-later](LICENSE).
- Project-owned artwork, models, music, and other creative assets are covered
by the [straywild Asset License](ASSET-LICENSE.md). It permits community
Mods for official straywild software and narrowly scoped contribution forks,
by the [NETfishing Asset License](ASSET-LICENSE.md). It permits community
Mods for official NETfishing software and narrowly scoped contribution forks,
but not independent forks, clones, or unrelated products.
- The straywild and Woofmeow names and branding are reserved as described in
- The NETfishing and Woofmeow names and branding are reserved as described in
[TRADEMARKS.md](TRADEMARKS.md).
- Third-party materials retain their own terms; see the consolidated
[credits, notices, and provenance record](docs/ATTRIBUTION.md).

View file

@ -1,7 +1,7 @@
# straywild and Woofmeow branding
# NETfishing and Woofmeow branding
The straywild and Woofmeow names, logos, icons, trade dress, and other source
identifiers are reserved by the straywild owners, publishing as Woofmeow.
The NETfishing and Woofmeow names, logos, icons, trade dress, and other source
identifiers are reserved by the NETfishing owners, publishing as Woofmeow.
Their presence in a GPL-licensed repository does not grant trademark rights or
imply permission to represent another product as official.
@ -10,30 +10,30 @@ exist through use and other law.
## Permitted references
You may use the names straywild and Woofmeow truthfully to:
You may use the names NETfishing and Woofmeow truthfully to:
- refer to the official game or development team;
- state that software interoperates with or is a Mod for straywild;
- state that software interoperates with or is a Mod for NETfishing;
- link to an official repository or distribution page; and
- discuss, review, criticize, or report on the Project.
Use only the amount of branding reasonably necessary to identify the Project.
Do not imply sponsorship, certification, endorsement, or official status.
An unofficial Mod may use wording such as “Example Mod for straywild” if its
An unofficial Mod may use wording such as “Example Mod for NETfishing” if its
name and presentation remain clearly distinct and it displays an unofficial
notice.
## Contribution forks
A qualifying Contribution Fork under `ASSET-LICENSE.md` may retain the
straywild and Woofmeow names, logos, icons, and trade dress already present in
NETfishing and Woofmeow names, logos, icons, and trade dress already present in
the official source repository solely as necessary to reproduce, modify, and
test the Project while preparing a proposed contribution. The source-control
host's visible fork relationship or an equivalent repository notice must make
its unofficial contribution purpose clear.
This permission does not allow a Contribution Fork to use straywild or
This permission does not allow a Contribution Fork to use NETfishing or
Woofmeow branding to advertise a public build, release, service, community
edition, or independent product. It does not imply acceptance, sponsorship,
endorsement, or official status.
@ -44,7 +44,7 @@ The GNU GPL permits forks and redistribution of covered code. A fork or
modified distribution that is not a qualifying Contribution Fork must:
- use a distinct product name;
- remove straywild and Woofmeow logos, icons, and official trade dress;
- remove NETfishing and Woofmeow logos, icons, and official trade dress;
- avoid confusingly similar names, domains, package identifiers, and account
names; and
- clearly identify itself as independent and unofficial.
@ -53,4 +53,4 @@ These branding terms do not limit rights granted by the GPL to the software
code or lawful nominative, descriptive, comparative, or fair use.
Permission for broader branding use must be obtained in writing from both
straywild owners.
NETfishing owners.

View file

@ -1,6 +1,6 @@
[plugin]
name="straywild Shoreline Auto-Baker"
name="NETfishing Shoreline Auto-Baker"
description="Rebuilds configured static shoreline ribbons after authored terrain reimports."
author="woofmeow"
version="1.0.0"

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://w7n4gjqq1juc"
path="res://.godot/imported/straywild_base_character.glb-65021653e51a906d3b4a3494f170317f.scn"
path="res://.godot/imported/netfishing_base_character.glb-0167c087f16181d405afb962dc877d2c.scn"
[deps]
source_file="res://art/exported/characters/base/straywild_base_character.glb"
dest_files=["res://.godot/imported/straywild_base_character.glb-65021653e51a906d3b4a3494f170317f.scn"]
source_file="res://art/exported/characters/base/netfishing_base_character.glb"
dest_files=["res://.godot/imported/netfishing_base_character.glb-0167c087f16181d405afb962dc877d2c.scn"]
[params]

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dyjwgkgw0syo8"
path.s3tc="res://.godot/imported/straywild_base_character_eyes_simple_shine.png-200a946ddace2078bbe44addb4e4524c.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_base_character_eyes_simple_shine.png-200a946ddace2078bbe44addb4e4524c.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/exported/characters/base/straywild_base_character_eyes_simple_shine.png"
dest_files=["res://.godot/imported/straywild_base_character_eyes_simple_shine.png-200a946ddace2078bbe44addb4e4524c.s3tc.ctex", "res://.godot/imported/straywild_base_character_eyes_simple_shine.png-200a946ddace2078bbe44addb4e4524c.etc2.ctex"]
source_file="res://art/exported/characters/base/netfishing_base_character_eyes_simple_shine.png"
dest_files=["res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.s3tc.ctex", "res://.godot/imported/netfishing_base_character_eyes_simple_shine.png-140bfa3aa0b6f662e8ff9e5721213a61.etc2.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dt5gitdtjdvcd"
path.s3tc="res://.godot/imported/straywild_base_character_mouth_three.png-5bcf329b31a11eff496760a63e62d0e2.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_base_character_mouth_three.png-5bcf329b31a11eff496760a63e62d0e2.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/exported/characters/base/straywild_base_character_mouth_three.png"
dest_files=["res://.godot/imported/straywild_base_character_mouth_three.png-5bcf329b31a11eff496760a63e62d0e2.s3tc.ctex", "res://.godot/imported/straywild_base_character_mouth_three.png-5bcf329b31a11eff496760a63e62d0e2.etc2.ctex"]
source_file="res://art/exported/characters/base/netfishing_base_character_mouth_three.png"
dest_files=["res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.s3tc.ctex", "res://.godot/imported/netfishing_base_character_mouth_three.png-90b4a98403d2a291a56a8ed42aaa8473.etc2.ctex"]
[params]

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bmho1ryst3smt"
path.s3tc="res://.godot/imported/straywild_base_character_nose_dog_round.png-e6909a2c139cf4a2748c2b79d1e12d92.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_base_character_nose_dog_round.png-e6909a2c139cf4a2748c2b79d1e12d92.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/exported/characters/base/straywild_base_character_nose_dog_round.png"
dest_files=["res://.godot/imported/straywild_base_character_nose_dog_round.png-e6909a2c139cf4a2748c2b79d1e12d92.s3tc.ctex", "res://.godot/imported/straywild_base_character_nose_dog_round.png-e6909a2c139cf4a2748c2b79d1e12d92.etc2.ctex"]
source_file="res://art/exported/characters/base/netfishing_base_character_nose_dog_round.png"
dest_files=["res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.s3tc.ctex", "res://.godot/imported/netfishing_base_character_nose_dog_round.png-0008adff5271dd0403e610ef13dd52cf.etc2.ctex"]
[params]

Binary file not shown.

View file

@ -1,45 +0,0 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dsa6yss1sxfcy"
path="res://.godot/imported/net.glb-cbbc53905aec6a50c4a3322ca7a93b1e.scn"
[deps]
source_file="res://art/exported/items/equipment/net.glb"
dest_files=["res://.godot/imported/net.glb-cbbc53905aec6a50c4a3322ca7a93b1e.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

View file

@ -1,45 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://binoqhg45vgbs"
path.s3tc="res://.godot/imported/net_Material.png-f4c4b0400561bc2751fe719b6b1a1e1a.s3tc.ctex"
path.etc2="res://.godot/imported/net_Material.png-f4c4b0400561bc2751fe719b6b1a1e1a.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={
"md5": "ef2c2ae657c9460c90eb808ba5217f39"
}
[deps]
source_file="res://art/exported/items/equipment/net_Material.png"
dest_files=["res://.godot/imported/net_Material.png-f4c4b0400561bc2751fe719b6b1a1e1a.s3tc.ctex", "res://.godot/imported/net_Material.png-f4c4b0400561bc2751fe719b6b1a1e1a.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View file

@ -1,45 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cdsabucjy5rpk"
path.s3tc="res://.godot/imported/net_Plane Base Color.png-3875ae3dd186ddf319c55aabb13e663f.s3tc.ctex"
path.etc2="res://.godot/imported/net_Plane Base Color.png-3875ae3dd186ddf319c55aabb13e663f.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={
"md5": "a6001c381d4c8e16bd2d64ea74ccff82"
}
[deps]
source_file="res://art/exported/items/equipment/net_Plane Base Color.png"
dest_files=["res://.godot/imported/net_Plane Base Color.png-3875ae3dd186ddf319c55aabb13e663f.s3tc.ctex", "res://.godot/imported/net_Plane Base Color.png-3875ae3dd186ddf319c55aabb13e663f.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View file

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bkh5hw8wwu8pc"
path="res://.godot/imported/straywild_1024.png-b9b5c159c9fcecc21b04324370d4522f.ctex"
path="res://.godot/imported/netfishing_1024.png-7c53a099ed2743b4a623c258641b1d29.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/exported/system_icons/straywild_1024.png"
dest_files=["res://.godot/imported/straywild_1024.png-b9b5c159c9fcecc21b04324370d4522f.ctex"]
source_file="res://art/exported/system_icons/netfishing_1024.png"
dest_files=["res://.godot/imported/netfishing_1024.png-7c53a099ed2743b4a623c258641b1d29.ctex"]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View file

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cty16m8ydla06"
path="res://.godot/imported/straywild_256.png-87b7e62e710eae4d3e3ed24a8454ca6d.ctex"
path="res://.godot/imported/netfishing_256.png-d9dfc9c7871ac38bc73d09d00df679be.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/exported/system_icons/straywild_256.png"
dest_files=["res://.godot/imported/straywild_256.png-87b7e62e710eae4d3e3ed24a8454ca6d.ctex"]
source_file="res://art/exported/system_icons/netfishing_256.png"
dest_files=["res://.godot/imported/netfishing_256.png-d9dfc9c7871ac38bc73d09d00df679be.ctex"]
[params]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cb4bcakhoprm8"
path="res://.godot/imported/straywild_base_character.blend-02abbfdb9b1d393f1bd3cfface615e27.scn"
path="res://.godot/imported/netfishing_base_character.blend-65bf3bc5b77cc1a37fa3f81ebd808d37.scn"
[deps]
source_file="res://art/source/characters/base/straywild_base_character.blend"
dest_files=["res://.godot/imported/straywild_base_character.blend-02abbfdb9b1d393f1bd3cfface615e27.scn"]
source_file="res://art/source/characters/base/netfishing_base_character.blend"
dest_files=["res://.godot/imported/netfishing_base_character.blend-65bf3bc5b77cc1a37fa3f81ebd808d37.scn"]
[params]

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bfhnup14638r7"
path="res://.godot/imported/straywild_base_character.glb-c9650c715a1b5b9ae0d8541191f7d7a9.scn"
path="res://.godot/imported/netfishing_base_character.glb-cbdc33eaa4fcd1d2d2a8f4a463b228d6.scn"
[deps]
source_file="res://art/source/characters/base/straywild_base_character.glb"
dest_files=["res://.godot/imported/straywild_base_character.glb-c9650c715a1b5b9ae0d8541191f7d7a9.scn"]
source_file="res://art/source/characters/base/netfishing_base_character.glb"
dest_files=["res://.godot/imported/netfishing_base_character.glb-cbdc33eaa4fcd1d2d2a8f4a463b228d6.scn"]
[params]

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://d38y8blk2w5c5"
path="res://.godot/imported/straywild_character_source.blend-0e7b8a87008f88e309ad73a63561ef5b.scn"
path="res://.godot/imported/netfishing_character_source.blend-1d18c95606937d4c8bcb87e334e02ee5.scn"
[deps]
source_file="res://art/source/characters/base/straywild_character_source.blend"
dest_files=["res://.godot/imported/straywild_character_source.blend-0e7b8a87008f88e309ad73a63561ef5b.scn"]
source_file="res://art/source/characters/base/netfishing_character_source.blend"
dest_files=["res://.godot/imported/netfishing_character_source.blend-1d18c95606937d4c8bcb87e334e02ee5.scn"]
[params]

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://3uq4cxiomttt"
path="res://.godot/imported/straywild_character_source.glb-3a8ccc55dbe60da1b70b62110b206353.scn"
path="res://.godot/imported/netfishing_character_source.glb-9c98ee44b142c5b3d06f0838b7d2c9c4.scn"
[deps]
source_file="res://art/source/characters/base/straywild_character_source.glb"
dest_files=["res://.godot/imported/straywild_character_source.glb-3a8ccc55dbe60da1b70b62110b206353.scn"]
source_file="res://art/source/characters/base/netfishing_character_source.glb"
dest_files=["res://.godot/imported/netfishing_character_source.glb-9c98ee44b142c5b3d06f0838b7d2c9c4.scn"]
[params]

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bdomsntfeovnc"
path.s3tc="res://.godot/imported/straywild_character_source_eyes1_eyebrows1.png-3c638377e631a94b998336d0ca1d8b8e.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_eyes1_eyebrows1.png-3c638377e631a94b998336d0ca1d8b8e.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_eyes1_eyebrows1.png-a0b9f287e407afd9688e141dc5f2b801.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_eyes1_eyebrows1.png-a0b9f287e407afd9688e141dc5f2b801.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_eyes1_eyebrows1.png"
dest_files=["res://.godot/imported/straywild_character_source_eyes1_eyebrows1.png-3c638377e631a94b998336d0ca1d8b8e.s3tc.ctex", "res://.godot/imported/straywild_character_source_eyes1_eyebrows1.png-3c638377e631a94b998336d0ca1d8b8e.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_eyes1_eyebrows1.png"
dest_files=["res://.godot/imported/netfishing_character_source_eyes1_eyebrows1.png-a0b9f287e407afd9688e141dc5f2b801.s3tc.ctex", "res://.godot/imported/netfishing_character_source_eyes1_eyebrows1.png-a0b9f287e407afd9688e141dc5f2b801.etc2.ctex"]
[params]

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://du4u6meapay05"
path.s3tc="res://.godot/imported/straywild_character_source_eyes_simple_shine.png-97500ad873e0da3aaf0e9e3c3198e38a.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_eyes_simple_shine.png-97500ad873e0da3aaf0e9e3c3198e38a.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_eyes_simple_shine.png"
dest_files=["res://.godot/imported/straywild_character_source_eyes_simple_shine.png-97500ad873e0da3aaf0e9e3c3198e38a.s3tc.ctex", "res://.godot/imported/straywild_character_source_eyes_simple_shine.png-97500ad873e0da3aaf0e9e3c3198e38a.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_eyes_simple_shine.png"
dest_files=["res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.s3tc.ctex", "res://.godot/imported/netfishing_character_source_eyes_simple_shine.png-965743f3716320bbc385096956ffef2d.etc2.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://css0k0virgoph"
path.s3tc="res://.godot/imported/straywild_character_source_mouth1.png-ff2ed280ca7e84bdd0749ed5b5b16f54.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_mouth1.png-ff2ed280ca7e84bdd0749ed5b5b16f54.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_mouth1.png-b323b9153acd3f552f35c1d1108567c8.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_mouth1.png-b323b9153acd3f552f35c1d1108567c8.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_mouth1.png"
dest_files=["res://.godot/imported/straywild_character_source_mouth1.png-ff2ed280ca7e84bdd0749ed5b5b16f54.s3tc.ctex", "res://.godot/imported/straywild_character_source_mouth1.png-ff2ed280ca7e84bdd0749ed5b5b16f54.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_mouth1.png"
dest_files=["res://.godot/imported/netfishing_character_source_mouth1.png-b323b9153acd3f552f35c1d1108567c8.s3tc.ctex", "res://.godot/imported/netfishing_character_source_mouth1.png-b323b9153acd3f552f35c1d1108567c8.etc2.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://di20c1x8vksi1"
path.s3tc="res://.godot/imported/straywild_character_source_mouth_three.png-adf40ee30e725bafadf6a8fa4dbd8abf.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_mouth_three.png-adf40ee30e725bafadf6a8fa4dbd8abf.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_mouth_three.png"
dest_files=["res://.godot/imported/straywild_character_source_mouth_three.png-adf40ee30e725bafadf6a8fa4dbd8abf.s3tc.ctex", "res://.godot/imported/straywild_character_source_mouth_three.png-adf40ee30e725bafadf6a8fa4dbd8abf.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_mouth_three.png"
dest_files=["res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.s3tc.ctex", "res://.godot/imported/netfishing_character_source_mouth_three.png-6bf79d4c9c660d30fb7fc365f0039313.etc2.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://7dwa0bfev1rk"
path.s3tc="res://.godot/imported/straywild_character_source_nose1.2.png-0a8355472731651768eaa5fc2ee168d4.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_nose1.2.png-0a8355472731651768eaa5fc2ee168d4.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_nose1.2.png-ef4dd456c5b0f0db73b3dc063bfba941.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_nose1.2.png-ef4dd456c5b0f0db73b3dc063bfba941.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_nose1.2.png"
dest_files=["res://.godot/imported/straywild_character_source_nose1.2.png-0a8355472731651768eaa5fc2ee168d4.s3tc.ctex", "res://.godot/imported/straywild_character_source_nose1.2.png-0a8355472731651768eaa5fc2ee168d4.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_nose1.2.png"
dest_files=["res://.godot/imported/netfishing_character_source_nose1.2.png-ef4dd456c5b0f0db73b3dc063bfba941.s3tc.ctex", "res://.godot/imported/netfishing_character_source_nose1.2.png-ef4dd456c5b0f0db73b3dc063bfba941.etc2.ctex"]
[params]

View file

@ -3,8 +3,8 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://b0p55hwdry2cr"
path.s3tc="res://.godot/imported/straywild_character_source_nose_dog_round.png-d1ea0db61e41dfeeed3b599286ffb82c.s3tc.ctex"
path.etc2="res://.godot/imported/straywild_character_source_nose_dog_round.png-d1ea0db61e41dfeeed3b599286ffb82c.etc2.ctex"
path.s3tc="res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.s3tc.ctex"
path.etc2="res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
@ -15,8 +15,8 @@ generator_parameters={
[deps]
source_file="res://art/source/characters/base/straywild_character_source_nose_dog_round.png"
dest_files=["res://.godot/imported/straywild_character_source_nose_dog_round.png-d1ea0db61e41dfeeed3b599286ffb82c.s3tc.ctex", "res://.godot/imported/straywild_character_source_nose_dog_round.png-d1ea0db61e41dfeeed3b599286ffb82c.etc2.ctex"]
source_file="res://art/source/characters/base/netfishing_character_source_nose_dog_round.png"
dest_files=["res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.s3tc.ctex", "res://.godot/imported/netfishing_character_source_nose_dog_round.png-1c89150861ebff3f930698c1747a0369.etc2.ctex"]
[params]

Binary file not shown.

View file

@ -7,7 +7,7 @@ prove authorship or licensing.
## Ownership and credits
straywild is jointly owned, developed, and published by its creators,
NETfishing is jointly owned, developed, and published by its creators,
publicly credited as Voyager and Endeavour and operating collectively as the
independent team Woofmeow.
@ -31,7 +31,7 @@ independent team Woofmeow.
Voyager is also the original catalog porter credit in PortMaster metadata.
Third-party creators are credited with their individual records below. Those
credits do not imply endorsement of straywild, Woofmeow, or its owners.
credits do not imply endorsement of NETfishing, Woofmeow, or its owners.
## License map
@ -41,7 +41,7 @@ Do not describe the complete repository as covered only by the GPL.
| --- | --- |
| Project-owned software code, shaders, code-oriented scene/resource configuration, tests, build tooling, and server software | GPL-3.0-or-later; source-root `LICENSE` and packaged `GPL-3.0-or-later.txt` |
| Project-owned artwork, textures, models, animation, music, audio, narrative content, characters, and other creative assets | Source-root or packaged `ASSET-LICENSE.md` |
| straywild and Woofmeow names, logos, icons, and official identity | Source-root or packaged `TRADEMARKS.md` |
| NETfishing and Woofmeow names, logos, icons, and official identity | Source-root or packaged `TRADEMARKS.md` |
| Third-party engines, fonts, sounds, and other external material | Their original terms, recorded below and in adjacent license texts where applicable |
| Previously accepted or expressly invited outside contributions | Source-root `CONTRIBUTOR-TERMS.md` plus any separately signed agreement |
@ -50,22 +50,22 @@ the terms of their source material or generating code. Repository location
alone does not relicense third-party material.
The GPL permits study, modification, redistribution, and forks of covered
code. It does not grant rights to straywild creative assets or branding. The
straywild Asset License separately permits qualifying noncommercial add-on
Mods for official straywild software and narrowly scoped Contribution Forks
code. It does not grant rights to NETfishing creative assets or branding. The
NETfishing Asset License separately permits qualifying noncommercial add-on
Mods for official NETfishing software and narrowly scoped Contribution Forks
used to prepare changes for possible upstream inclusion. It does not permit
those assets to accompany independent code forks, clones, standalone games,
unrelated products, or general-purpose asset packs. A GPL fork that is not a
qualifying Contribution Fork must replace straywild assets and reserved
qualifying Contribution Fork must replace NETfishing assets and reserved
branding with independently licensed material and a distinct identity.
Project-wide code, asset, branding, or contributor-license changes require
written approval from both straywild owners under their private joint
written approval from both NETfishing owners under their private joint
ownership agreement.
## Godot Engine notice
straywild uses Godot Engine under the MIT License:
NETfishing uses Godot Engine under the MIT License:
> Copyright (c) 2014-present Godot Engine contributors.
> Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.
@ -103,7 +103,7 @@ FreeType for font rendering; portions are copyright The FreeType Project
Runtime file: `ui/fonts/seattle_avenue.otf`; source, hash, and original notice:
`ui/fonts/Seattle-Avenue-LICENSE.txt`.
Public-domain fonts are not governed by the straywild Asset License.
Public-domain fonts are not governed by the NETfishing Asset License.
## Intake policy
@ -122,7 +122,7 @@ owners' private project records. This public document should contain the
credits and license notices needed by recipients; it should not duplicate a
changing file inventory that can be derived from the repository itself.
straywild does not accept unsolicited contributions. For work expressly
NETfishing does not accept unsolicited contributions. For work expressly
invited by both Owners, maintainers must obtain affirmative agreement to the
source-root `CONTRIBUTOR-TERMS.md` and retain the written invitation and
agreement in a durable Project record.
@ -159,8 +159,8 @@ against the repository when this record was revised.
| Material | Runtime location | Credit or terms |
| --- | --- | --- |
| Kat animalese alphabet and number sounds | `sound/dialogue/animalese/alphanumeric/` | Project-processed derivatives of the original source voice recording supplied by straywild community member kat. |
| Kim animalese alphabet and number sounds | `sound/dialogue/animalese/kim/` | Project-processed derivatives of the original source voice recording supplied by straywild community member kim. |
| Kat animalese alphabet and number sounds | `sound/dialogue/animalese/alphanumeric/` | Project-processed derivatives of the original source voice recording supplied by NETfishing community member kat. |
| Kim animalese alphabet and number sounds | `sound/dialogue/animalese/kim/` | Project-processed derivatives of the original source voice recording supplied by NETfishing community member kim. |
| Tuffy font | `ui/fonts/Tuffy_Bold.otf` | Public-domain dedication in `ui/fonts/Tuffy-LICENSE.txt`. |
| Seattle Avenue font | `ui/fonts/seattle_avenue.otf` | Public-domain font by JLH Fonts; notice in `ui/fonts/Seattle-Avenue-LICENSE.txt`. |
| Fishing fight loop | `audio/sfx/fishing/fighting.wav` | Edited from “Spinning reel.wav” by Freesound user tosha73, sound 509902, CC0. |

View file

@ -1,6 +1,6 @@
# Development reference
This is the authoritative reference for straywild architecture, engineering
This is the authoritative reference for NETfishing architecture, engineering
decisions, content policy, authoring, and validation.
## Architecture
@ -43,7 +43,7 @@ open host may publish a short-lived room lease, and the shared Join Game page
may browse compatible leases before handing the selected address back to the
existing direct ENet connection flow. The directory does not carry gameplay
traffic or become a gameplay authority. Its base URL comes from
`network/discovery/base_url`, with `straywild_DISCOVERY_URL` available as a
`network/discovery/base_url`, with `NETFISHING_DISCOVERY_URL` available as a
development/deployment override.
Friendships are local identity relationships shared across save slots. A live,
@ -261,7 +261,7 @@ copies of the entire customization catalog.
### Texture sampling
straywild artwork uses nearest-neighbor sampling. Do not enable linear,
NETfishing artwork uses nearest-neighbor sampling. Do not enable linear,
bilinear, trilinear, or anisotropic texture filtering. Shader samplers must
declare `filter_nearest`. The three canonical repeating terrain textures are
the sole mipmap exception: their projected shader uses nearest-filtered
@ -351,10 +351,10 @@ godot --headless --path . --script tests/fish_catalog_content_validation.gd
rm -rf -- "$test_root"
```
Do not point `straywild_DATA_DIR` at an arbitrary empty directory; it is an
Do not point `NETFISHING_DATA_DIR` at an arbitrary empty directory; it is an
explicit portable-data override and must identify a valid data root. The
PortMaster launcher is the narrow exception: it also sets
`straywild_CREATE_DATA_DIR=1`, allowing the game to initialize its known empty
`NETFISHING_CREATE_DATA_DIR=1`, allowing the game to initialize its known empty
external save directory on first launch.
Headless tests cannot prove visual alignment, mouse routing, shader appearance,

View file

@ -1,15 +1,15 @@
# PortMaster reference
straywild's PortMaster release is a canonical PortMaster package, not a
NETfishing's PortMaster release is a canonical PortMaster package, not a
version-named generic ZIP. The installer-facing archive must be named
`straywild.zip`, and its root must contain exactly:
`netfishing.zip`, and its root must contain exactly:
```text
straywild.sh
straywild/
NETfishing.sh
netfishing/
```
`port.json` belongs at `straywild/port.json` in the distributable archive.
`port.json` belongs at `netfishing/port.json` in the distributable archive.
The upstream source-submission layout keeps it beside the launcher and port
directory, but PortMaster's release builder relocates it into the declared
port directory. Do not copy the source-submission layout directly into a
@ -17,7 +17,7 @@ release ZIP.
HarbourMaster's installer also relocates recognized non-script files found at
an archive root into the detected port directory. That compatibility behavior
masked straywild's former root-level `port.json` during auto-install tests.
masked NETfishing's former root-level `port.json` during auto-install tests.
Directly extracting the same archive into `/ports` did not perform the repair.
Do not rely on installer relocation; build the distributable layout correctly.
@ -26,34 +26,30 @@ directory. The templates in `scripts/portmaster/` are authoritative.
## Release contract
- `port.json` uses schema version 4, names `straywild.zip`, and marks the
- `port.json` uses schema version 4, names `netfishing.zip`, and marks the
self-contained package ready to run.
- `straywild.sh` does not contain a `# PORTMASTER:` signature in the source or
- `NETfishing.sh` does not contain a `# PORTMASTER:` signature in the source or
distributable archive. HarbourMaster adds that installation marker when it
installs the port.
- The executable is `straywild/straywild.aarch64`.
- The executable is `netfishing/NETfishing.aarch64`.
- The package declares AArch64, two analog sticks, GLIBC 2.28, and
`weston_pkg_0.2.squashfs`.
- The launcher starts GPTOKEYB with the explicit `straywild.gptk` no-op map.
- The launcher starts GPTOKEYB with the explicit `netfishing.gptk` no-op map.
Every keyboard and mouse binding is disabled, leaving only GPTOKEYB's
device-specific force-quit chord while Godot and straywild's controller
device-specific force-quit chord while Godot and NETfishing's controller
mapping manager handle gameplay input. The explicit map also avoids the
anomalous controller behavior observed on ROCKNIX without a passthrough map.
- The launcher calls `pm_platform_helper` for the game executable after
starting GPTOKEYB and calls `pm_finish` after the game exits.
- straywild automatically creates player data for new installations under
`ports/saves/straywild/` and does not present the in-game folder picker.
- NETfishing automatically creates player data for new installations under
`ports/saves/netfishing/` and does not present the in-game folder picker.
- Existing installations with a selected data root keep that location when
upgraded. Device-local data, configuration, and cache remain under
`straywild/conf/data`, `straywild/conf/config`, and
`straywild/conf/cache`.
- A rebrand upgrade copies an existing `netfishing/conf/` tree into the new
`straywild/conf/` tree when the latter does not exist. It also reuses an
existing `ports/saves/netfishing/` data root rather than creating an empty
replacement. New installations use straywild paths exclusively.
`netfishing/conf/data`, `netfishing/conf/config`, and
`netfishing/conf/cache`.
- The archive must not contain `conf/`, saves, identities, logs, source files,
`.git`, or `.godot` content.
- Release downloads must publish only the canonical `straywild.zip` for this
- Release downloads must publish only the canonical `netfishing.zip` for this
platform. Do not also publish a byte-identical versioned PortMaster ZIP;
HarbourMaster identifies the port by its canonical archive name and the
Forgejo release tag already supplies the version.
@ -71,7 +67,7 @@ The script deletes and regenerates the Linux ARM64 export, stages the package,
validates its structure, and writes:
```text
builds/v<project-version>/straywild.zip
builds/v<project-version>/netfishing.zip
```
`--package-only` is reserved for repackaging an already validated ARM64 export.
@ -87,7 +83,7 @@ bash scripts/build_portmaster.sh --package-only --hotfix
The hotfix keeps the game executable and PCK tied to the release tag while
recording the newer packaging commit separately in `BUILD-INFO.txt`. Replace
the release's existing `straywild.zip`; never move the game release tag.
the release's existing `netfishing.zip`; never move the game release tag.
## Local muOS installation
@ -97,22 +93,22 @@ The muOS auto-install directory is:
/mnt/mmc/MUOS/PortMaster/autoinstall/
```
For an explicit offline installation test, copy `straywild.zip` to a temporary
For an explicit offline installation test, copy `netfishing.zip` to a temporary
device directory and run:
```bash
/mnt/mmc/MUOS/PortMaster/harbourmaster \
--offline --no-check install ./straywild.zip
--offline --no-check install ./netfishing.zip
```
Before upgrading an existing installation, preserve either the current
`/mnt/mmc/ports/straywild/` paths or the former `/mnt/mmc/ports/netfishing/`
paths on the device. After installation:
Before upgrading an existing installation, preserve
`/mnt/mmc/ports/netfishing/conf/` and `/mnt/mmc/ports/saves/netfishing/` on the
device. After installation:
1. Confirm the installed executable and PCK hashes match the staged release.
2. Confirm HarbourMaster added its `# PORTMASTER:` installation signature to
the installed launcher, then confirm the launcher starts GPTOKEYB with
`straywild.gptk` and calls `pm_platform_helper` for the game executable.
`netfishing.gptk` and calls `pm_platform_helper` for the game executable.
3. Confirm `conf/` and the external save directory were not replaced or
removed.
4. Launch the installed port through the normal muOS menu.
@ -121,7 +117,7 @@ paths on the device. After installation:
Start+Select on most devices.
Installing the public PortMaster catalog entry can still install an older
catalog build until the upstream `straywild.zip` is updated. A local release
catalog build until the upstream `netfishing.zip` is updated. A local release
test must install the generated local archive explicitly.
## Template provenance
@ -134,7 +130,7 @@ f24daae48f543b3a270a5aa46b5e73a31904bf0c7216d4c8a9e15a8dc48a5eed screenshot.png
```
The remaining catalog metadata assets were copied from the installed official
`straywild.zip` package and are intentionally preserved byte-for-byte:
`netfishing.zip` package and are intentionally preserved byte-for-byte:
```text
e2a9d132744684c67865c01eca027a8c9946b4c5a19da57c82f1af0373dc83b7 gameinfo.xml
@ -164,7 +160,7 @@ The device-verified Godot mapping is:
- left-stick click `b9`, left trigger `b10`, right trigger `b11`, right-stick click `b12`
- D-pad `h0`; left and right sticks `a0..a3`
`scripts/portmaster/straywild.sh` must replace the incompatible SDL2 entry
`scripts/portmaster/NETfishing.sh` must replace the incompatible SDL2 entry
with the Godot entry when that SDL2 GUID is selected. Do not append the two
entries with a newline. WestonPack reconstructs the wrapped game command
through a shell, so raw mapping values passed in that command can be split into
@ -173,14 +169,14 @@ this failure with the `GO-Super Gamepad` mapping. The outer Weston environment
also does not reliably preserve the corrected muOS mapping for the game.
Write the exact selected mapping to `conf/cache/controller_mapping.txt` before
starting Weston. Weston must launch `launch-straywild.sh`, which reads that
starting Weston. Weston must launch `launch-netfishing.sh`, which reads that
file, exports `SDL_GAMECONTROLLERCONFIG`, and immediately replaces itself with
the game process. This applies the mapping at the same point as the working
0.10.1 launcher without passing its raw text through WestonPack's command
reconstruction. Do not move the mapping back to either side of
`westonwrap.sh`.
Always pass `straywild.gptk`, which explicitly unassigns every direct and
Always pass `netfishing.gptk`, which explicitly unassigns every direct and
hotkey binding with GPTOKEYB's `\"` value. This keeps GPTOKEYB from injecting
keyboard or mouse events on top of Godot's native controller input and retains
the device-specific kill chord. Supplying the explicit passthrough map also
@ -213,8 +209,8 @@ The light profile passes these Godot options:
- `--max-fps 30`
- `--audio-output-latency 40`
It also passes `straywild_PERFORMANCE_PROFILE=light` and
`straywild_LOW_END=1`. The game renders the 3D world at 37.5% linear
It also passes `NETFISHING_PERFORMANCE_PROFILE=light` and
`NETFISHING_LOW_END=1`. The game renders the 3D world at 37.5% linear
resolution with nearest-neighbor scaling, reducing 3D pixel work by about 86%
while the separately rendered UI retains its canonical resolution. The light
profile also:
@ -248,7 +244,7 @@ omitted ambience or replace the micro textures with desktop-resolution assets.
The normal profile otherwise retains the full visual presentation.
To opt a capable device into the normal profile, create the persistent file
`straywild/conf/performance_profile` containing exactly:
`netfishing/conf/performance_profile` containing exactly:
```text
normal
@ -257,13 +253,13 @@ normal
On a typical muOS installation, the full path is:
```text
/mnt/mmc/ports/straywild/conf/performance_profile
/mnt/mmc/ports/netfishing/conf/performance_profile
```
Set the file to `light`, or remove it, to restore the default. An externally
provided `straywild_PERFORMANCE_PROFILE=normal` or `light` environment value
provided `NETFISHING_PERFORMANCE_PROFILE=normal` or `light` environment value
takes precedence over the persistent file. Invalid values safely fall back to
the light profile and are reported in `straywild/log.txt`.
the light profile and are reported in `netfishing/log.txt`.
Do not use Godot's low processor mode for the light profile. It reduces idle
CPU usage by sleeping between updates and is not a game-performance

View file

@ -1,10 +1,10 @@
straywild
v0.19.0-alpha
Alpha 0.19.0
NETfishing
v0.18.1-alpha
Alpha 0.18.1
Thank you for trying this early private playtest.
straywild is an early multiplayer fishing game. This alpha includes local
NETfishing is an early multiplayer fishing game. This alpha includes local
progression, player-hosted and dedicated multiplayer sessions, public room
discovery, and direct UDP connections. Expect rough edges and please keep a
backup of any save or identity data you care about.
@ -12,15 +12,15 @@ backup of any save or identity data you care about.
INSTALLATION
1. Extract the entire ZIP into a new folder.
2. Keep the executable and straywild.pck together.
3. Launch straywild.exe on Windows or straywild on Linux.
2. Keep the executable and netfishing.pck together.
3. Launch netfishing.exe on Windows or netfishing on Linux.
Windows may show a warning for an unsigned application. This private build is
not code signed. Only run a copy received from the playtest organizer.
Linux users may need to allow execution:
chmod +x straywild
chmod +x netfishing
CONTROLS

View file

@ -1,4 +1,4 @@
# straywild documentation
# NETfishing documentation
This directory is the single home for maintained project documentation.
Start here instead of searching feature, asset, world, or script directories
@ -17,10 +17,10 @@ for local README files.
## Related repositories
- [Discovery service API](https://forge.makearmy.io/woofmeow/straywild-discovery-server/src/branch/main/docs/API.md)
- [Discovery service API](https://forge.makearmy.io/woofmeow/netfishing-discovery-server/src/branch/main/docs/API.md)
stays with the service implementation and defines its versioned HTTP
contract.
- [Dedicated-server packaging](https://forge.makearmy.io/woofmeow/straywild-dedicated-server/src/branch/main/README.md)
- [Dedicated-server packaging](https://forge.makearmy.io/woofmeow/netfishing-dedicated-server/src/branch/main/README.md)
stays with its installer and update scripts. It consumes this repository's
attribution and legal notices from the exact pinned game commit instead of
maintaining copies.

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.19.0-alpha/windows-x86_64/straywild.exe"
export_path="builds/v0.18.1-alpha/windows-x86_64/NETfishing.exe"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -32,16 +32,16 @@ codesign/digest_algorithm=1
codesign/description=""
codesign/custom_options=PackedStringArray()
application/modify_resources=true
application/icon="res://art/exported/system_icons/straywild.ico"
application/icon="res://art/exported/system_icons/netfishing.ico"
application/console_wrapper_icon=""
application/icon_interpolation=0
application/file_version="0.19.0.0"
application/product_version="0.19.0.0"
application/icon_interpolation=4
application/file_version="0.18.1.0"
application/product_version="0.18.1.0"
application/company_name="Woofmeow"
application/product_name="straywild"
application/file_description="straywild v0.19.0-alpha"
application/product_name="NETfishing"
application/file_description="NETfishing v0.18.1-alpha"
application/copyright="Copyright © 2026 Woofmeow"
application/trademarks="straywild and Woofmeow branding is reserved; see TRADEMARKS.md"
application/trademarks="NETfishing and Woofmeow branding is reserved; see TRADEMARKS.md"
application/export_angle=0
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
@ -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.19.0-alpha/linux-arm64/straywild.arm64"
export_path="builds/v0.18.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.19.0-alpha/macos/straywild.zip"
export_path="builds/v0.18.1-alpha/macos/NETfishing.zip"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -106,10 +106,10 @@ script_export_mode=2
custom_template/debug=""
custom_template/release=""
application/bundle_identifier="io.woofmeow.netfishing"
application/icon="res://art/exported/system_icons/straywild_1024.png"
application/icon="res://art/exported/system_icons/netfishing_1024.png"
application/icon_interpolation=0
application/short_version="0.19.0"
application/version="0.19.0"
application/short_version="0.18.1"
application/version="0.18.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.19.0-alpha/server-linux-x86_64/straywildServer.x86_64"
export_path="builds/v0.18.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.19.0-alpha/android/straywild.apk"
export_path="builds/v0.18.1-alpha/android/NETfishing.apk"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
@ -176,10 +176,10 @@ architectures/armeabi-v7a=false
architectures/arm64-v8a=true
architectures/x86=false
architectures/x86_64=false
version/code=190000
version/name="v0.19.0-alpha"
version/code=180100
version/name="v0.18.1-alpha"
package/unique_name="io.woofmeow.netfishing"
package/name="straywild"
package/name="NETfishing"
package/signed=true
package/app_category=0
package/retain_data_on_uninstall=false
@ -187,7 +187,7 @@ package/exclude_from_recents=false
package/show_in_android_tv=false
package/show_in_app_library=true
package/show_as_launcher_app=true
launcher_icons/main_192x192="res://art/exported/system_icons/straywild_256.png"
launcher_icons/main_192x192="res://art/exported/system_icons/netfishing_256.png"
graphics/opengl_debug=false
screen/immersive_mode=true
screen/edge_to_edge=false
@ -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.19.0-alpha/linux-x86_64/straywild.x86_64"
export_path="builds/v0.18.1-alpha/linux-x86_64/NETfishing.x86_64"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""

View file

@ -150,7 +150,6 @@ var _network_session: NetworkSessionType
var _network_fishing: NetworkFishingServiceType
var _world_time: WorldTimeServiceType
var _world_weather: WorldWeatherServiceType
var _fishable_water_regions_resolver := Callable()
var _active_player: PlayerType
var _state_time_remaining: float = 0.0
var _cast_charge: float = 0.0
@ -223,7 +222,6 @@ func setup(
network_fishing: NetworkFishingServiceType = null,
world_time: WorldTimeServiceType = null,
world_weather: WorldWeatherServiceType = null,
fishable_water_regions_resolver: Callable = Callable(),
) -> void:
_local_player = local_player
_local_inventory = local_inventory
@ -244,7 +242,6 @@ func setup(
_network_fishing = network_fishing
_world_time = world_time
_world_weather = world_weather
_fishable_water_regions_resolver = fishable_water_regions_resolver
if (
_network_session != null
and not _network_session.state_changed.is_connected(
@ -1667,47 +1664,6 @@ func build_network_context(
return _build_fishing_context(region)
func is_species_available_now(fish: FishDataType) -> bool:
if fish == null or not fish.is_selectable():
return false
var season := (
_world_time.get_season()
if _world_time != null
else CalendarSeason.UNKNOWN
)
if not fish.is_available_in_season(season):
return false
if fish.collection_method != FishDataType.CollectionMethod.FISHING:
return true
for region: FishableWaterRegionType in _get_logbook_water_regions():
if (
region == null
or region.fish_pool == null
or region.fish_pool.get_fish_by_id(fish.id) == null
):
continue
var context := _build_fishing_context(region)
if not fish.is_allowed_in_water(context.water_type):
continue
if fish.availability == null or fish.availability.is_available(context):
return true
return false
func _get_logbook_water_regions() -> Array[FishableWaterRegionType]:
var regions: Array[FishableWaterRegionType] = []
if not _fishable_water_regions_resolver.is_valid():
return regions
var resolved: Variant = _fishable_water_regions_resolver.call()
if resolved is not Array:
return regions
for value: Variant in resolved:
var region := value as FishableWaterRegionType
if region != null and is_instance_valid(region):
regions.append(region)
return regions
func _get_active_bait_tags() -> Array[StringName]:
if _local_player == null or _item_catalog == null:
return []

View file

@ -29,16 +29,12 @@ func configure(
entity_id = configured_entity_id
data = configured_data
type_id = data.type_id if data != null else StringName()
# Establish the authoritative transform before constructing transient visuals.
# Effects emitted before this point would begin at the default world origin.
apply_network_state(position, yaw, true)
if data != null and data.is_stationary_hotspot():
_ensure_water_spurt_visual()
_water_spurt_elapsed = (
float(abs(hash(entity_id)) % 1000) / 1000.0
* WATER_SPURT_INTERVAL_SECONDS
)
_emit_water_spurt()
else:
_ensure_visual()
if data != null and data.catch_data != null and _sprite != null:
@ -54,6 +50,7 @@ func configure(
)
)
_sprite.rotation_degrees.x = data.sprite_tilt_degrees
apply_network_state(position, yaw, true)
func apply_network_state(
@ -150,6 +147,7 @@ func _ensure_water_spurt_visual() -> void:
hole.mesh = hole_mesh
hole.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
_water_spurt_root.add_child(hole)
_emit_water_spurt()
func _emit_water_spurt() -> void:
@ -161,7 +159,6 @@ func _emit_water_spurt() -> void:
particles.amount = 6
particles.lifetime = 0.42
particles.one_shot = true
particles.local_coords = true
particles.explosiveness = 1.0
particles.direction = Vector3.UP
particles.spread = 32.0

View file

@ -277,7 +277,6 @@ var _rain_ambience: RainAmbienceType
func _ready() -> void:
_data_root.prepare_legacy_user_data()
_performance_profile = RuntimePerformanceProfileType.from_environment()
_dedicated_runtime = _is_dedicated_server_runtime()
if _dedicated_runtime:
@ -295,7 +294,7 @@ func _ready() -> void:
_configure_presentation_performance_profile(
_performance_profile.is_light()
)
DisplayServer.window_set_title("straywild")
DisplayServer.window_set_title("NETfishing")
_rain_ambience = RainAmbienceType.new()
_rain_ambience.name = "RainAmbience"
add_child(_rain_ambience)
@ -325,12 +324,11 @@ func _ready() -> void:
func _configure_presentation_performance_profile(light_profile: bool) -> void:
_game_ui.get_title_screen().set_minimal_presentation(light_profile)
_game_ui.set_light_performance_profile(light_profile)
var title_background_material := (
_title_background.material as ShaderMaterial
)
if title_background_material != null:
title_background_material.set_shader_parameter(
var title_water_material := _title_background.material as ShaderMaterial
if title_water_material != null:
title_water_material.set_shader_parameter(
"animation_enabled",
not light_profile,
)
@ -463,7 +461,7 @@ func _print_dedicated_metrics() -> void:
metrics["gatherables"] = _network_world_spawns.call(
"get_network_metrics"
)
print("straywild server metrics: %s" % JSON.stringify(metrics))
print("NETfishing server metrics: %s" % JSON.stringify(metrics))
func _start_dedicated_server() -> void:
@ -472,7 +470,10 @@ func _start_dedicated_server() -> void:
_fail_dedicated_server(config.error_message)
return
var data_path: String = config.data_directory
if not _data_root.has_data_manifest(data_path):
var manifest_path: String = data_path.path_join(
PlayerDataRoot.MANIFEST_FILENAME
)
if not FileAccess.file_exists(manifest_path):
var created: Dictionary = _data_root.create_unbound_root(data_path)
if not bool(created.get("ok", false)):
_fail_dedicated_server(str(created.get(
@ -555,7 +556,7 @@ func _start_dedicated_server() -> void:
_fail_dedicated_server(_discovery.get_host_status_message())
return
print(
"straywild dedicated server ready: %s on %s:%d (%d players, %s, timezone %s)"
"NETfishing dedicated server ready: %s on %s:%d (%d players, %s, timezone %s)"
% [
config.server_name,
config.bind_address,
@ -920,7 +921,6 @@ func _initialize_application(dedicated: bool) -> void:
_network_fishing,
_world_time,
_world_weather,
Callable(_test_world, "get_fishable_water_regions"),
)
if dedicated:
return
@ -972,7 +972,6 @@ func _initialize_application(dedicated: bool) -> void:
_network_session,
_interface_fonts,
)
_game_ui.data_root_changed.connect(_on_data_root_changed)
_game_ui.setup_controller_mapping(_controller_mapping_manager)
_ui_pixelation.setup_controller_mapping(_controller_mapping_manager)
_game_ui.setup_keyboard_mouse_mapping(_keyboard_mouse_mapping_manager)
@ -1007,8 +1006,7 @@ func _initialize_application(dedicated: bool) -> void:
_game_ui,
_game_ui.get_screen_fade(),
_test_world.get_player_water_triggers(),
_test_world.get_safe_respawn_points(),
Callable(_test_world, "get_water_recovery_position"),
_test_world.get_safe_respawn_points()
)
_ui_pixelation.effective_pixel_size_changed.connect(
_on_effective_ui_pixel_size_changed
@ -1098,7 +1096,7 @@ func _initialize_application(dedicated: bool) -> void:
func _show_data_root_setup() -> void:
if _data_setup_dialog == null:
_data_setup_dialog = ConfirmationDialog.new()
_data_setup_dialog.title = "straywild player data"
_data_setup_dialog.title = "NETfishing player data"
_data_setup_dialog.ok_button_text = "Use This Folder"
_data_setup_dialog.cancel_button_text = "Quit"
_data_setup_dialog.confirmed.connect(_use_default_data_root)
@ -1115,14 +1113,14 @@ func _show_data_root_setup() -> void:
var default_path: String = _data_root.default_visible_path()
var legacy: bool = PortableDataMigration.legacy_files_present()
_data_setup_dialog.dialog_text = (
("Move your existing straywild data to an easy-to-find folder."
if legacy else "Choose where straywild stores your player data.")
("Move your existing NETfishing data to an easy-to-find folder."
if legacy else "Choose where NETfishing stores your player data.")
+ "\n\n%s\n\nYou can choose a Syncthing folder."
% (default_path if not default_path.is_empty() else "Choose a folder")
)
_data_setup_dialog.ok_button_text = (
(
"Move to Documents/straywild"
"Move to Documents/NETFISHING"
if legacy else "Use This Folder"
)
if not default_path.is_empty()
@ -1131,7 +1129,7 @@ func _show_data_root_setup() -> void:
_data_setup_current_button.visible = not default_path.is_empty()
if not _data_root.error_message.is_empty():
_data_setup_dialog.dialog_text = (
"Your straywild data folder is unavailable.\n\n%s"
"Your NETfishing data folder is unavailable.\n\n%s"
% _data_root.error_message
)
_data_setup_dialog.popup_centered(Vector2i(640, 360))
@ -1267,11 +1265,11 @@ func _activate_selected_data_path(path: String, app_data: bool = false) -> void:
func _show_existing_root_choice(path: String) -> void:
_pending_existing_root_path = path
var dialog: ConfirmationDialog = ConfirmationDialog.new()
dialog.title = "Existing straywild data"
dialog.title = "Existing NETfishing data"
dialog.ok_button_text = "Use Data Already in Selected Folder"
dialog.cancel_button_text = "Cancel"
dialog.dialog_text = (
"This folder already contains straywild player data.\n\n"
"This folder already contains NETfishing player data.\n\n"
+ "Choose which complete data set to use. Data is never merged automatically."
)
dialog.add_button(
@ -1345,18 +1343,6 @@ func _on_data_root_status(message: String) -> void:
_configure_popup_dialog.call_deferred(dialog, dialog.get_ok_button())
func _on_data_root_changed() -> void:
_save_manager.set_autosave_enabled(false)
_save_manager.cancel_pending_autosave()
_configure_portable_stores()
if not _network_profile_service.reload_persisted_profile():
push_warning("The selected data folder's player profile could not be loaded.")
_network_session.set_local_appearance_snapshot(
_appearance_store.get_snapshot()
)
_game_ui.get_title_screen().refresh_after_data_root_change()
func _on_server_trust_required(
endpoint: String,
expected_fingerprint: String,
@ -2346,9 +2332,17 @@ func _on_remote_recovery_requested(
peer_id,
"Fishing attempt ended."
)
var target_position := _test_world.get_water_recovery_position(
entry_position
)
var target_position: Vector3 = _test_world.get_player_spawn_transform().origin
var nearest_distance: float = INF
for point: SafeRespawnPoint in _test_world.get_safe_respawn_points():
if point == null or not point.enabled:
continue
var distance: float = point.get_horizontal_distance_squared(
entry_position
)
if distance < nearest_distance:
nearest_distance = distance
target_position = point.global_position
target_position.y += _water_recovery.respawn_height_offset
avatar.global_position = target_position
avatar.velocity = Vector3.ZERO
@ -2426,7 +2420,6 @@ func _apply_world(
spawn_transform,
_test_world.get_player_water_triggers(),
_test_world.get_safe_respawn_points(),
Callable(_test_world, "get_water_recovery_position"),
)
_shoreline_ambience.configure(
_player,

View file

@ -38,7 +38,7 @@
[ext_resource type="Script" uid="uid://dpiv6wttry0j4" path="res://network/player_data_root.gd" id="37_data_root"]
[ext_resource type="Script" uid="uid://bu5q4a8jfvxkf" path="res://network/identity_backup_service.gd" id="38_identity_backup"]
[ext_resource type="Script" uid="uid://djmxy6jibi5y3" path="res://ui/interface_font_controller.gd" id="39_fonts"]
[ext_resource type="Texture2D" uid="uid://doju2lbj2ghwa" path="res://world/generation/chunks/assets/chunk_0000_grass_lite.png" id="40_title_grass"]
[ext_resource type="Shader" uid="uid://c8s1g7tn771du" path="res://ui/title_water_background.gdshader" id="40_title_water"]
[ext_resource type="Texture2D" uid="uid://f8a0cs0s7ler" path="res://art/patterns/pattern_tealdot.png" id="41_menu_pattern"]
[ext_resource type="Shader" uid="uid://byw3iub66qvog" path="res://ui/player_menu_pattern.gdshader" id="42_menu_pattern"]
[ext_resource type="Texture2D" uid="uid://b6xws1d2dnbnn" path="res://art/patterns/pattern_moneyfish.png" id="43_shop_pattern"]
@ -59,12 +59,18 @@
[ext_resource type="Script" path="res://network/network_world_spawn_service.gd" id="59_world_spawns"]
[ext_resource type="Script" path="res://gathering/gathering_controller.gd" id="60_gathering_controller"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_grass_native"]
shader = ExtResource("42_menu_pattern")
shader_parameter/pattern_texture = ExtResource("40_title_grass")
shader_parameter/source_tile_size = Vector2(128, 128)
shader_parameter/display_scale = 1.0
shader_parameter/scroll_velocity_pixels = Vector2(-7.5, -7.5)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_water_native"]
shader = ExtResource("40_title_water")
shader_parameter/surface_color = Color(0.1, 0.45, 0.62, 1)
shader_parameter/middle_color = Color(0.055, 0.285, 0.4, 1)
shader_parameter/depth_color = Color(0.02, 0.16, 0.27, 1)
shader_parameter/virtual_pixel_density = Vector2(320, 180)
shader_parameter/color_step_count = 14.0
shader_parameter/continuous_depth_blend = 0.12
shader_parameter/wave_speed = 0.1
shader_parameter/wave_scale = 2.4
shader_parameter/wave_strength = 0.012
shader_parameter/caustic_strength = 0.018
[sub_resource type="ShaderMaterial" id="ShaderMaterial_player_menu_pattern"]
shader = ExtResource("42_menu_pattern")
@ -133,7 +139,7 @@ layer = -1
[node name="TitleBackground" type="ColorRect" parent="TitleBackgroundLayer" unique_id=1768697365]
unique_name_in_owner = true
material = SubResource("ShaderMaterial_title_grass_native")
material = SubResource("ShaderMaterial_title_water_native")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0

View file

@ -2,13 +2,9 @@ class_name RuntimePerformanceProfile
extends RefCounted
const PROFILE_ENVIRONMENT_VARIABLE: String = (
"straywild_PERFORMANCE_PROFILE"
)
const LEGACY_LIGHT_ENVIRONMENT_VARIABLE: String = "straywild_LOW_END"
const NETFISHING_PROFILE_ENVIRONMENT_VARIABLE := (
"NETFISHING_PERFORMANCE_PROFILE"
)
const NETFISHING_LIGHT_ENVIRONMENT_VARIABLE := "NETFISHING_LOW_END"
const LEGACY_LIGHT_ENVIRONMENT_VARIABLE: String = "NETFISHING_LOW_END"
const NORMAL_PROFILE: StringName = &"normal"
const LIGHT_PROFILE: StringName = &"light"
const NORMAL_WORLD_RENDER_SCALE: float = 1.0
@ -18,19 +14,9 @@ var _profile_name: StringName = NORMAL_PROFILE
static func from_environment() -> RuntimePerformanceProfile:
var profile_name: String = OS.get_environment(
PROFILE_ENVIRONMENT_VARIABLE
)
if profile_name.is_empty():
profile_name = OS.get_environment(
NETFISHING_PROFILE_ENVIRONMENT_VARIABLE
)
return from_name(
StringName(profile_name),
(
OS.get_environment(LEGACY_LIGHT_ENVIRONMENT_VARIABLE) == "1"
or OS.get_environment(NETFISHING_LIGHT_ENVIRONMENT_VARIABLE) == "1"
),
StringName(OS.get_environment(PROFILE_ENVIRONMENT_VARIABLE)),
OS.get_environment(LEGACY_LIGHT_ENVIRONMENT_VARIABLE) == "1",
)

View file

@ -1,6 +1,6 @@
extends Node
## Enforces straywild's nearest-neighbor-only artwork policy at runtime.
## Enforces NETfishing's nearest-neighbor-only artwork policy at runtime.
##
## Godot uses separate texture-filter enums for CanvasItem and 3D materials.
## Applying both here prevents imported models, dynamically created controls,

View file

@ -20,13 +20,12 @@ signal friend_invite_received(
signal friend_invite_finished(success: bool, message: String)
const BASE_URL_SETTING: String = "network/discovery/base_url"
const BASE_URL_ENVIRONMENT: String = "straywild_DISCOVERY_URL"
const LEGACY_BASE_URL_ENVIRONMENT: String = "NETFISHING_DISCOVERY_URL"
const BASE_URL_ENVIRONMENT: String = "NETFISHING_DISCOVERY_URL"
const SETTINGS_PATH: String = "user://network_discovery.cfg"
const DEFAULT_ROOM_NAME: String = "Player's Server"
const LEGACY_DEFAULT_ROOM_NAME: String = "straywild Room"
const LEGACY_DEFAULT_ROOM_NAME: String = "NETfishing Room"
const LEGACY_DEDICATED_DEFAULT_ROOM_NAME: String = (
"straywild Dedicated Server"
"NETfishing Dedicated Server"
)
const ROOM_NAME_SUFFIX: String = "'s Server"
const MAX_ROOM_NAME_LENGTH: int = 48
@ -34,7 +33,7 @@ const HEARTBEAT_INTERVAL_SECONDS: float = 15.0
const REQUEST_TIMEOUT_SECONDS: float = 8.0
const TRAVERSAL_POLL_INTERVAL_SECONDS: float = 1.0
const JOIN_PROBE_INTERVAL_SECONDS: float = 0.35
const TRAVERSAL_PACKET_PREFIX: String = "straywild_TRAVERSAL_V1 "
const TRAVERSAL_PACKET_PREFIX: String = "NETFISHING_TRAVERSAL_V1 "
const UPNP_MAPPING_DURATION_SECONDS: int = 3600
const UPNP_RENEW_INTERVAL_SECONDS: float = 2700.0
const UPNP_RETRY_INTERVAL_SECONDS: float = 300.0
@ -554,10 +553,6 @@ func is_own_room(room: Dictionary) -> bool:
func _configured_base_url() -> String:
var value: String = OS.get_environment(BASE_URL_ENVIRONMENT).strip_edges()
if value.is_empty():
value = OS.get_environment(
LEGACY_BASE_URL_ENVIRONMENT
).strip_edges()
if value.is_empty():
value = str(ProjectSettings.get_setting(BASE_URL_SETTING, "")).strip_edges()
while value.ends_with("/"):
@ -565,7 +560,7 @@ func _configured_base_url() -> String:
if not value.is_empty() and not (
value.begins_with("https://") or value.begins_with("http://")
):
push_warning("Ignored invalid straywild discovery URL.")
push_warning("Ignored invalid NETfishing discovery URL.")
return ""
return value
@ -814,7 +809,7 @@ func _on_traversal_request_completed(
var port: int = int(endpoint.get("port", 0))
if address.is_empty() or port < 1 or port > 65535:
continue
var punch: PackedByteArray = "straywild_PUNCH_V1".to_utf8_buffer()
var punch: PackedByteArray = "NETFISHING_PUNCH_V1".to_utf8_buffer()
for _attempt: int in 3:
_session.send_traversal_packet(address, port, punch)
@ -900,13 +895,13 @@ func _configure_upnp_mapping(port: int) -> Dictionary:
var mapping_result: int = upnp.add_port_mapping(
port,
port,
"straywild",
"NETfishing",
"UDP",
UPNP_MAPPING_DURATION_SECONDS,
)
if mapping_result == UPNP.UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED:
mapping_result = upnp.add_port_mapping(
port, port, "straywild", "UDP", 0
port, port, "NETfishing", "UDP", 0
)
return {
"success": mapping_result == UPNP.UPNP_RESULT_SUCCESS,
@ -1379,18 +1374,18 @@ func _discovery_version_mismatch_message(required_version: String) -> String:
match rejection:
NetworkProtocol.RejectionCode.CLIENT_OUTDATED:
return (
"Your straywild version is out of date. Update to %s to "
"Your NETfishing version is out of date. Update to %s to "
+ "enable public discovery. This room will not be listed "
+ "until you update."
) % required_version
NetworkProtocol.RejectionCode.SERVER_OUTDATED:
return (
"Public discovery is still on straywild %s. This room "
"Public discovery is still on NETfishing %s. This room "
+ "will not be listed until discovery is updated for %s."
) % [required_version, local_version]
_:
return (
"Public discovery requires straywild %s. This room will "
"Public discovery requires NETfishing %s. This room will "
+ "not be listed until both versions match."
) % required_version
@ -1582,4 +1577,4 @@ func _save_settings() -> void:
config.set_value("social", "share_presence", _presence_sharing)
var error: Error = config.save(SETTINGS_PATH)
if error != OK:
push_warning("Could not save local straywild discovery settings.")
push_warning("Could not save local NETfishing discovery settings.")

View file

@ -17,10 +17,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_store_path = path
_data_root = data_root
_namespaces.clear()
_loaded = false
_write_blocked = false
_expected_hash = ""
func is_banned(host_fingerprint: String, target_fingerprint: String) -> bool:

View file

@ -3,8 +3,7 @@ extends Node
signal operation_finished(success: bool, message: String)
const MAGIC := "straywild_IDENTITY_BACKUP"
const LEGACY_MAGIC := "NETFISHING_IDENTITY_BACKUP"
const MAGIC := "NETFISHING_IDENTITY_BACKUP"
const FORMAT_VERSION := 1
const MAX_BACKUP_BYTES := 256 * 1024
const MIN_PASSPHRASE_LENGTH := 12
@ -111,9 +110,8 @@ func inspect_backup(
if json.parse(text) != OK or typeof(json.data) != TYPE_DICTIONARY:
return {"ok": false}
var data: Dictionary = json.data
var legacy_backup: bool = data.get("magic") == LEGACY_MAGIC
if (
data.get("magic") not in [MAGIC, LEGACY_MAGIC]
data.get("magic") != MAGIC
or data.get("format_version") != FORMAT_VERSION
or data.get("identity_type") != expected_type
or data.get("algorithm") != NetworkIdentityCrypto.ALGORITHM
@ -136,23 +134,12 @@ func inspect_backup(
var signature: PackedByteArray = Marshalls.base64_to_raw(
str(data.get("self_signature", ""))
)
var public_key: CryptoKey = NetworkIdentityCrypto.load_public_key(public_pem)
var backup_signature_valid: bool = (
NetworkIdentityCrypto.verify_legacy_fields(
public_key,
"identity_backup_self_test",
[expected_type, fingerprint],
signature,
)
if legacy_backup
else NetworkIdentityCrypto.verify_fields(
public_key,
"identity_backup_self_test",
[expected_type, fingerprint],
signature,
)
)
if not backup_signature_valid:
if not NetworkIdentityCrypto.verify_fields(
NetworkIdentityCrypto.load_public_key(public_pem),
"identity_backup_self_test",
[expected_type, fingerprint],
signature,
):
return {"ok": false}
var fresh: PackedByteArray = NetworkIdentityCrypto.sign_fields(
key, "identity_import_self_test", [fingerprint]
@ -202,7 +189,7 @@ func import_backup(
)
_finish(
bool(result.get("ok", false)),
"Identity imported. Restart straywild before multiplayer."
"Identity imported. Restart NETfishing before multiplayer."
if bool(result.get("ok", false))
else "Could not install this identity backup.",
)

View file

@ -15,10 +15,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_store_path = path
_data_root = data_root
_records.clear()
_loaded = false
_write_blocked = false
_expected_hash = ""
func observe(fingerprint: String, display_name: String) -> String:

View file

@ -5,8 +5,7 @@ const ALGORITHM: String = "RSA-3072-SHA256"
const FINGERPRINT_LENGTH: int = 64
const MAX_PUBLIC_KEY_BYTES: int = 8192
const MAX_SIGNATURE_BYTES: int = 1024
const DOMAIN_PREFIX: String = "straywild"
const LEGACY_DOMAIN_PREFIX: String = "NETFISHING"
const DOMAIN_PREFIX: String = "NETFISHING"
const IDENTITY_VERSION: String = "identity_v1"
@ -51,16 +50,8 @@ static func secure_id(byte_count: int = 16) -> String:
static func canonical_bytes(domain: String, fields: Array) -> PackedByteArray:
return canonical_bytes_for_prefix(DOMAIN_PREFIX, domain, fields)
static func canonical_bytes_for_prefix(
prefix: String,
domain: String,
fields: Array,
) -> PackedByteArray:
var output := PackedByteArray()
_append_string(output, prefix)
_append_string(output, DOMAIN_PREFIX)
_append_string(output, IDENTITY_VERSION)
_append_string(output, domain)
for value: Variant in fields:
@ -126,37 +117,6 @@ static func verify_fields(
)
static func verify_legacy_fields(
public_key: CryptoKey,
domain: String,
fields: Array,
signature: PackedByteArray,
) -> bool:
if (
public_key == null
or signature.is_empty()
or signature.size() > MAX_SIGNATURE_BYTES
):
return false
var bytes: PackedByteArray = canonical_bytes_for_prefix(
LEGACY_DOMAIN_PREFIX,
domain,
fields,
)
if bytes.is_empty():
return false
var context := HashingContext.new()
if context.start(HashingContext.HASH_SHA256) != OK:
return false
context.update(bytes)
return Crypto.new().verify(
HashingContext.HASH_SHA256,
context.finish(),
signature,
public_key,
)
static func load_public_key(public_pem: String) -> CryptoKey:
var normalized := normalize_public_pem(public_pem)
if normalized.is_empty() or normalized.to_utf8_buffer().size() > MAX_PUBLIC_KEY_BYTES:

View file

@ -21,8 +21,6 @@ var _future_version := false
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_profile_path = path
_data_root = data_root
_expected_hash = ""
_future_version = false
func _temp_path() -> String:

View file

@ -51,17 +51,6 @@ func setup(
_apply_local_voice_to_avatar()
func reload_persisted_profile() -> bool:
if (
not _preferences.load_or_create()
or not _appearance_store.load_preferences()
):
return false
_apply_to_avatar(1, _appearance_store.get_snapshot())
_apply_local_voice_to_avatar()
return true
func get_persisted_name() -> String:
return _preferences.display_name

View file

@ -3,7 +3,7 @@ extends RefCounted
const WorldLayoutType = preload("res://world/world_layout.gd")
const PROTOCOL_VERSION: int = 11
const PROTOCOL_VERSION: int = 10
const GAME_BUILD: String = "prealpha"
const MAX_GAME_VERSION_LENGTH: int = 64
const MAX_DISPLAY_NAME_LENGTH: int = 24
@ -304,7 +304,7 @@ static func make_server_hello(
assigned_peer_id: int,
player_count: int,
max_players: int,
server_display_name: String = "straywild",
server_display_name: String = "NETfishing",
world_seed: int = DEFAULT_WORLD_SEED,
world_layout: StringName = WorldLayoutType.GENERATED,
) -> Dictionary:
@ -372,17 +372,17 @@ static func rejection_text(code: int) -> String:
return "You are not permitted to join this server."
RejectionCode.CLIENT_OUTDATED:
return (
"Your straywild version is out of date. "
"Your NETfishing version is out of date. "
+ "Update the game to join this server."
)
RejectionCode.SERVER_OUTDATED:
return (
"This server is out of date. "
+ "The host needs to update straywild."
+ "The host needs to update NETfishing."
)
RejectionCode.VERSION_MISMATCH:
return (
"This game and server use different straywild versions. "
"This game and server use different NETfishing versions. "
+ "Update both to the latest release."
)
_:

View file

@ -160,7 +160,7 @@ var _local_appearance_snapshot: Dictionary = (
)
var _moderation_disconnect_message := ""
var _host_port: int = 0
var _session_display_name: String = "straywild Room"
var _session_display_name: String = "NETfishing Room"
var _dedicated_host: bool = false
var _configured_operator_fingerprints: Dictionary[String, bool] = {}
var _session_operator_fingerprints: Dictionary[String, bool] = {}
@ -432,7 +432,7 @@ func set_peer_operator(
func set_session_display_name(value: String) -> void:
var cleaned: String = value.strip_edges().left(48)
if cleaned.is_empty():
cleaned = "straywild Room"
cleaned = "NETfishing Room"
if cleaned == _session_display_name:
return
_session_display_name = cleaned
@ -1187,7 +1187,7 @@ func resolve_server_trust(accepted: bool) -> void:
if not _server_trust.trust(
get_current_endpoint(),
str(_pending_server_proof["server_fingerprint"]),
"straywild",
"NETfishing",
):
_fail_identity("The server identity could not be pinned.")
return

View file

@ -879,7 +879,7 @@ func export_canvas_png(canvas_id: String) -> String:
_emit_hud_state("paint something before exporting")
return ""
if _data_root == null or _data_root.root_path.is_empty():
_emit_hud_state("choose a straywild data folder before exporting")
_emit_hud_state("choose a NETfishing data folder before exporting")
return ""
var export_directory: String = _artwork_directory()
if DirAccess.make_dir_recursive_absolute(export_directory) != OK:
@ -990,7 +990,7 @@ func _stamp_entry_is_unlocked(entry: Dictionary) -> bool:
func _next_artwork_export_path(directory: String) -> String:
var date_time: Dictionary = Time.get_datetime_dict_from_system()
var stem: String = "straywild-artwork-%04d%02d%02d-%02d%02d%02d" % [
var stem: String = "netfishing-artwork-%04d%02d%02d-%02d%02d%02d" % [
int(date_time.get("year", 0)),
int(date_time.get("month", 0)),
int(date_time.get("day", 0)),

View file

@ -9,42 +9,12 @@ const BOOTSTRAP_TEMP_PATH := "user://data_root_bootstrap.json.tmp"
const BOOTSTRAP_VERSION := 1
const MANIFEST_VERSION := 1
const LAYOUT_VERSION := 1
const MANIFEST_FILENAME := "straywild_data.json"
const LEGACY_MANIFEST_FILENAME := "netfishing_data.json"
const MANIFEST_FILENAME := "netfishing_data.json"
const README_FILENAME := "README.txt"
const ENVIRONMENT_VARIABLE := "straywild_DATA_DIR"
const CREATE_ENVIRONMENT_VARIABLE := "straywild_CREATE_DATA_DIR"
const LEGACY_ENVIRONMENT_VARIABLE := "NETFISHING_DATA_DIR"
const LEGACY_CREATE_ENVIRONMENT_VARIABLE := "NETFISHING_CREATE_DATA_DIR"
const APPLICATION_ID := "straywild"
const LEGACY_APPLICATION_ID := "netfishing"
const ENVIRONMENT_VARIABLE := "NETFISHING_DATA_DIR"
const CREATE_ENVIRONMENT_VARIABLE := "NETFISHING_CREATE_DATA_DIR"
const APPLICATION_ID := "netfishing"
const APP_DATA_PORTABLE_PATH := "user://portable-data"
const LEGACY_USER_DIRECTORY_NAME := "NETFISHING"
const LEGACY_USER_FILES := [
"data_root_bootstrap.json",
"data_root_bootstrap.json.backup",
"network_discovery.cfg",
"player_settings.json",
"player_settings.json.backup",
"controller_mappings.json",
"controller_mappings.json.backup",
"keyboard_mouse_bindings.json",
"keyboard_mouse_bindings.json.backup",
"player_save.json",
"network_profile.json",
"player_appearance.json",
"saved_servers.json",
"known_players.json",
"player_relationships.json",
"server_trust.json",
"host_bans.json",
"player_identity.key",
"player_identity.pub",
"player_identity.json",
"host_identity.key",
"host_identity.pub",
"host_identity.json",
]
const PATH_ALLOWED: StringName = &"allowed"
const PATH_SOURCE_PROJECT: StringName = &"source_project"
const PATH_INSTALLATION: StringName = &"installation"
@ -67,29 +37,23 @@ var override_active := false
func resolve() -> bool:
prepare_legacy_user_data()
_load_bootstrap_identity()
var command_line: String = _command_line_override()
if not command_line.is_empty():
override_active = true
mode = Mode.COMMAND_LINE_OVERRIDE
return _activate_existing(command_line, "", false)
var environment_variable: String = _available_environment_variable(
ENVIRONMENT_VARIABLE,
LEGACY_ENVIRONMENT_VARIABLE,
)
if not environment_variable.is_empty():
if OS.has_environment(ENVIRONMENT_VARIABLE):
override_active = true
mode = Mode.ENVIRONMENT_OVERRIDE
var environment_path: String = OS.get_environment(environment_variable)
var environment_path: String = OS.get_environment(ENVIRONMENT_VARIABLE)
if not environment_path.is_absolute_path():
return _fail("straywild_DATA_DIR must be an absolute path.")
return _fail("NETFISHING_DATA_DIR must be an absolute path.")
if (
_environment_flag(
CREATE_ENVIRONMENT_VARIABLE,
LEGACY_CREATE_ENVIRONMENT_VARIABLE,
OS.get_environment(CREATE_ENVIRONMENT_VARIABLE) == "1"
and not FileAccess.file_exists(
environment_path.path_join(MANIFEST_FILENAME)
)
and not has_data_manifest(environment_path)
):
var created: Dictionary = create_unbound_root(environment_path)
if not bool(created.get("ok", false)):
@ -116,35 +80,11 @@ func resolve() -> bool:
return false
func prepare_legacy_user_data() -> void:
var current_root: String = _normalize(
ProjectSettings.globalize_path("user://")
)
if current_root.is_empty():
return
var legacy_root: String = _normalize(
current_root.get_base_dir().path_join(LEGACY_USER_DIRECTORY_NAME)
)
if legacy_root == current_root or not DirAccess.dir_exists_absolute(legacy_root):
return
for filename: String in LEGACY_USER_FILES:
var destination: String = current_root.path_join(filename)
if FileAccess.file_exists(destination):
continue
var source: String = legacy_root.path_join(filename)
if FileAccess.file_exists(source):
_copy_legacy_user_file(source, destination)
func has_data_manifest(path: String) -> bool:
return not _existing_manifest_path(_normalize(path)).is_empty()
func default_visible_path() -> String:
var documents: String = OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS)
if documents.is_empty():
return ""
var candidate: String = _normalize(documents.path_join("straywild"))
var candidate: String = _normalize(documents.path_join("NETFISHING"))
if not candidate.is_absolute_path():
return ""
var classification: StringName = classify_candidate_path(
@ -165,22 +105,20 @@ func select_new_root(path: String, app_data: bool = false) -> bool:
normalized = ProjectSettings.globalize_path(APP_DATA_PORTABLE_PATH)
if not _validate_candidate(normalized, true):
return false
var manifest_path: String = _existing_manifest_path(normalized)
if not manifest_path.is_empty():
var manifest_path: String = normalized.path_join(MANIFEST_FILENAME)
if FileAccess.file_exists(manifest_path):
var manifest: Dictionary = _read_json(manifest_path)
if not _valid_manifest(manifest):
return _fail("The selected folder has a malformed straywild manifest.")
return _fail("The selected folder has a malformed NETfishing manifest.")
root_id = str(manifest["root_id"])
if not _upgrade_legacy_manifest(normalized, manifest, manifest_path):
return _fail("The legacy data-folder manifest could not be upgraded.")
else:
if not _directory_is_empty(normalized) and not app_data:
return _fail(
"Choose an empty folder or an existing straywild data folder."
"Choose an empty folder or an existing NETfishing data folder."
)
root_id = Crypto.new().generate_random_bytes(16).hex_encode()
if not _create_layout(normalized, root_id):
return _fail("The straywild data folder could not be created.")
return _fail("The NETfishing data folder could not be created.")
if not _write_bootstrap(normalized, root_id):
return _fail("The data-folder pointer could not be saved.")
root_path = normalized
@ -207,14 +145,14 @@ func create_app_data_layout_for_migration(path: String) -> Dictionary:
var normalized: String = _normalize(path)
if not _validate_candidate(normalized, false):
return {"ok": false, "message": error_message}
var manifest_path: String = _existing_manifest_path(normalized)
if not manifest_path.is_empty():
var manifest_path: String = normalized.path_join(MANIFEST_FILENAME)
if FileAccess.file_exists(manifest_path):
var manifest: Dictionary = _read_json(manifest_path)
if not _valid_manifest(manifest):
return {"ok": false, "message": "The app-data manifest is malformed."}
if not _upgrade_legacy_manifest(normalized, manifest, manifest_path):
return {"ok": false, "message": "The app-data manifest could not be upgraded."}
return {"ok": true, "root_id": str(manifest.get("root_id", ""))}
return (
{"ok": true, "root_id": str(manifest.get("root_id", ""))}
if _valid_manifest(manifest)
else {"ok": false, "message": "The app-data manifest is malformed."}
)
var id: String = Crypto.new().generate_random_bytes(16).hex_encode()
if not _create_layout(normalized, id):
return {"ok": false, "message": "The app-data layout could not be created."}
@ -298,19 +236,17 @@ func _activate_existing(path: String, expected_id: String, permit_creation: bool
var normalized: String = _normalize(path)
if not _validate_candidate(normalized, permit_creation):
return false
var manifest_path: String = _existing_manifest_path(normalized)
if manifest_path.is_empty():
return _fail("The selected folder is not a straywild data folder.")
var manifest_path: String = normalized.path_join(MANIFEST_FILENAME)
if not FileAccess.file_exists(manifest_path):
return _fail("The selected folder is not a NETfishing data folder.")
var manifest: Dictionary = _read_json(manifest_path)
if not _valid_manifest(manifest):
return _fail("The straywild data-folder manifest is malformed.")
if not _upgrade_legacy_manifest(normalized, manifest, manifest_path):
return _fail("The legacy data-folder manifest could not be upgraded.")
return _fail("The NETfishing data-folder manifest is malformed.")
var found_id: String = str(manifest["root_id"])
if not expected_id.is_empty() and expected_id != found_id:
return _fail("The selected data folder does not match this device pointer.")
if not _test_writable(normalized):
return _fail("The straywild data folder is unavailable or unwritable.")
return _fail("The NETfishing data folder is unavailable or unwritable.")
root_path = normalized
root_id = found_id
requires_selection = false
@ -403,7 +339,7 @@ static func _is_same_or_child_path(candidate: String, reference: String) -> bool
func _test_writable(path: String) -> bool:
var probe: String = path.path_join(
".straywild-write-%s.tmp" % device_id.left(12)
".netfishing-write-%s.tmp" % device_id.left(12)
)
var file: FileAccess = FileAccess.open(probe, FileAccess.WRITE)
if file == null:
@ -434,7 +370,7 @@ func _create_layout(path: String, id: String) -> bool:
):
return false
var readme: String = (
"straywild player data\n\n"
"NETfishing player data\n\n"
+ "This folder is safe to synchronize with tools such as Syncthing.\n"
+ "Active private identity keys remain device-local.\n"
+ "Encrypted identity backups require their passphrase.\n"
@ -486,71 +422,12 @@ func _valid_manifest(data: Dictionary) -> bool:
return (
data.get("format_version") == MANIFEST_VERSION
and data.get("layout_version") == LAYOUT_VERSION
and data.get("application") in [APPLICATION_ID, LEGACY_APPLICATION_ID]
and data.get("application") == APPLICATION_ID
and typeof(data.get("root_id")) == TYPE_STRING
and str(data["root_id"]).length() == 32
)
func _existing_manifest_path(path: String) -> String:
var current: String = path.path_join(MANIFEST_FILENAME)
if FileAccess.file_exists(current):
return current
var legacy: String = path.path_join(LEGACY_MANIFEST_FILENAME)
return legacy if FileAccess.file_exists(legacy) else ""
func _upgrade_legacy_manifest(
path: String,
manifest: Dictionary,
manifest_path: String,
) -> bool:
if (
manifest_path.get_file() == MANIFEST_FILENAME
and manifest.get("application") == APPLICATION_ID
):
return true
var upgraded: Dictionary = manifest.duplicate(true)
upgraded["application"] = APPLICATION_ID
upgraded["last_opened_at_unix"] = int(Time.get_unix_time_from_system())
return _write_text_atomic(
path.path_join(MANIFEST_FILENAME),
JSON.stringify(upgraded, "\t"),
)
func _available_environment_variable(primary: String, legacy: String) -> String:
if OS.has_environment(primary):
return primary
return legacy if OS.has_environment(legacy) else ""
func _environment_flag(primary: String, legacy: String) -> bool:
var variable: String = _available_environment_variable(primary, legacy)
return not variable.is_empty() and OS.get_environment(variable) == "1"
func _copy_legacy_user_file(source: String, destination: String) -> bool:
var bytes: PackedByteArray = PortableFileGuard.read_bytes(
source,
16 * 1024 * 1024,
)
if bytes.is_empty() and FileAccess.get_open_error() != OK:
return false
if DirAccess.make_dir_recursive_absolute(destination.get_base_dir()) != OK:
return false
var file: FileAccess = FileAccess.open(destination, FileAccess.WRITE)
if file == null:
return false
file.store_buffer(bytes)
file.flush()
var copied: bool = file.get_error() == OK
file.close()
if copied and source.ends_with(".key"):
FileAccess.set_unix_permissions(destination, 384)
return copied
func _directory_is_empty(path: String) -> bool:
var access: DirAccess = DirAccess.open(path)
if access == null:

View file

@ -7,8 +7,8 @@ const FORMAT_VERSION := 2
const MAX_RECORDS := 500
const MAX_FRIENDS := 200
const SOCIAL_TOKEN_LENGTH := 64
const PRESENCE_CHANNEL_DOMAIN := "straywild_PRESENCE_V1:"
const INVITE_INBOX_DOMAIN := "straywild_INVITE_V1:"
const PRESENCE_CHANNEL_DOMAIN := "NETFISHING_PRESENCE_V1:"
const INVITE_INBOX_DOMAIN := "NETFISHING_INVITE_V1:"
var _records: Dictionary = {}
var _loaded := false
@ -21,10 +21,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_store_path = path
_data_root = data_root
_records.clear()
_loaded = false
_write_blocked = false
_expected_hash = ""
func is_muted(fingerprint: String) -> bool:

View file

@ -26,16 +26,19 @@ static func migrate_legacy_to(
) -> Dictionary:
var normalized: String = destination.simplify_path().trim_suffix("/")
if DirAccess.dir_exists_absolute(normalized):
if data_root.has_data_manifest(normalized):
var existing_manifest: String = normalized.path_join(
PlayerDataRoot.MANIFEST_FILENAME
)
if FileAccess.file_exists(existing_manifest):
return {
"ok": false,
"requires_existing_root_decision": true,
"message": "The selected folder already contains straywild data.",
"message": "The selected folder already contains NETfishing data.",
}
if not _directory_empty(normalized):
return {
"ok": false,
"message": "Choose an empty folder or create a straywild subfolder.",
"message": "Choose an empty folder or create a NETfishing subfolder.",
}
var staging: String = "%s.migration-%s" % [
normalized, Crypto.new().generate_random_bytes(8).hex_encode()
@ -103,16 +106,16 @@ static func migrate_active_to(
"message": "This data folder is already active.",
}
if DirAccess.dir_exists_absolute(normalized) and not _directory_empty(normalized):
if data_root.has_data_manifest(normalized):
if FileAccess.file_exists(normalized.path_join(PlayerDataRoot.MANIFEST_FILENAME)):
return {
"ok": false,
"requires_existing_root_decision": true,
"message": (
"The selected folder already contains straywild data. "
"The selected folder already contains NETfishing data. "
+ "Choose it through the existing-data recovery flow."
),
}
return {"ok": false, "message": "Choose an empty folder or a straywild subfolder."}
return {"ok": false, "message": "Choose an empty folder or a NETfishing subfolder."}
var staging: String = "%s.migration-%s" % [
normalized, Crypto.new().generate_random_bytes(8).hex_encode()
]
@ -204,8 +207,9 @@ static func replace_existing_with_legacy(
destination: String,
) -> Dictionary:
var normalized: String = destination.simplify_path().trim_suffix("/")
if not data_root.has_data_manifest(normalized):
return {"ok": false, "message": "The selected folder is not a straywild data root."}
var manifest: String = normalized.path_join(PlayerDataRoot.MANIFEST_FILENAME)
if not FileAccess.file_exists(manifest):
return {"ok": false, "message": "The selected folder is not a NETfishing data root."}
var recovery: String = ProjectSettings.globalize_path(
"user://migration-recovery"
).path_join(
@ -225,8 +229,8 @@ static func replace_existing_with_active(
destination: String,
) -> Dictionary:
var normalized: String = destination.simplify_path().trim_suffix("/")
if not data_root.has_data_manifest(normalized):
return {"ok": false, "message": "The selected folder is not a straywild data root."}
if not FileAccess.file_exists(normalized.path_join(PlayerDataRoot.MANIFEST_FILENAME)):
return {"ok": false, "message": "The selected folder is not a NETfishing data root."}
var recovery: String = ProjectSettings.globalize_path(
"user://migration-recovery"
).path_join(

View file

@ -22,12 +22,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_store_path = path
_data_root = data_root
_saved_entries.clear()
_recent_entries.clear()
_loaded = false
_recovery_warning = ""
_write_blocked = false
_expected_hash = ""
func _temp_path() -> String:

View file

@ -19,10 +19,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_store_path = path
_data_root = data_root
_records.clear()
_loaded = false
_write_blocked = false
_expected_hash = ""
func verify(endpoint: ConnectionEndpoint, fingerprint: String) -> Verification:

View file

@ -1,88 +1,7 @@
extends "res://player/tool_socket_attachment.gd"
const TextureSamplingPolicyScript := preload(
"res://main/texture_sampling_policy.gd"
)
const SPRING_ROOT_BONE: StringName = &"net_mid"
const SPRING_END_BONE: StringName = &"net_tip"
const IMPACT_BONE: StringName = &"net_rim"
@export_range(0.0, 10.0, 0.05) var spring_stiffness: float = 1.8
@export_range(0.0, 1.0, 0.01) var spring_drag: float = 0.68
@export_range(0.0, 10.0, 0.05) var spring_gravity: float = 0.3
@export_range(0.01, 0.5, 0.01) var spring_end_length: float = 0.1
@onready var _catching_net: Node3D = %CatchingNet
@onready var _net_model: Node3D = %NetModel
var _spring: SpringBoneSimulator3D
var _spring_was_visible: bool = false
var _net_skeleton: Skeleton3D
func _ready() -> void:
super._ready()
TextureSamplingPolicyScript.enforce_subtree(_net_model)
_configure_spring()
_sync_spring_activity()
func _process(_delta: float) -> void:
_sync_spring_activity()
func _configure_spring() -> void:
_net_skeleton = _net_model.find_child(
"Skeleton3D", true, false
) as Skeleton3D
if _net_skeleton == null:
push_error("Imported net model is missing its Skeleton3D.")
return
if _net_skeleton.find_bone(SPRING_ROOT_BONE) < 0:
push_error("Imported net model is missing bone %s." % SPRING_ROOT_BONE)
return
if _net_skeleton.find_bone(SPRING_END_BONE) < 0:
push_error("Imported net model is missing bone %s." % SPRING_END_BONE)
return
if _net_skeleton.find_bone(IMPACT_BONE) < 0:
push_error("Imported net model is missing bone %s." % IMPACT_BONE)
return
_spring = SpringBoneSimulator3D.new()
_spring.name = "NetSpring"
_spring.set_setting_count(1)
_spring.set_root_bone_name(0, SPRING_ROOT_BONE)
_spring.set_end_bone_name(0, SPRING_END_BONE)
_spring.set_extend_end_bone(0, true)
_spring.set_end_bone_direction(
0, SkeletonModifier3D.BONE_DIRECTION_FROM_PARENT
)
_spring.set_end_bone_length(0, spring_end_length)
_spring.set_stiffness(0, spring_stiffness)
_spring.set_drag(0, spring_drag)
_spring.set_gravity(0, spring_gravity)
_spring.set_gravity_direction(0, Vector3.DOWN)
_net_skeleton.add_child(_spring)
@onready var _impact_marker: Marker3D = %ImpactMarker
func get_impact_world_position() -> Vector3:
if _net_skeleton == null:
return _catching_net.global_position
var impact_bone_index := _net_skeleton.find_bone(IMPACT_BONE)
if impact_bone_index < 0:
return _catching_net.global_position
return _net_skeleton.global_transform * (
_net_skeleton.get_bone_global_pose(impact_bone_index).origin
)
func _sync_spring_activity() -> void:
if _spring == null:
return
var is_visible := _catching_net.is_visible_in_tree()
if is_visible and not _spring_was_visible:
_spring.active = true
_spring.reset()
elif not is_visible:
_spring.active = false
_spring_was_visible = is_visible
return _impact_marker.global_position

View file

@ -1,7 +1,42 @@
[gd_scene load_steps=3 format=3]
[gd_scene load_steps=8 format=3]
[ext_resource type="Script" path="res://player/net_attachment.gd" id="1_script"]
[ext_resource type="PackedScene" path="res://art/exported/items/equipment/net.glb" id="2_model"]
[sub_resource type="StandardMaterial3D" id="HandleMaterial"]
albedo_color = Color(0.25, 0.13, 0.055, 1)
roughness = 0.9
[sub_resource type="CylinderMesh" id="HandleMesh"]
material = SubResource("HandleMaterial")
top_radius = 0.025
bottom_radius = 0.035
height = 1.25
[sub_resource type="StandardMaterial3D" id="HoopMaterial"]
albedo_color = Color(0.34, 0.39, 0.4, 1)
metallic = 0.25
roughness = 0.65
[sub_resource type="TorusMesh" id="HoopMesh"]
material = SubResource("HoopMaterial")
inner_radius = 0.24
outer_radius = 0.29
rings = 12
ring_segments = 18
[sub_resource type="StandardMaterial3D" id="NetMaterial"]
transparency = 1
albedo_color = Color(0.65, 0.78, 0.75, 0.42)
shading_mode = 0
cull_mode = 2
[sub_resource type="CylinderMesh" id="NetMesh"]
material = SubResource("NetMaterial")
top_radius = 0.24
bottom_radius = 0.08
height = 0.34
radial_segments = 12
rings = 1
[node name="NetAttachment" type="BoneAttachment3D"]
bone_name = "rod_socket"
@ -12,9 +47,18 @@ aligned_mount_path = NodePath("CatchingNet")
unique_name_in_owner = true
visible = false
[node name="ModelMount" type="Node3D" parent="CatchingNet"]
position = Vector3(-0.000217, -0.098636, -0.020218)
rotation = Vector3(0, 3.1415927, 0)
[node name="Handle" type="MeshInstance3D" parent="CatchingNet"]
position = Vector3(0, 0.55, 0)
mesh = SubResource("HandleMesh")
[node name="NetModel" parent="CatchingNet/ModelMount" unique_id=1627767240 instance=ExtResource("2_model")]
[node name="Hoop" type="MeshInstance3D" parent="CatchingNet"]
position = Vector3(0, 1.17, 0)
mesh = SubResource("HoopMesh")
[node name="Bag" type="MeshInstance3D" parent="CatchingNet"]
position = Vector3(0, 1, 0)
mesh = SubResource("NetMesh")
[node name="ImpactMarker" type="Marker3D" parent="CatchingNet"]
unique_name_in_owner = true
position = Vector3(0, 1.17, 0)

View file

@ -12,7 +12,7 @@
[ext_resource type="Script" path="res://progression/player_cooler_capacity.gd" id="10_capacity"]
[ext_resource type="Script" path="res://player/player_ground_shadow.gd" id="11_ground_shadow"]
[ext_resource type="Material" path="res://player/materials/player_blob_shadow.tres" id="12_blob_shadow"]
[ext_resource type="PackedScene" path="res://art/exported/characters/base/straywild_base_character.glb" id="13_character"]
[ext_resource type="PackedScene" path="res://art/exported/characters/base/netfishing_base_character.glb" id="13_character"]
[ext_resource type="Script" path="res://progression/player_art_unlocks.gd" id="14_art_unlocks"]
[ext_resource type="Script" path="res://progression/player_experience.gd" id="15_experience"]
[ext_resource type="Script" path="res://player/sprint_dust_trail.gd" id="16_sprint_dust"]

View file

@ -3,9 +3,9 @@ extends RefCounted
const PlayerScene: PackedScene = preload("res://player/player.tscn")
const FurPatternShader: Shader = preload("res://player/fur_pattern.gdshader")
const RUNTIME_MATERIAL_META: StringName = &"straywild_runtime_material"
const RUNTIME_MATERIAL_META: StringName = &"netfishing_runtime_material"
const RUNTIME_FUR_PATTERN_MATERIAL_META: StringName = (
&"straywild_runtime_fur_pattern_material"
&"netfishing_runtime_fur_pattern_material"
)
const EAR_MESH_NAMES: Array[String] = [
"ears_antlers_round",

View file

@ -13,10 +13,6 @@ var _data_root: PlayerDataRoot
func configure_storage(path: String, data_root: PlayerDataRoot) -> void:
_profile_path = path
_data_root = data_root
_snapshot = CharacterCustomizationCatalog.default_snapshot()
_loaded = false
_future_version = false
_expected_hash = ""
func _temp_path() -> String:

View file

@ -10,11 +10,11 @@ config_version=5
[application]
config/name="straywild"
config/version="0.19.0-alpha"
config/name="NETFISHING"
config/version="0.18.1-alpha"
run/main_scene="res://main/main.tscn"
config/features=PackedStringArray("4.7", "GL Compatibility")
config/icon="res://art/exported/system_icons/straywild_256.png"
config/icon="res://art/exported/system_icons/netfishing_256.png"
[autoload]
@ -26,7 +26,7 @@ window/stretch/aspect="expand"
[editor_plugins]
enabled=PackedStringArray("res://addons/straywild_shoreline_baker/plugin.cfg")
enabled=PackedStringArray("res://addons/netfishing_shoreline_baker/plugin.cfg")
[gui]
@ -260,7 +260,7 @@ alternate_fishing={
[network]
discovery/base_url="https://discovery.straywild.io"
discovery/base_url="https://discovery.netfishing.org"
[physics]

View file

@ -1,8 +1,7 @@
class_name ProgressionSaveCodec
extends RefCounted
const MAGIC := "straywild_PROGRESSION_CONTAINER"
const LEGACY_MAGIC := "NETFISHING_PROGRESSION_CONTAINER"
const MAGIC := "NETFISHING_PROGRESSION_CONTAINER"
const FORMAT_VERSION := 1
const LOCAL_KIND := "local_save"
const ARCHIVE_KIND := "portable_archive"
@ -10,8 +9,6 @@ const MAX_CONTAINER_BYTES := 16 * 1024 * 1024
# This key keeps routine progression files opaque to casual editing. Since the
# client is open source, it is intentionally not treated as a security secret.
# Its original value is a stable file-format detail so released saves remain
# readable after the Straywild rebrand.
const CONTAINER_PASSPHRASE := (
"NETfishing progression container v1 / not an identity credential"
)
@ -105,9 +102,15 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
or FileAccess.get_size(path) > MAX_CONTAINER_BYTES
):
return {"ok": false, "message": "progression file is unavailable."}
var envelope_text: String = _read_encrypted_text(path)
if envelope_text.is_empty():
var file: FileAccess = FileAccess.open_encrypted_with_pass(
path,
FileAccess.READ,
CONTAINER_PASSPHRASE,
)
if file == null:
return {"ok": false, "message": "progression file could not be opened."}
var envelope_text: String = file.get_as_text()
file.close()
var envelope_json := JSON.new()
if (
envelope_json.parse(envelope_text) != OK
@ -115,9 +118,8 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
):
return {"ok": false, "message": "progression container is malformed."}
var envelope: Dictionary = envelope_json.data
var legacy_container: bool = envelope.get("magic") == LEGACY_MAGIC
if (
envelope.get("magic") not in [MAGIC, LEGACY_MAGIC]
envelope.get("magic") != MAGIC
or int(envelope.get("format_version", -1)) != FORMAT_VERSION
or str(envelope.get("kind", "")) != expected_kind
):
@ -142,23 +144,9 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
"game_version": str(envelope.get("game_version", "")),
"created_at_unix": int(envelope.get("created_at_unix", 0)),
"legacy_plaintext": false,
"legacy_container": legacy_container,
}
static func _read_encrypted_text(path: String) -> String:
var file: FileAccess = FileAccess.open_encrypted_with_pass(
path,
FileAccess.READ,
CONTAINER_PASSPHRASE,
)
if file == null:
return ""
var text: String = file.get_as_text()
file.close()
return text
static func _read_plaintext_dictionary(path: String) -> Dictionary:
var bytes: PackedByteArray = PortableFileGuard.read_bytes(
path,

View file

@ -4,7 +4,7 @@ set -euo pipefail
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
readonly OUTPUT_PATH="${PROJECT_ROOT}/builds/android/straywild-debug.apk"
readonly OUTPUT_PATH="${PROJECT_ROOT}/builds/android/NETfishing-debug.apk"
readonly GODOT_BIN="${GODOT_BIN:-godot}"
mkdir -p -- "$(dirname -- "${OUTPUT_PATH}")"

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.19.0-alpha"
readonly BUILD_ROOT="${PROJECT_ROOT}/builds/v0.18.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/straywild"
readonly WINDOWS_ZIP="${BUILD_ROOT}/straywild-v0.19.0-alpha-windows-x86_64.zip"
readonly LINUX_ZIP="${BUILD_ROOT}/straywild-v0.19.0-alpha-linux-x86_64.zip"
readonly SOURCE_URL="https://forge.makearmy.io/woofmeow/netfishing"
readonly WINDOWS_ZIP="${BUILD_ROOT}/NETfishing-v0.18.1-alpha-windows-x86_64.zip"
readonly LINUX_ZIP="${BUILD_ROOT}/NETfishing-v0.18.1-alpha-linux-x86_64.zip"
readonly GODOT_BIN="${GODOT_BIN:-godot}"
if [[ ! -f "${PROJECT_ROOT}/project.godot" ]]; then
@ -31,26 +31,26 @@ mkdir -p -- "${WINDOWS_DIR}" "${LINUX_DIR}"
--headless \
--path "${PROJECT_ROOT}" \
--export-release "Windows Desktop" \
"${WINDOWS_DIR}/straywild.exe"
"${WINDOWS_DIR}/NETfishing.exe"
"${GODOT_BIN}" \
--headless \
--path "${PROJECT_ROOT}" \
--export-release "Linux Desktop" \
"${LINUX_DIR}/straywild.x86_64"
"${LINUX_DIR}/NETfishing.x86_64"
for required_file in \
"${WINDOWS_DIR}/straywild.exe" \
"${WINDOWS_DIR}/straywild.pck" \
"${LINUX_DIR}/straywild.x86_64" \
"${LINUX_DIR}/straywild.pck"; do
"${WINDOWS_DIR}/NETfishing.exe" \
"${WINDOWS_DIR}/NETfishing.pck" \
"${LINUX_DIR}/NETfishing.x86_64" \
"${LINUX_DIR}/NETfishing.pck"; do
if [[ ! -s "${required_file}" ]]; then
echo "error: expected export output is missing: ${required_file}" >&2
exit 1
fi
done
chmod +x -- "${LINUX_DIR}/straywild.x86_64"
chmod +x -- "${LINUX_DIR}/NETfishing.x86_64"
cp -- "${README_SOURCE}" "${WINDOWS_DIR}/README-PLAYTEST.txt"
cp -- "${README_SOURCE}" "${LINUX_DIR}/README-PLAYTEST.txt"
@ -60,7 +60,7 @@ stage_licenses() {
install -m 0644 "${PROJECT_ROOT}/LICENSE" \
"${destination}/GPL-3.0-or-later.txt"
install -m 0644 "${PROJECT_ROOT}/ASSET-LICENSE.md" \
"${destination}/straywild-ASSET-LICENSE.md"
"${destination}/NETFISHING-ASSET-LICENSE.md"
install -m 0644 "${PROJECT_ROOT}/docs/ATTRIBUTION.md" \
"${destination}/ATTRIBUTION.md"
install -m 0644 "${PROJECT_ROOT}/TRADEMARKS.md" \
@ -72,7 +72,7 @@ stage_licenses() {
cat >"${destination}/SOURCE-CODE.md" <<EOF
# Corresponding source
straywild code is licensed under GPL-3.0-or-later.
NETfishing code is licensed under GPL-3.0-or-later.
Source repository: ${SOURCE_URL}
Source revision at build time: ${SOURCE_COMMIT}

View file

@ -42,13 +42,13 @@ fi
readonly RELEASE_TAG="v${PROJECT_VERSION}"
readonly RELEASE_ROOT="${PROJECT_ROOT}/builds/${RELEASE_TAG}"
readonly ARM64_ROOT="${RELEASE_ROOT}/linux-arm64"
readonly ARM64_EXECUTABLE="${ARM64_ROOT}/straywild.arm64"
readonly ARM64_PCK="${ARM64_ROOT}/straywild.pck"
readonly ARM64_EXECUTABLE="${ARM64_ROOT}/NETfishing.arm64"
readonly ARM64_PCK="${ARM64_ROOT}/NETfishing.pck"
readonly STAGE_ROOT="${RELEASE_ROOT}/portmaster-stage"
readonly GAME_ROOT="${STAGE_ROOT}/straywild"
readonly ARCHIVE="${RELEASE_ROOT}/straywild.zip"
readonly OBSOLETE_VERSIONED_ARCHIVE="${RELEASE_ROOT}/straywild-${RELEASE_TAG}-portmaster-arm64.zip"
readonly OBSOLETE_LOWERCASE_ARCHIVE="${RELEASE_ROOT}/straywild-${RELEASE_TAG}-portmaster-arm64.zip"
readonly GAME_ROOT="${STAGE_ROOT}/netfishing"
readonly ARCHIVE="${RELEASE_ROOT}/netfishing.zip"
readonly OBSOLETE_VERSIONED_ARCHIVE="${RELEASE_ROOT}/NETfishing-${RELEASE_TAG}-portmaster-arm64.zip"
readonly OBSOLETE_LOWERCASE_ARCHIVE="${RELEASE_ROOT}/netfishing-${RELEASE_TAG}-portmaster-arm64.zip"
readonly HEAD_COMMIT="$(git -C "${PROJECT_ROOT}" rev-parse HEAD)"
readonly TAG_COMMIT="$(git -C "${PROJECT_ROOT}" rev-parse "${RELEASE_TAG}^{commit}")"
@ -74,7 +74,7 @@ elif [[ "${HEAD_COMMIT}" != "${TAG_COMMIT}" ]]; then
echo "HEAD does not match ${RELEASE_TAG}. Refusing to package mutable source." >&2
exit 1
fi
if [[ "${straywild_ALLOW_DIRTY_RELEASE:-0}" != "1" ]]; then
if [[ "${NETFISHING_ALLOW_DIRTY_RELEASE:-0}" != "1" ]]; then
dirty_tree=0
git -C "${PROJECT_ROOT}" diff --quiet || dirty_tree=1
git -C "${PROJECT_ROOT}" diff --cached --quiet || dirty_tree=1
@ -97,7 +97,7 @@ done
mkdir -p -- "${ARM64_ROOT}" "${RELEASE_ROOT}"
if [[ ${PACKAGE_ONLY} -eq 0 ]]; then
readonly EXPORT_PROJECT_ROOT="$(
mktemp -d -t straywild-portmaster-export.XXXXXX
mktemp -d -t netfishing-portmaster-export.XXXXXX
)"
cleanup_export_project() {
rm -rf -- "${EXPORT_PROJECT_ROOT}"
@ -108,9 +108,9 @@ if [[ ${PACKAGE_ONLY} -eq 0 ]]; then
--exclude '/.git/' \
--exclude '/.godot/' \
--exclude '/art/source/' \
--exclude '/art/exported/system_icons/straywild.ico' \
--exclude '/art/exported/system_icons/straywild_1024.png' \
--exclude '/art/exported/system_icons/straywild_1024.png.import' \
--exclude '/art/exported/system_icons/netfishing.ico' \
--exclude '/art/exported/system_icons/netfishing_1024.png' \
--exclude '/art/exported/system_icons/netfishing_1024.png.import' \
--exclude '/audio/ambience/' \
--exclude '/builds/' \
--exclude '/docs/design/' \
@ -141,14 +141,14 @@ rm -f -- \
"${OBSOLETE_LOWERCASE_ARCHIVE}"
mkdir -p -- "${GAME_ROOT}/licenses"
install -m 0755 "${TEMPLATE_ROOT}/straywild.sh" "${STAGE_ROOT}/straywild.sh"
install -m 0755 "${TEMPLATE_ROOT}/NETfishing.sh" "${STAGE_ROOT}/NETfishing.sh"
install -m 0644 "${TEMPLATE_ROOT}/port.json" "${GAME_ROOT}/port.json"
install -m 0644 "${TEMPLATE_ROOT}/straywild.gptk" \
"${GAME_ROOT}/straywild.gptk"
install -m 0755 "${TEMPLATE_ROOT}/launch-straywild.sh" \
"${GAME_ROOT}/launch-straywild.sh"
install -m 0755 "${ARM64_EXECUTABLE}" "${GAME_ROOT}/straywild.aarch64"
install -m 0644 "${ARM64_PCK}" "${GAME_ROOT}/straywild.pck"
install -m 0644 "${TEMPLATE_ROOT}/netfishing.gptk" \
"${GAME_ROOT}/netfishing.gptk"
install -m 0755 "${TEMPLATE_ROOT}/launch-netfishing.sh" \
"${GAME_ROOT}/launch-netfishing.sh"
install -m 0755 "${ARM64_EXECUTABLE}" "${GAME_ROOT}/NETfishing.aarch64"
install -m 0644 "${ARM64_PCK}" "${GAME_ROOT}/NETfishing.pck"
install -m 0644 "${TEMPLATE_ROOT}/gameinfo.xml" "${GAME_ROOT}/gameinfo.xml"
install -m 0644 "${TEMPLATE_ROOT}/screenshot.png" "${GAME_ROOT}/screenshot.png"
install -m 0644 \
@ -159,7 +159,7 @@ install -m 0644 \
"${GAME_ROOT}/licenses/GPL-3.0-or-later.txt"
install -m 0644 \
"${PROJECT_ROOT}/ASSET-LICENSE.md" \
"${GAME_ROOT}/licenses/straywild-ASSET-LICENSE.md"
"${GAME_ROOT}/licenses/NETFISHING-ASSET-LICENSE.md"
install -m 0644 \
"${PROJECT_ROOT}/TRADEMARKS.md" \
"${GAME_ROOT}/licenses/TRADEMARKS.md"
@ -171,7 +171,7 @@ install -m 0644 \
"${GAME_ROOT}/licenses/Seattle-Avenue-LICENSE.txt"
cat >"${GAME_ROOT}/BUILD-INFO.txt" <<EOF
straywild PortMaster ARM64 build
NETfishing PortMaster ARM64 build
Project version: ${PROJECT_VERSION}
Game source commit: ${TAG_COMMIT}
@ -191,109 +191,105 @@ EOF
cat >"${GAME_ROOT}/licenses/SOURCE-CODE.md" <<EOF
# Corresponding source
straywild code is licensed under GPL-3.0-or-later.
NETfishing code is licensed under GPL-3.0-or-later.
Source repository: https://forge.makearmy.io/woofmeow/straywild
Source repository: https://forge.makearmy.io/woofmeow/netfishing
Exact source revision: ${TAG_COMMIT}
Release tag: ${RELEASE_TAG}
PortMaster packaging revision: ${HEAD_COMMIT}
EOF
cat >"${GAME_ROOT}/README.md" <<EOF
# straywild for PortMaster
# NETfishing for PortMaster
This package contains straywild \`${RELEASE_TAG}\`, exported from Godot 4.7.1
This package contains NETfishing \`${RELEASE_TAG}\`, exported from Godot 4.7.1
for 64-bit ARM Linux and wrapped for PortMaster.
## Installation
Install the complete \`straywild.zip\` archive with PortMaster or HarbourMaster.
Install the complete \`netfishing.zip\` archive with PortMaster or HarbourMaster.
The package requires an ARM64 device, two analog sticks, GLIBC 2.28 or newer,
and the \`weston_pkg_0.2\` runtime.
New installations store player data under \`ports/saves/straywild/\` without
New installations store player data under \`ports/saves/netfishing/\` without
opening a folder picker. Existing installations preserve their previously
selected data root. Device-local configuration remains under
\`straywild/conf/\`.
\`netfishing/conf/\`.
PortMaster launches use the light performance profile by default. Put the word
\`normal\` in \`straywild/conf/performance_profile\` to opt a capable device
\`normal\` in \`netfishing/conf/performance_profile\` to opt a capable device
into the normal rendering profile. PortMaster packages retain title and world
music while omitting rain and shoreline ambience in both profiles. See
\`straywild/licenses/\` for bundled credits and license information.
\`netfishing/licenses/\` for bundled credits and license information.
## Controls
straywild reads the handheld controller directly. GPTOKEYB's device-specific
NETfishing reads the handheld controller directly. GPTOKEYB's device-specific
force-quit chord remains available; this is Start+Select on most devices.
EOF
(
cd "${STAGE_ROOT}"
zip -qry "${ARCHIVE}" straywild.sh straywild
zip -qry "${ARCHIVE}" NETfishing.sh netfishing
)
unzip -tq "${ARCHIVE}" >/dev/null
readonly TOP_LEVELS="$(
unzip -Z1 "${ARCHIVE}" | cut -d/ -f1 | sort -u
)"
readonly EXPECTED_TOP_LEVELS="$(printf '%s\n' straywild.sh straywild)"
readonly EXPECTED_TOP_LEVELS="$(printf '%s\n' NETfishing.sh netfishing)"
if [[ "${TOP_LEVELS}" != "${EXPECTED_TOP_LEVELS}" ]]; then
echo "Unexpected PortMaster archive roots:" >&2
printf '%s\n' "${TOP_LEVELS}" >&2
exit 1
fi
grep -q '"version": 4' "${GAME_ROOT}/port.json"
grep -q '"name": "straywild.zip"' "${GAME_ROOT}/port.json"
grep -q '"name": "netfishing.zip"' "${GAME_ROOT}/port.json"
grep -q '"rtr": true' "${GAME_ROOT}/port.json"
if unzip -Z1 "${ARCHIVE}" | grep -qx 'port.json'; then
echo "port.json must be inside straywild/, not at the archive root." >&2
echo "port.json must be inside netfishing/, not at the archive root." >&2
exit 1
fi
if grep -Eq '^[[:space:]]*#[[:space:]]*PORTMASTER:' \
"${STAGE_ROOT}/straywild.sh"; then
"${STAGE_ROOT}/NETfishing.sh"; then
echo "The distributable launcher contains an installed PortMaster signature." >&2
exit 1
fi
grep -Fq 'PROFILE_PATH="$CONFDIR/performance_profile"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'straywild_PERFORMANCE_PROFILE=light' \
"${STAGE_ROOT}/straywild.sh"
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'NETFISHING_PERFORMANCE_PROFILE=light' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'CONTROLLER_MAPPING_FILE="$CONFDIR/cache/controller_mapping.txt"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'SAVEDIR="$PORTS_ROOT/saves/straywild"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'LEGACY_SAVEDIR="$PORTS_ROOT/saves/netfishing"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'cp -a "$LEGACY_CONFDIR/." "$CONFDIR/"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq '"straywild_DATA_DIR=$SAVEDIR"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq '"straywild_CREATE_DATA_DIR=1"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'printf '\''%s\n'\'' "$straywild_controllerconfig" > "$CONTROLLER_MAPPING_FILE"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq '"$GAME_LAUNCHER"' "${STAGE_ROOT}/straywild.sh"
grep -Fq '"$CONTROLLER_MAPPING_FILE"' "${STAGE_ROOT}/straywild.sh"
if grep -Fq 'SDL_GAMECONTROLLERCONFIG="$straywild_controllerconfig"' \
"${STAGE_ROOT}/straywild.sh"; then
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'SAVEDIR="$PORTS_ROOT/saves/netfishing"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"NETFISHING_DATA_DIR=$SAVEDIR"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"NETFISHING_CREATE_DATA_DIR=1"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'printf '\''%s\n'\'' "$netfishing_controllerconfig" > "$CONTROLLER_MAPPING_FILE"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"$GAME_LAUNCHER"' "${STAGE_ROOT}/NETfishing.sh"
grep -Fq '"$CONTROLLER_MAPPING_FILE"' "${STAGE_ROOT}/NETfishing.sh"
if grep -Fq 'SDL_GAMECONTROLLERCONFIG="$netfishing_controllerconfig"' \
"${STAGE_ROOT}/NETfishing.sh"; then
echo "Raw controller mappings must not be passed through westonwrap.sh." >&2
exit 1
fi
grep -Fq 'SDL_GAMECONTROLLERCONFIG="$(<"$CONTROLLER_MAPPING_FILE")"' \
"${GAME_ROOT}/launch-straywild.sh"
"${GAME_ROOT}/launch-netfishing.sh"
grep -Fq 'export SDL_GAMECONTROLLERCONFIG' \
"${GAME_ROOT}/launch-straywild.sh"
grep -Fq 'exec "$@"' "${GAME_ROOT}/launch-straywild.sh"
grep -Fq 'GPTOKEYB_CONFIG="$GAMEDIR/straywild.gptk"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq '$GPTOKEYB "straywild.aarch64" -c "$GPTOKEYB_CONFIG" &' \
"${STAGE_ROOT}/straywild.sh"
"${GAME_ROOT}/launch-netfishing.sh"
grep -Fq 'exec "$@"' "${GAME_ROOT}/launch-netfishing.sh"
grep -Fq 'GPTOKEYB_CONFIG="$GAMEDIR/netfishing.gptk"' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq '$GPTOKEYB "NETfishing.aarch64" -c "$GPTOKEYB_CONFIG" &' \
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'pm_platform_helper "$GAME_EXECUTABLE"' \
"${STAGE_ROOT}/straywild.sh"
grep -Fq 'pm_finish' "${STAGE_ROOT}/straywild.sh"
"${STAGE_ROOT}/NETfishing.sh"
grep -Fq 'pm_finish' "${STAGE_ROOT}/NETfishing.sh"
if [[ "$(grep -Ec '^[[:space:]]*\$GPTOKEYB[[:space:]]' \
"${STAGE_ROOT}/straywild.sh")" -ne 1 ]]; then
echo "straywild must start exactly one GPTOKEYB exit handler." >&2
"${STAGE_ROOT}/NETfishing.sh")" -ne 1 ]]; then
echo "NETfishing must start exactly one GPTOKEYB exit handler." >&2
exit 1
fi
readonly GPTOKEYB_NOOP_KEYS=(
@ -307,13 +303,13 @@ readonly GPTOKEYB_NOOP_KEYS=(
for noop_key in "${GPTOKEYB_NOOP_KEYS[@]}"; do
if ! grep -Eq \
"^[[:space:]]*${noop_key}[[:space:]]*=[[:space:]]*\\\\\"[[:space:]]*$" \
"${GAME_ROOT}/straywild.gptk"; then
"${GAME_ROOT}/netfishing.gptk"; then
echo "GPTOKEYB no-op mapping is missing: ${noop_key}" >&2
exit 1
fi
done
if [[ "$(grep -Ec '^[[:space:]]*[a-z0-9_]+[[:space:]]*=' \
"${GAME_ROOT}/straywild.gptk")" -ne "${#GPTOKEYB_NOOP_KEYS[@]}" ]]; then
"${GAME_ROOT}/netfishing.gptk")" -ne "${#GPTOKEYB_NOOP_KEYS[@]}" ]]; then
echo "GPTOKEYB no-op mapping contains an unexpected assignment." >&2
exit 1
fi

View file

@ -35,10 +35,10 @@ if [[ ! "$SAMPLE_SET_DIRECTORY" =~ ^[a-z0-9_-]+$ ]]; then
fi
readonly DESTINATION_DIRECTORY="$PROJECT_ROOT/sound/dialogue/animalese/$SAMPLE_SET_DIRECTORY"
readonly WORK_DIRECTORY="$(mktemp -d -t straywild-animalese-import.XXXXXX)"
readonly WORK_DIRECTORY="$(mktemp -d -t netfishing-animalese-import.XXXXXX)"
cleanup() {
if [[ "$WORK_DIRECTORY" == /tmp/straywild-animalese-import.* ]]; then
if [[ "$WORK_DIRECTORY" == /tmp/netfishing-animalese-import.* ]]; then
find "$WORK_DIRECTORY" -depth -delete
fi
}

View file

@ -13,7 +13,7 @@ fi
readonly ROOT_PATH="$1"
readonly WORK_ROOT="$(mktemp -d -t straywild-godot-data.XXXXXX)"
readonly WORK_ROOT="$(mktemp -d -t netfishing-godot-data.XXXXXX)"
trap 'rm -rf -- "${WORK_ROOT}"' EXIT
cd "${PROJECT_ROOT}"

View file

@ -16,56 +16,35 @@ source "$controlfolder/control.txt"
[ -f "${controlfolder}/mod_${CFW_NAME}.txt" ] && source "${controlfolder}/mod_${CFW_NAME}.txt"
get_controls
GAMEDIR="/${directory}/ports/straywild"
GAMEDIR="/${directory}/ports/netfishing"
CONFDIR="$GAMEDIR/conf"
PORTS_ROOT="${GAMEDIR%/straywild}"
SAVEDIR="$PORTS_ROOT/saves/straywild"
LEGACY_GAMEDIR="$PORTS_ROOT/netfishing"
LEGACY_CONFDIR="$LEGACY_GAMEDIR/conf"
LEGACY_SAVEDIR="$PORTS_ROOT/saves/netfishing"
DATA_BOOTSTRAP_DIR="$CONFDIR/data/godot/app_userdata/straywild"
LEGACY_DATA_BOOTSTRAP_DIR="$CONFDIR/data/godot/app_userdata/NETFISHING"
GAME_EXECUTABLE="$GAMEDIR/straywild.aarch64"
GAME_LAUNCHER="$GAMEDIR/launch-straywild.sh"
GPTOKEYB_CONFIG="$GAMEDIR/straywild.gptk"
PORTS_ROOT="${GAMEDIR%/netfishing}"
SAVEDIR="$PORTS_ROOT/saves/netfishing"
DATA_BOOTSTRAP_DIR="$CONFDIR/data/godot/app_userdata/NETFISHING"
GAME_EXECUTABLE="$GAMEDIR/NETfishing.aarch64"
GAME_LAUNCHER="$GAMEDIR/launch-netfishing.sh"
GPTOKEYB_CONFIG="$GAMEDIR/netfishing.gptk"
CONTROLLER_MAPPING_FILE="$CONFDIR/cache/controller_mapping.txt"
WESTON_DIR="/tmp/straywild-weston"
WESTON_DIR="/tmp/netfishing-weston"
WESTON_RUNTIME="weston_pkg_0.2"
HARBOURMASTER="$controlfolder/harbourmaster"
mkdir -p "$CONFDIR/data" "$CONFDIR/config" "$CONFDIR/cache" "$WESTON_DIR"
chmod +x "$GAME_EXECUTABLE"
# A renamed PortMaster entry installs beside the former NETfishing port. Copy
# its device-local configuration once and continue using its established save
# root when present. New installations use straywild paths exclusively.
if [ -d "$LEGACY_CONFDIR" ] && [ ! -f "$CONFDIR/.netfishing-imported" ]; then
cp -a "$LEGACY_CONFDIR/." "$CONFDIR/"
touch "$CONFDIR/.netfishing-imported"
fi
if [ ! -f "$SAVEDIR/straywild_data.json" ] \
&& [ ! -f "$SAVEDIR/netfishing_data.json" ] \
&& { [ -f "$LEGACY_SAVEDIR/straywild_data.json" ] \
|| [ -f "$LEGACY_SAVEDIR/netfishing_data.json" ]; }; then
SAVEDIR="$LEGACY_SAVEDIR"
fi
# straywild uses a predictable save directory beside the port instead of
# NETfishing uses a predictable save directory beside the port instead of
# presenting a folder picker on a small screen. Preserve an established
# data-root choice when upgrading an existing installation.
straywild_DATA_ENVIRONMENT=()
if [ -f "$SAVEDIR/straywild_data.json" ] \
|| [ -f "$SAVEDIR/netfishing_data.json" ] || {
NETFISHING_DATA_ENVIRONMENT=()
if [ -f "$SAVEDIR/netfishing_data.json" ] || {
[ ! -f "$DATA_BOOTSTRAP_DIR/data_root_bootstrap.json" ] &&
[ ! -f "$DATA_BOOTSTRAP_DIR/data_root_bootstrap.json.backup" ] &&
[ ! -f "$LEGACY_DATA_BOOTSTRAP_DIR/data_root_bootstrap.json" ] &&
[ ! -f "$LEGACY_DATA_BOOTSTRAP_DIR/data_root_bootstrap.json.backup" ]
[ ! -f "$DATA_BOOTSTRAP_DIR/data_root_bootstrap.json.backup" ]
}; then
mkdir -p "$SAVEDIR"
straywild_DATA_ENVIRONMENT+=(
"straywild_DATA_DIR=$SAVEDIR"
"straywild_CREATE_DATA_DIR=1"
NETFISHING_DATA_ENVIRONMENT+=(
"NETFISHING_DATA_DIR=$SAVEDIR"
"NETFISHING_CREATE_DATA_DIR=1"
)
fi
@ -73,7 +52,7 @@ fi
if [ ! -f "$controlfolder/libs/${WESTON_RUNTIME}.squashfs" ]; then
if [ ! -x "$HARBOURMASTER" ]; then
pm_message "straywild requires the latest PortMaster and WestonPack runtime."
pm_message "NETfishing requires the latest PortMaster and WestonPack runtime."
sleep 5
exit 1
fi
@ -99,17 +78,17 @@ cd "$GAMEDIR" || exit 1
GODOT_MUOS_MAPPING="19004ca6010000000100000000010000,muOS-Keys,a:b0,b:b1,x:b3,y:b2,leftshoulder:b4,rightshoulder:b5,lefttrigger:b10,righttrigger:b11,guide:b8,start:b7,back:b6,dpup:h0.1,dpleft:h0.8,dpright:h0.2,dpdown:h0.4,leftx:a0,lefty:a1,leftstick:b9,rightx:a2,righty:a3,rightstick:b12,platform:Linux,"
MUOS_SDL2_GUID="19000000010000000100000000010000"
if [[ "$sdl_controllerconfig" == "${MUOS_SDL2_GUID},"* ]]; then
straywild_controllerconfig="$GODOT_MUOS_MAPPING"
netfishing_controllerconfig="$GODOT_MUOS_MAPPING"
elif [ -n "$sdl_controllerconfig" ]; then
straywild_controllerconfig="$sdl_controllerconfig"
netfishing_controllerconfig="$sdl_controllerconfig"
else
straywild_controllerconfig="$GODOT_MUOS_MAPPING"
netfishing_controllerconfig="$GODOT_MUOS_MAPPING"
fi
printf '%s\n' "$straywild_controllerconfig" > "$CONTROLLER_MAPPING_FILE"
printf '%s\n' "$netfishing_controllerconfig" > "$CONTROLLER_MAPPING_FILE"
straywild_GODOT_OPTIONS=()
straywild_GAME_ENVIRONMENT=()
PERFORMANCE_PROFILE="${straywild_PERFORMANCE_PROFILE:-}"
NETFISHING_GODOT_OPTIONS=()
NETFISHING_GAME_ENVIRONMENT=()
PERFORMANCE_PROFILE="${NETFISHING_PERFORMANCE_PROFILE:-}"
PROFILE_PATH="$CONFDIR/performance_profile"
if [[ -z "$PERFORMANCE_PROFILE" && -r "$PROFILE_PATH" ]]; then
IFS= read -r PERFORMANCE_PROFILE < "$PROFILE_PATH" || true
@ -117,16 +96,16 @@ if [[ -z "$PERFORMANCE_PROFILE" && -r "$PROFILE_PATH" ]]; then
fi
case "$PERFORMANCE_PROFILE" in
normal)
straywild_GAME_ENVIRONMENT+=(
"straywild_PERFORMANCE_PROFILE=normal"
NETFISHING_GAME_ENVIRONMENT+=(
"NETFISHING_PERFORMANCE_PROFILE=normal"
)
;;
light|"")
straywild_GAME_ENVIRONMENT+=(
"straywild_PERFORMANCE_PROFILE=light"
"straywild_LOW_END=1"
NETFISHING_GAME_ENVIRONMENT+=(
"NETFISHING_PERFORMANCE_PROFILE=light"
"NETFISHING_LOW_END=1"
)
straywild_GODOT_OPTIONS+=(
NETFISHING_GODOT_OPTIONS+=(
--single-window
--disable-vsync
--max-fps 30
@ -135,11 +114,11 @@ case "$PERFORMANCE_PROFILE" in
;;
*)
echo "Unknown performance profile '$PERFORMANCE_PROFILE'; using light." >&2
straywild_GAME_ENVIRONMENT+=(
"straywild_PERFORMANCE_PROFILE=light"
"straywild_LOW_END=1"
NETFISHING_GAME_ENVIRONMENT+=(
"NETFISHING_PERFORMANCE_PROFILE=light"
"NETFISHING_LOW_END=1"
)
straywild_GODOT_OPTIONS+=(
NETFISHING_GODOT_OPTIONS+=(
--single-window
--disable-vsync
--max-fps 30
@ -148,10 +127,10 @@ case "$PERFORMANCE_PROFILE" in
;;
esac
# straywild reads gameplay input natively. The explicit no-op map prevents
# NETfishing reads gameplay input natively. The explicit no-op map prevents
# GPTOKEYB from injecting duplicate keyboard or mouse input while retaining
# its device-specific force-quit chord, including on ROCKNIX.
$GPTOKEYB "straywild.aarch64" -c "$GPTOKEYB_CONFIG" &
$GPTOKEYB "NETfishing.aarch64" -c "$GPTOKEYB_CONFIG" &
pm_platform_helper "$GAME_EXECUTABLE"
$ESUDO env CRUSTY_RESOLUTION="${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" \
@ -160,12 +139,12 @@ $ESUDO env CRUSTY_RESOLUTION="${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" \
XDG_CONFIG_HOME="$CONFDIR/config" \
XDG_CACHE_HOME="$CONFDIR/cache" \
GODOT_SILENCE_ROOT_WARNING=1 \
"${straywild_DATA_ENVIRONMENT[@]}" \
"${straywild_GAME_ENVIRONMENT[@]}" \
"${NETFISHING_DATA_ENVIRONMENT[@]}" \
"${NETFISHING_GAME_ENVIRONMENT[@]}" \
"$GAME_LAUNCHER" \
"$CONTROLLER_MAPPING_FILE" \
"$GAME_EXECUTABLE" \
"${straywild_GODOT_OPTIONS[@]}" \
"${NETFISHING_GODOT_OPTIONS[@]}" \
--resolution "${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" \
--fullscreen \
--rendering-driver opengl3_es \

View file

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<gameList>
<game>
<path>./straywild.sh</path>
<name>straywild</name>
<path>./NETfishing.sh</path>
<name>NETfishing</name>
<desc>A relaxed multiplayer fishing game about exploring a small island, catching and collecting fish, customizing your character, and spending time by the water.</desc>
<releasedate>20260804T000000</releasedate>
<developer>straywild project</developer>
<developer>NETfishing project</developer>
<publisher>Independent</publisher>
<genre>adventure, simulation</genre>
<image>./straywild/screenshot.png</image>
<image>./netfishing/screenshot.png</image>
</game>
</gameList>

View file

@ -1,4 +1,4 @@
# straywild reads the controller directly. GPTOKEYB is retained only for its
# NETfishing reads the controller directly. GPTOKEYB is retained only for its
# device-specific force-quit chord, so every keyboard and mouse binding is
# disabled to prevent duplicate input.

View file

@ -1,13 +1,13 @@
{
"version": 4,
"name": "straywild.zip",
"name": "netfishing.zip",
"items": [
"straywild.sh",
"straywild/"
"NETfishing.sh",
"netfishing/"
],
"items_opt": null,
"attr": {
"title": "straywild",
"title": "NETfishing",
"porter": [
"Voyager"
],

View file

@ -6,9 +6,9 @@ readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
readonly GODOT_BIN="${GODOT_BIN:-godot}"
readonly TEST_TIMEOUT_SECONDS="${TEST_TIMEOUT_SECONDS:-120}"
readonly RUN_ROOT="$(mktemp -d -t straywild-validations.XXXXXX)"
readonly RUN_ROOT="$(mktemp -d -t netfishing-validations.XXXXXX)"
export straywild_ISOLATED_VALIDATION_STORAGE=1
export NETFISHING_ISOLATED_VALIDATION_STORAGE=1
readonly -a QUICK_TESTS=(
"scripts/validate_animalese_samples.gd"

View file

@ -336,8 +336,8 @@ check_editor_settings() {
run_export_hint() {
echo
echo "Example export commands:"
echo " ${GODOT} --headless --path \"$PROJECT_ROOT\" --export-release \"Android\" builds/${PROJECT_VERSION}/android/straywild.apk"
echo " ${GODOT} --headless --path \"$PROJECT_ROOT\" --export-debug \"Android\" builds/android/straywild-debug.apk"
echo " ${GODOT} --headless --path \"$PROJECT_ROOT\" --export-release \"Android\" builds/${PROJECT_VERSION}/android/NETfishing.apk"
echo " ${GODOT} --headless --path \"$PROJECT_ROOT\" --export-debug \"Android\" builds/android/NETfishing-debug.apk"
}
print_status INFO "Starting Android dependency preflight..."

View file

@ -1,36 +1,36 @@
extends SceneTree
const PROJECT_PATH := "/tmp/straywild"
const INSTALL_PATH := "/opt/straywild"
const PROJECT_PATH := "/tmp/netfishing"
const INSTALL_PATH := "/opt/NETfishing"
func _initialize() -> void:
var root_to_create: String = OS.get_environment("straywild_TEST_CREATE_ROOT")
var root_to_create: String = OS.get_environment("NETFISHING_TEST_CREATE_ROOT")
if not root_to_create.is_empty():
_create_validation_root(root_to_create)
return
var failures: PackedStringArray = []
_expect(
"external temporary directory",
"/tmp/straywild-test-data",
"/tmp/NETfishing-test-data",
PlayerDataRoot.PATH_ALLOWED,
failures,
)
_expect(
"external trailing slash",
"/tmp/straywild-test-data/",
"/tmp/NETfishing-test-data/",
PlayerDataRoot.PATH_ALLOWED,
failures,
)
_expect(
"similar project-name sibling",
"/tmp/straywild-data",
"/tmp/netfishing-data",
PlayerDataRoot.PATH_ALLOWED,
failures,
)
_expect(
"documents directory",
"/home/player/Documents/straywild",
"/home/player/Documents/NETfishing",
PlayerDataRoot.PATH_ALLOWED,
failures,
)
@ -55,7 +55,7 @@ func _initialize() -> void:
)
_expect_with_references(
"empty project reference",
"/tmp/straywild-test-data",
"/tmp/NETfishing-test-data",
"",
INSTALL_PATH,
PlayerDataRoot.PATH_ALLOWED,
@ -63,7 +63,7 @@ func _initialize() -> void:
)
_expect_with_references(
"root project reference",
"/tmp/straywild-test-data",
"/tmp/NETfishing-test-data",
"/",
INSTALL_PATH,
PlayerDataRoot.PATH_ALLOWED,
@ -71,9 +71,9 @@ func _initialize() -> void:
)
_expect_with_references(
"Windows component and case normalization",
"C:\\Games\\straywild Data",
"C:\\Games\\straywild",
"C:\\Program Files\\straywild",
"C:\\Games\\NETfishing Data",
"C:\\Games\\NETfishing",
"C:\\Program Files\\NETfishing",
PlayerDataRoot.PATH_ALLOWED,
failures,
true,

View file

@ -1,7 +1,7 @@
class_name DedicatedServerConfig
extends RefCounted
const DEFAULT_NAME: String = "straywild Dedicated Server"
const DEFAULT_NAME: String = "NETfishing Dedicated Server"
const DEFAULT_BIND_ADDRESS: String = "*"
const DEFAULT_PORT: int = 7777
const DEFAULT_MAX_PLAYERS: int = 8
@ -31,10 +31,8 @@ static func from_runtime() -> DedicatedServerConfig:
result.discovery_url = str(ProjectSettings.get_setting(
"network/discovery/base_url", ""
)).strip_edges()
var config_path: String = _environment_string(
"straywild_SERVER_CONFIG",
"NETFISHING_SERVER_CONFIG",
"",
var config_path: String = OS.get_environment(
"NETFISHING_SERVER_CONFIG"
).strip_edges()
for argument: String in OS.get_cmdline_user_args():
if argument.begins_with("--config="):
@ -89,44 +87,36 @@ func _load_file(path: String) -> bool:
func _apply_environment() -> void:
server_name = _environment_string(
"straywild_SERVER_NAME", "NETFISHING_SERVER_NAME", server_name
"NETFISHING_SERVER_NAME", server_name
)
bind_address = _environment_string(
"straywild_SERVER_BIND", "NETFISHING_SERVER_BIND", bind_address
)
port = _environment_int(
"straywild_SERVER_PORT", "NETFISHING_SERVER_PORT", port
"NETFISHING_SERVER_BIND", bind_address
)
port = _environment_int("NETFISHING_SERVER_PORT", port)
max_players = _environment_int(
"straywild_SERVER_MAX_PLAYERS",
"NETFISHING_SERVER_MAX_PLAYERS",
max_players,
"NETFISHING_SERVER_MAX_PLAYERS", max_players
)
world_seed = _environment_int(
"straywild_WORLD_SEED", "NETFISHING_WORLD_SEED", world_seed
"NETFISHING_WORLD_SEED", world_seed
)
public_listing = _environment_bool(
"straywild_SERVER_PUBLIC", "NETFISHING_SERVER_PUBLIC", public_listing
"NETFISHING_SERVER_PUBLIC", public_listing
)
discovery_url = _environment_string(
"straywild_DISCOVERY_URL", "NETFISHING_DISCOVERY_URL", discovery_url
"NETFISHING_DISCOVERY_URL", discovery_url
)
data_directory = _environment_string(
"straywild_DATA_DIR", "NETFISHING_DATA_DIR", data_directory
"NETFISHING_DATA_DIR", data_directory
)
chat_logging = _environment_bool(
"straywild_CHAT_LOGGING", "NETFISHING_CHAT_LOGGING", chat_logging
"NETFISHING_CHAT_LOGGING", chat_logging
)
chat_log_path = _environment_string(
"straywild_CHAT_LOG_PATH", "NETFISHING_CHAT_LOG_PATH", chat_log_path
"NETFISHING_CHAT_LOG_PATH", chat_log_path
)
var operators_variable: String = _available_environment_variable(
"straywild_SERVER_OPERATORS",
"NETFISHING_SERVER_OPERATORS",
)
if not operators_variable.is_empty():
if OS.has_environment("NETFISHING_SERVER_OPERATORS"):
operator_fingerprints = _parse_fingerprint_list(
OS.get_environment(operators_variable)
OS.get_environment("NETFISHING_SERVER_OPERATORS")
)
@ -221,45 +211,21 @@ static func _safe_text(value: String) -> bool:
return true
static func _available_environment_variable(
name: String,
legacy_name: String,
) -> String:
if OS.has_environment(name):
return name
return legacy_name if OS.has_environment(legacy_name) else ""
static func _environment_string(name: String, fallback: String) -> String:
return OS.get_environment(name) if OS.has_environment(name) else fallback
static func _environment_string(
name: String,
legacy_name: String,
fallback: String,
) -> String:
var variable: String = _available_environment_variable(name, legacy_name)
return OS.get_environment(variable) if not variable.is_empty() else fallback
static func _environment_int(
name: String,
legacy_name: String,
fallback: int,
) -> int:
var variable: String = _available_environment_variable(name, legacy_name)
static func _environment_int(name: String, fallback: int) -> int:
return (
_parse_int(OS.get_environment(variable), fallback)
if not variable.is_empty() else fallback
_parse_int(OS.get_environment(name), fallback)
if OS.has_environment(name) else fallback
)
static func _environment_bool(
name: String,
legacy_name: String,
fallback: bool,
) -> bool:
var variable: String = _available_environment_variable(name, legacy_name)
if variable.is_empty():
static func _environment_bool(name: String, fallback: bool) -> bool:
if not OS.has_environment(name):
return fallback
var value: String = OS.get_environment(variable).strip_edges().to_lower()
var value: String = OS.get_environment(name).strip_edges().to_lower()
return value in ["1", "true", "yes", "on"]

View file

@ -7,7 +7,7 @@ const TEMP_PATH: String = "user://player_settings.json.tmp"
const BACKUP_PATH: String = "user://player_settings.json.backup"
const SILENT_VOLUME_DB: float = -80.0
const HEADLESS_WRITE_ENVIRONMENT: String = (
"straywild_ISOLATED_VALIDATION_STORAGE"
"NETFISHING_ISOLATED_VALIDATION_STORAGE"
)
signal settings_changed(settings: PlayerSettings)

View file

@ -416,12 +416,6 @@ func _run() -> void:
)
assert(normal_camera.is_position_behind(chat_anchor))
assert(not free_camera.is_position_behind(chat_anchor))
var shop_prompt := game_ui.get_node("%ShopPrompt") as Control
var storage_prompt := game_ui.get_node("%StoragePrompt") as Control
game_ui.set_shop_prompt_visible(true, chat_anchor)
game_ui.set_storage_prompt_visible(true, chat_anchor)
assert(shop_prompt.visible)
assert(storage_prompt.visible)
chat_ui.show_local_speech("hello there friend")
await process_frame
assert(bool(player.get("_speech_mouth_active")))

View file

@ -2,7 +2,7 @@ extends SceneTree
const CHARACTER_SCENE: PackedScene = preload(
"res://art/exported/characters/base/straywild_base_character.glb"
"res://art/exported/characters/base/netfishing_base_character.glb"
)
const EXPECTED_ANIMATIONS: Array[StringName] = [

Some files were not shown because too many files have changed in this diff Show more