close
Skip to content

[pull] main from fishfolk:main#2

Merged
pull[bot] merged 84 commits into
codingwatching:mainfrom
fishfolk:main
Jul 15, 2025
Merged

[pull] main from fishfolk:main#2
pull[bot] merged 84 commits into
codingwatching:mainfrom
fishfolk:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Mar 5, 2024

See Commits and Changes for more details.


Created by Image pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull Bot added the ⤵️ pull label Mar 5, 2024
MaxCWhitehead and others added 28 commits March 9, 2024 18:47
Install the bones network debug egui plugin / add a button to open it
from debug window.

Companion PR to fishfolk/bones#345
Add a steam_package.sh script that pulls releases from github, rezips as
.zip such that they can be uploaded to steamworks for respective
platforms.

For linux, we also install some launch scripts. There's logic here to
fix #904. Isn't pretty but seems to work, scaling is correct in steam
deck game mode + desktop mode. Should not impact other linux platforms.

Need to test again with steam deck with external display, but I think
this should work based on last I was exploring solutions to #904.
companion PR for: fishfolk/bones#346

frame time window re-added to bones, this enables viewing it.
…pdate velocities to keep behavior (#925)

**Overview:**
Delta time in physics update previously had a scale of 60 due to a prior
fix regarding timestep.

This change removes the scaling of physics timestep by 60, and adjusts
velocities / forces (gravity) to account for this so behavior does not
change.

**Impact:** Will help with ragdoll work I am doing, velocity metadata
can be used with objects simulated in rapier and on our kinematics
without having to get messy scaling them back and forth, or dealing with
a very large timestep in rapier (which did not go well in my
experiments).

units of velocity and gravity now relate more intuitively to position +
sizes of objects in terms of setting velocity based on how far a
contributor may want something to move per second.

**Changes:**
- velocities all scaled up by 60, gravity scaled up by 3600 (60*60) as
this is multiplied by time twice.
- Gravity values are now quite large, unless we want to change unit of
gravity and add back in a magic scale factor will have to roll with this
I guess. I think it's ok this way, new contributors may reference global
gravity metadata to get an idea of what to set a specific body's gravity
to.
- apply_rotation now uses delta time (kinematic rotations should now be
consistent regardless of frame rate)
- Fix bullet position update from velocity not being scaled by delta
time
- Fix setting velocity.y = 0 when grounded comparing against global
gravity (now corrected to use body's gravity)
- Fix sproinger velocity condition including gravity incorrectly (don't
think we need gravity in this at all)

**Other Notes:**
I am hoping I caught all of the values that needed updating. Testing
movement / jump, throwing items, sproinger, bomb bounces, it looks right
to me.
- One thing I noticed is that some item metadata includes a
"angular_velocity" value which is used as spin factor for item throw.
Spin scales based on the throw velocity, so these spin values do not
need to be updated. This is more of a spin factor than a true angular
velocity, may consider renaming in future.
- There are a few values hard coded that we could pull into metadata,
but I didn't want to make footprint of change any larger than necessary.
- some metadata for player movement is duplicated between player skin
metadata, may want to pull this out to single metadata location in
future.
This is the base of core changes to support ragdolls, allows us to
simulate dynamic bodies in rapier.

DynamicBody component may be added to an entity that has KinematicBody,
and if enabled, body will simulate physics. Transitioning between
kinematic / dynamic and adjusting rapier data + collider is handled on
next physics update.

This change should have no impact on existing kinematics, scene queries,
etc. Usage of these changes will come in other PR soon.

**Switched to fork of rapier (temporarily hopefully):**
I switched us to a fork of rapier to fix a bug in which changing a
rapier rigidbody from kinematic to dynamic will not put it in active
dynamic set, so gravity is not applied. It seems they rely on contact
graph to add body to this set, but if not in contact with anything it
breaks. I have a PR open for a fix in rapier.
- I also updated version, slight change in debug draw code is because of
changes there.

**Some notes on changes:**
- Some helper functions are included for pushing simulation commands for
dynamic body that apply changes to rapier body before next physics step.
- There is a mutate_rigidbody function on CollisionWorld that makes
accessing rapier body for immediate mutation slightly more convenient.
- Previously bodies were created as dynamic (but we used them as
kinematic anyway), now they are actually flagged as kinematic in rapier.
This does not impact collision events at all.

There's a decent chunk of physics stuff in collision module now, at some
point maybe should detangle this, but probably fine for now. I renamed
some functions to make things more clear.
…simulated bodies (#928)

Another chunk of features implemented to support ragdolls + dynamic
bodies in Jumpy.

### **Contact filtering:**
Add bit flags for rapier `CollisionGroup` and `SolverGroup`.
- The Collision group filters both contact forces and events, these are
configured such that there is no change here in collision events.
- Solver group then filters contact forces, this is used to make sure
dynamic actors only simulate collision with tiles (solid + jump through)
and solids, not other kinematic (or dynamic) actors.

### **Jump Through for Dynamics:**
Dynamics collide with jump through tiles. A contact modification physics
hook is implemented so dynamics moving upward through jump throughs have
contact thrown out, and kept when falling.
- Only the contact filtering `PhysicsHook` is used, and is only enable
on dynamic bodies while they are simulating.

### **Changing actor shape:**
I found that using a capsule works better for player ragdoll then
rectangle, which requires being able to change the shape of a collider.
A helper function is added to do this correctly, changing shape is only
currently supported for actors.

### **Handling `Stop` collision events for removed colliders:**
Changing an actor's shape involves removing collider and re-adding it.
This triggers a stop event from rapier. These events provide collider
handles, yet we map this to entities from userdata. The consequence of
this is that when the stop event is dispatched, the collider handle is
already invalid (generation incremented), meaning we no longer can
access user data to determine what entity should be removed.
- We now have a function that should be called on removal of collider in
`CollisionCache` that temporarily caches the handle + entity, which is
used as fallback when receiving stop event if collider handle is not
valid.

This is not a great system, if someone removes a collider and does not
call this, our collision event will not be removed causing bugs. Might
be able to make this better, but for now will just have to make sure if
we get fancy removing a collider (which is already a delicate / involved
operation) this is called. The function to change actor shape calls this
for us.
### Ragdoll State
Player may toggle ragdoll state with `F` or `Right bumper`.
- player body switches to capsule and simulates physics in ragdoll
state.
- movement during ragdoll twitches the body slightly, small velocity +
animation change.


### Minor Related Fixes
- set position with respect to parent no longer forced to 0 for all
objects. Used this to tweak capsule position.
- Attached entities now rotate with parent.


### Animation
This will need another pass, for now I re-used some stuff we have.
Making the corpse more obviously dead would be good (though I guess
being able to reasonably play dead may also be amusing).


https://github.com/fishfolk/jumpy/assets/35712032/9bdcbc0c-146b-4339-a7bd-4ed1ca1bb44d


https://github.com/fishfolk/jumpy/assets/35712032/f9004638-fc03-4ee6-8e6f-0f7f0ab1f3a3


https://github.com/fishfolk/jumpy/assets/35712032/5407bcf3-e9c9-4aa3-83e1-ba95adc3fcac
Closes #930 

- Adds a `PlayerCommand` to drop a player's hat and reset its properties
- Replaces all instances of manually dropping a hat to use the new
convenience command
…from metadata (#935)

I opened a PR in bones to expose these settings for networking, instead
of hard coding in engine. (fishfolk/bones#354)

The defaults of these values were also changed in bones such that things
are feeling much better in network play with ping around 100ms-150ms.

Now we may tune in metadata, though settings only take effect if new
network match is created. This will not pass CI until bones PR is merged
+ bones version updated.
…n with dynamics (#931)

define some collision info for jump through wood tiles, used to create
accurate colliders for collision with ragdoll / dynamics.

The standard tile is still there for all intents and purposes. If there
is an extra collider defined, this collider is also added, and is set to
solver group such that dynamics will collider with it.
- This additional collider is not used for collision events.
- if additional collider is present, original tile collider no longer
has solver group for collisions.

This fixes dynamics colliding with the invisible chunk on thin tiles
such as jump through wood.

I think we're done with the trickle of auxiliary features and next PR
should be ragdolls 😆
Fixing a crash in release that was in 0.11.0
…#946)

Should switch off git revision once new rapier release is published.
…atforms successfully (#947)

0.11.1 macOS x86_64 build failed during release - seemed related to dep
on my fork of rapier, which we no longer need as PR was merged. Crossing
my fingers that #946 resolved that issue and 0.11.2 goes smoothly.
The new blunderbuss is done, this closes #579.

I used the artwork from #152. `bullet_spread` and `bullet_count` are
open for changes on `assets/elements/item/buss/buss.yaml`. I also made a
quick artwork as the musket bullets explosions are too big for the buss
bullets size, but it's basically a smaller musket explosion. My idea was
a mid-range shotgun but it could be easily modified through `yaml`.
Blunderbuss will spawn in level 1, 3, 4, 7 and 11.



https://github.com/fishfolk/jumpy/assets/107818001/93ee26ef-3e94-49a2-8bce-e7484eb1ed0d
Periscope ported, this closes #151.

It's similar to the musket and is mainly useful if the enemy is higher
than you. Used the artwork from #151 but the concept art confused me a
bit as it says to be "similar to the musket" but in the art it looks
like more a shotgun as it has some bullet spread, but adding a very low
bullet spread would be a nice idea here so let me know if you think it
should be used.

As it's very similar to the musket, it had a certain amount of code
duplication, which I think we could discuss together and come to a
decision whether to generalize something elsewhere or whether we want to
make adjustments to add more uniqueness to the designs.



![shooting_periscope](https://github.com/fishfolk/jumpy/assets/107818001/c772e309-3e3c-4fc9-a6f4-84edf08ce877)



![periscope](https://github.com/fishfolk/jumpy/assets/107818001/042110a6-4043-4d4e-95f4-93fecf259789)
Closes #951 

- De-duplicates dependencies:
- `async-lock`, `base64`, `getrandom`, `linux-raw-sys`, `parking_lot`,
`parking_lot_core`, `rand`, `rand_chacha`, `rand_core`, `rustix`,
`synstructure`, `wasi`
- Duplicates dependencies:
  - `erased-serde`, `polling`
- Fixes security advisory due to `failure` crate removed from dependency
tree
  - All CI tasks now pass! 🎉 

---

<details>
<summary>Compare duplicated dependencies</summary>
<pre>
function get_dups() { cargo deny check 2>&1 | sed -En
"s/^warning\\[duplicate].*('.*')/\1/p"; }
<br>
git switch main
get_dups > before.txt
<br>
git switch &lt;ref-you-want-to-compare-to-main&gt;
get_dups > after.txt
<br>
git diff --no-index before.txt after.txt
</pre>
</details>
This PR closes #573.

I added `bullet_spread` system to the machine gun because I think it
balances the game and looks good, and added `empty_cooldown` because it
would be really boring if `gun_empty.ogg` kept playing at the same
frequency as the normal cooldown, so in this gun we have the shooting
cooldown and the empty sound cooldown. I also made a very slight change
in the main system for using items because it had to be able to shoot
constantly, so now you can keep shoot input pressed with any weapon.

Something I think is important to mention is that the shooting animation
is synchronized to the rate of fire, so if you change the rate of fire
the animation will also change. It could be easily changed with a new
variable in the .yaml so let me know whether you think it should be
faster or slower.

The machine gun has two states (idle and shooting) and its only function
is to reset and start animations.
…ng incorrect post-physics refactor (#957)

Found a few velocity-based meta values I missed in the #925 refactor.
I did what @MaxCWhitehead told me earlier, created a
`bullet_spawn_offset` field in `.yaml`. I added this to all the weapons
because it makes it easier for new contributors to locate and modify in
case we change the artworks.
…in QBVH (#960)

I've been frequently hitting a crash / bug in parry2d QBVH involving
incremental update. Sometimes it crashes, sometimes is a framerate death
spiral / fully locks up.

```
thread 'main' panicked at /Users/max/.cargo/registry/src/index.crates.io-6f17d22bba15001f/parry2d-0.13.6/src/partitioning/qbvh/update.rs:367:54:
attempt to add with overflow
```

Appears to be been fixed at
dimforge/parry@7df2728
in parry2d 0.13.7. Updated rapier to use a fork with parry2d update as
not updated in rapier yet.
…every frame (#962)

See #961 for context. There's a bug in parry2d involving incremental
update failing to balance broadphase BVH. Fully rebuilding BVH avoids
this issue, and we can get away with it due to few bodies in our game.
This was our previous behavior before supporting dynamic bodies and
relying on incremental update in physics pipeline, which turns out to be
broken.
…#966)

Update bones for the following fixes:

fishfolk/bones@6b8d743
(fix: Fix race condition on if EguiCtx is initialized before bones game)

fishfolk/bones@cbe537f
(fix: Fix Zero'd DenseMoveDir not representing no input.)
… max prediction (#967)

Update bones to get a fix for issue causing desync in 3+ player matches.
MaxCWhitehead and others added 29 commits August 5, 2024 00:19
…1017)

Use AudioCenter from bones now that it has been moved there, and remove
from Jumpy.

Added a trait extension to continue playing music from kira
`StaticSoundSettings`, to avoid having to put all of the params in
`play_music_advanced`, as the looping is configured a bit differently.

The addition of `force_restart` in PlayMusic event has been helpful, now
music does not restart each time switch menu pages.

Resolves #1016
)

Should address at least part if not all of the issues with the current
.gitattributes
We updated download-artifacts to v4 but not upload, seems to have broken
release pipeline, hopefully this fixes.
Add support for some environment variables, only available in debug
builds, that allow for quickly loading into a single-player game.

## Examples

To launch straight into a single-player match with Fishy, the default
player, on Keyboard1:

```shell
TEST_MAP='Dev Level 1' cargo run
```

You can also specify another player:

```shell
TEST_MAP='Dev Level 1' TEST_PLAYER='Sharky' cargo run
```

And even provide a hat:

```shell
TEST_MAP='Dev Level 1' TEST_PLAYER='Sharky' TEST_HAT='Cowboy Hat' cargo run
```

Or, auto-select a player, launching directly to the map select menu
(again, optionally with a hat):

```shell
TEST_PLAYER='Orcy' TEST_HAT='Unicorn Hat' cargo run
```

All of these examples set Keyboard1 as the control source for the
player. You can provide a different source like so:

```shell
TEST_CONTROLLER='Gamepad' TEST_MAP='Dev Level 1' cargo run
```

Any combination of one or more of these four environment variables will
skip straight to either the map select menu or directly into a match if
a map is provided. Fishy with no hat on keyboard1 is the default if only
a map is given.
…te (#1032)

This updates bones and uses new matchmaking flow. Includes using the new
matchmaker rng seed, and gilrs update.

Some other little fixes included:
- "Waiting for players" text now displays again when matchamaking
- If start matchmaking online and switch to lan tab, matchmaking is now
cancelled.

Gilrs update confirmed fixes: #989
Fixes #933 

Disabling only gamepad input seems to make the input behave as one would
expect. Arrow keys, backspace, etc work like normal, and bound keys
(e.g. A, D) only update the text and no longer move the caret.

Unfortunately I don't have a controller to test with, but I assume this
will work with those kind of inputs too.

---------

Co-authored-by: Max Whitehead <max.blackllama.alt3@gmail.com>
Follow-up to #1023, partially reverting it as there is a simpler fix,
and fixing the remaining bugs.
Replace `std::process::exit(0)` with proper use of the
`bones::ExitBones` resource.
Fixes #963

## Changes

-
[6781542](6781542)
`PlayerSlot` is now (sort of) a state machine, starting out `Empty` then
progressing through `SelectingPlayer` and `SelectingHat` until becoming
`Ready`
- Slot for a network player only uses the `SelectingHat` and `Ready`
states for simplicity
- Angled brackets `<` and `>` show around the thing being selected
(player/hat), brackets now don't show when ready
-
[a2393c4](a2393c4)
fix bug where label has incorrect text for 1 frame when pressing Menu
Back to remove player from slot
-
[f636d33](f636d33)
Upgrade bones to latest
- Set gitattributes for `*.ftl` files so that they are treated as text
for diffs and not binary files
- Ignore advisory `RUSTSEC-2024-0370` proc-macro-error is unmaintained
(see [related bones issue](fishfolk/bones#479)
and [the advisory](https://rustsec.org/advisories/RUSTSEC-2024-0370))

This also fixes a bug I was seeing on `main` where another player in a
LAN lobby pressing A/D would behave as if everyone pressed A/D, e.g.
pressing D to select the next skin would change to the next skin in both
slots.

**Rationale for the rough state machine:**

Previously there were 3 states for a player slot: Empty,
SelectingPlayer, and Ready + SelectingHat. This state was maintained by
two booleans, `active` and `confirmed`, which tell you whether the slot
is not empty and whether the player has readied-up respectively.
Together they represent the 3 states as: (`active/confirmed`)
`false/false`, `true/false` and `true/true`; with `false/true` being an
invalid state.

Now that there are four states to the ready-up process, one way of
implementing this is to add a third boolean, but this introduces 3 more
invalid states. Let's say the boolean is called `selectedPlayer`, these
are the possible boolean combinations and the states they represent
(`active/selectedPlayer/confirmed`):

```
false/false/false Empty
false/false/true <invalid>
false/true/false <invalid>
false/true/true <invalid>
true/false/false SelectingPlayer
true/false/true <invalid>
true/true/false SelectingHat
true/true/true Ready
```

The implementation I opted for is a simple state machine. While it added
a lot more code to some areas of this module I found it made reasoning
about some sections much easier. It also made explicit certain edge
cases in the `handle_match_setup_messages` system where e.g the client
could theoretically receive a confirmation message from a peer when it
had not yet received any player selection messages. A warning log is now
generated in the unlikely case this occurs.
…ready (#1040)

Fixes #1036 and couple other things along the way

Not entirely sure what caused this - but I think I introduced it when
updating for new matchmaker interface in bones.

We would allow online matches to continue if >1 players are ready and no
unconfirmed players. The issue is that in online remote players who had
not made a selection were in `Empty` state, and not tracked as
unconfirmed. Now for any local + required players, I initialize them to
new PlayerSlot type `SelectingLocalControlSource`. `Empty` may be used
for online slots that are unused (the last 2 slots in a 2 player game)
in online, or for lan, optional slots that may be joined by additional
players/AI, but are not required. And remote required players are set to
`SelectingPlayer` with default fish + no hat - as next message expected
from them is change in player, and they don't need to select control
source, we know they are remote.

This seems to have fixed the match starting without all players ready,
as all required players are initialized to something other than `Empty`.


### Other fixes / changes

#### Remembering Hats:

I noticed that if you select a hat and then deselect it going back to
fish select - the other online players would still see this hat, but
local player resets to None. If player selected hat, went back to fish
select, then readied up with no hat, the remote players would see hat,
but not the local player. This could cause desync. Now When you go back
to fish select, your hat is remembered.

#### Always display default fish:
We were no longer displaying default fish in online when player had not
yet selected a control source/fish. Now regardless of if have actually
selected a fish, the default fish + no hat is shown (If the slot is a
required player that we are sure will select one eventually / must ready
up). In local for unjoined slots, no default fish is shown until joined
or AI is set.

#### Show when remote players ready
In online when a remote player is ready, this is now displayed.

@nelson137 feel free to review (if you want) as I know you were just in
here. Player select sure is complicated lol, but feeling good about the
changes I think we're making it more manageable 😅
Fixes #990.

Reorder the spawners in the level asset so that players 1 & 2 spawn on
opposite sides of the map.
Fixes #1014 (for now).

It sounds like a proper fix entails significant work; but to fix the
immediate issue we can move the rope tiles away from any others so that
those adjacent to them are blank.

## Before

<img width="256" alt="before-asset"
src="https://github.com/user-attachments/assets/41e8ffb8-4034-492b-9f17-ce182656679b">
<img width="256" alt="before-game"
src="https://github.com/user-attachments/assets/e30bf931-ca2a-46a7-86b8-c2e6971e4155">

## After

<img width="256" alt="after-asset"
src="https://github.com/user-attachments/assets/86342a5c-cab9-4caf-948b-ce01f68393b0">
<img width="256" alt="after-game"
src="https://github.com/user-attachments/assets/df8c7c46-8a4d-4828-8370-fad89c108bdb">
Follow-up to #1041.

## Changes

- Fix the rest of the sprite artifacts in `ship_decorations`

## Things Worth Mentioning

- Changed levels 3 & 8 to use YAML flow style so that I could find tiles
by position (e.g. by searching for `pos: [13, 10]`:

    Before: 
    ```yaml
    tiles:
    - pos:
      - 1
      - 2
      idx: 3
      collision: Solid
    ```
    After:
    ```yaml
    tiles:
    - { pos: [1, 2], idx: 3, collision: Solid }
    ```

- Add script to get the layer names in any level files that use specific
tile indexes of a tilemap:

    ```yaml
    # Find all crow's nests (indexes 30-32) from ship_decorations
$ ./scripts/find-atlas-tiles.sh ship_decorations.atlas.yaml '[30,31,32]'

    ./assets/map/levels/level_3.map.yaml
    - foreground

    ./assets/map/levels/level_8.map.yaml
    - foreground

# This tells us levels 3 and 8 have crow's nests in their "foreground"
layer
    ```

- Fix git attributes for text files in `assets/` & `old_assets/` which
shouldn't be treated as binary (yaml, txt, ftl)
Added a glug sound when player dies to give additional audio feedback.
Here is the audio used:
https://freesound.org/people/brittmosel/sounds/529300/

This resolves #986.
The forked version wasn't working for me when building in a sandbox, so
I've bumped it to the upstream one that contained the fix.

Signed-off-by: Marcin Serwin <marcin@serwin.dev>
@pull pull Bot merged commit 8234e6d into codingwatching:main Jul 15, 2025
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants