Adjusted when a join request is sent, and who it is sent to
Adjusted default course/act/level/area for new players
Added a sequence id to level area inform
Adjusted reliable packets to be sent half as frequently
Added ability to make a DjuiBase keep its aspect ration
Added on_render_pre callback
Added ability to display 32b images
Added DjuiFlowLayout
Added logo
In an attempt to track down an issue that causes packet flooding and
hanging, I've looked at every step of the networking process and tried
to clean up anything strange I saw.
Made DJUI render at 60 fps
Added mouse cursor and hooks in SDL for capturing the window-relative mouse position
Started creating an interable system where elements can respond to events such as on_mouse_hover
The birth of a custom user interface system.
Has the ability to draw things to the screen at native resolution
regardless of window size.
Components can be nested within one another to an arbitrary depth.
Text rendering is completely rewritten.
Text and images can be clipped by their parent container.
Fixed releasing of sync objects that otherwise don't sync their death events
Fixed using/releasing reserved objects in an area that the server isn't in
Created a timer based on area that is shared. The puzzle pieces will
execute rapidly to catch up to the timer on level join. This keeps them
in sync without constantly needing to acknowledge that a puzzle piece
had moved before continuing.
Prevented crash that happened when an upstairs painting was entered
Synchronized TTC speed setting
Synchronized WDW water level on late join
Player packets no longer broadcasted to clients in a different location
No longer needs hacky stuff like relying on the macro for goomba triplet removal.
Instead we simply keep a list of sync ids of objects that were removed (but were
around at the start of level loading)
Instead of the server dropping them immediately, the server only drops the processing. This allows it to broadcast/send the packet to the correct client without the server processing it.
Fixed how "static" level objects were detected. The old way was error prone and would consider spawned objects to be static anyway.
Made ERROR_LOGs always show up, "disabling" logging only turns off INFO_LOGs now.
Now "syncId"s can only be reserved at ID 127+. This ensures that static level
objects and spawned reserved objects never clash. The server keeps track of
every player's list of reserved IDs, as well as when an ID is used, or when
an entity using that ID is destroyed. This is much more complicated than it
used to be, but this complication is required due to players being allowed to
be in different areas of the game.
Now packets can be grouped up and sent separately, but still be processed
sequentially regardless of how much they get scrambled over the network.
If a packet group isn't received for 15 seconds, all unprocessed packets
in that group will be dropped. Packet ordering is required for level and
area synchronization information when someone joins the level late.
Added packet_level_respawn_info to inform the players of entity
deletions in a different area of the same level. Currently it's
massively noisy due to sending out a new packet for each entity
destroyed. This can cause chaos when collecting a series of coins.
Ideally this information would be batched and sent in one big blob every
so often.
Now level changes and area changes are separated. Entity deletions are
properly tracked on level change or area change. Late entity
synchronization is now triggered on any area change.
Removed (slightly) old coin and static ent removal system
Resynchronized respawners
Added packet for macro deletions
better than previous system since the entities don't need a sync id and we can synchronize deletion station across areas
allows the synchronization of odd entities like lines of coins
Added packet for spawn info deletions
Split packet_location_request into multiple files
Players/cameras were able to clip inside of island-like levels
previously. I have hardcoded sane minimum Y values for the following
courses: WF, CCM, PSS, BITDW, TTM, RR, BITS
Considered nearest player for various things within the following
entities that I missed the first time around: cloud, koopa, monty mole,
moving coin, piranha bubbles, scuttlebug, shock wave, spindrift.
* added a new audio bank 10 for luigi sounds
* made some audio memory buffers larger to fix sound cuts
* added option to enable/disable luigi sounds in the sound options menu
* added Andrat's "90's Classic Luigi Voice Pack" as default luigi sounds
Co-authored-by: anzz1 <>
Switched from manual checking of Luigi to using new Character structs
Synchronized cap spawning for mario_blow_off_cap()
Added declarations for network_send_death() and network_receive_death()
* Ukiki now steals Mario/Luigi hat correctly
* Klepto now steals Mario/Luigi hat correctly
* Mr. Blizzard now knocks off Mario/Luigi hat correctly
* Fwoosh now knocks off Mario/Luigi hat correctly
Co-authored-by: anzz1 <>
Adds button to the host menu to allow shared lives.
Resolves#37
Buttons are now resizeable. Use gButtonScale.<size> (large, medium, or small).
It could be argued that we don't need the small size. However, it may be beneficial for the future if the menu becomes more complex.
large is the normal default size. Or at least it was the size already being used by sm64ex-coop (0.11111111f)
Note: Buttons for changing menu's should be gButtonScale.large as the menu animation is made for large buttons. To keep consistency it's probably a good idea for buttons that transfer you to a new menu to always be set to large. As such, I didn't feel it necessary to extend this feature to these methods: bhv_menu_button_growing_from_custom and bhv_menu_button_shrinking_to_custom.
Resolves#60
Increased error checking of get_behavior_from_id
Made failure logging for packet_object a lot better
Changed debug logging to show global index instead of "Server/Client"
Changed debug keyboard binds to support more keyboard types
Made SyncObject's rxEventId de-duplication per-player instead of one-player
Removed sizeof(enum) from packet_read/packet_write
The old implementation was hacky and often returned desynchronized
results. This implementation gives a seed to each sync object, and
synchronizes that seed. Also allows for a seed to be saved temporarily
based on position and recycled for multiple calls.
Allows mods to register themselves so that mismatches don't occur. This
does not automagically detect when someone modified the game, so the
mods will have to insert a function like this into their patch:
static void __attribute__((constructor)) _register_this_mod() {
network_register_mod("mod name here");
}
Eyerok was synchronized, but I'm still not super pleased with the
result. I had to sacrifice dialog to prevent weird states and he's
completely controlled by the server. His synchronization should be
revisited in the future.
SSL should be fully synchronized now.
* Remove Discord references if DISCORD_SDK=0
* Disallow non-valid ports > 65535
* Only print last attempt's port in direct connection screen if it's non-default
Stay in level after star option revealed that the deduplication
checking I was doing previously is no longer a valid way to do it.
The old way would prevent a second star from spawning.
The precision of ray casting was too low previously, causing the
collision checks to skip right past a wall sometimes. There was also
nothing to prevent the camera from getting too close to a wall
horizontally or vertically.
Changed synchronizing text to be more descriptive
Added 'player connected', 'player disconnected', 'network shutdown' chat messages
Prevented someone from joining through Discord while in another lobby
Added the distinction of sending a packet to all vs to a specific player
Enforced lobby size of 2, multiple joiners in a direct connection will be booted
Stored network destination for each player
Detected network drops
The vanilla main menu is an awful pile of code that is extremely painful
to make additions to. So I've side-stepped the problem by writing an
entiely new menu system without all of vanilla's quirks. I've separated
the custom menu system from the menus I want to make, which allows for
easy additions and a clear separation of responsibilities.
Along with this rewrite comes a host menu, adding the missing
configuration options in-game.
Fixes#29
In preparation for other forms of communication, I have abstracted all
of the socket code (which needs direct connections) behind a struct
whose calls can be swapped out for other systems if desired.
Should be snappier and less prone to crashes. I tested as many scenarios
as I could think of and it has been rock solid. But time will tell.
Also created a new debug log system, just so I could understand what the
hell was going on with this code.
Two players in the same cannon was causing softlocks and general
insanity. Now this should be fixed. Also prevented players from being
able to push or attack a player inside of a cannon.
As noticed by anuserlol, stars would sometimes not spawn from breakable
boxes on the remote. This was due to the box being destroyed before the
star spawned, when the star tried to spawn it couldn't find the parent
and gave up. Now if no parent is found the spawned object will be its
own parent. This should make all spawned objects more reliable, but may
cause weirdness somewhere.
Fixes#34
Since the second-player code was the first code I wrote, it was implemented
poorly. At that point, I didn't know the code base at all and the way it was
written would prevent anyone from ever adding to those parts.
The rewrite allows me to use the default geo.inc.c file for Mario, and removes
all of the geo2.inc.c files. I no longer do a bunch of bit shifting to figure
out which player is being drawn in the rendering code.
I'm also now able to remove tons of duplicate code that exists just for the
remote player. The main player code is generic enough to support both indices.
A side-effect of the rewrite is I was able to remove many assumptions in the
code where two-players is assumed, but many other parts of the code still
assume two players.
This is a fairly major change that, if all goes well, will be completely
unnoticed by the player. However, I do expect new bugs to pop up in strange
places. Time will tell.
Saves and loads last join IP/port attempt
Made host's port configurable in config file
Made host's save slot configurable in config file
Made host's player interaction setting configurable in config file
Indicated when the client was trying to connect on the join menu.
Fixed join menu display error where the port would disappear
Made water punch do an attack
Increased knockback significantly
Different types of attacks will have different knockback severity and damage (Stomp > kick > the rest)
Fixed rapid attack spam
Adjust radius for bouncing on players and popping bubbles
Made player interactions a synchronized server flag:
None - Players are not solid
Solid (Default) - Player can run into each other and stun each other
PVP - Same as solid except friendly fire is on
Note: Not currently configurable due to a lack of a UI.
Player life counters are separate.
When one player dies they lose a life and are turned into a bubble.
If the other player pops it, they are alive again.
If all players are bubbled, they get kicked out of the level.
If the bubbled player ran out of lives, they can not come back to life
until the level is over.
Whenever a level change happens, everyone's life count is set to a
minimum of two.
No game overs.
Took heavy inspiration from Kaze Emanuar
Now when a client joins, it will request the entire 512 byte EEPROM from
the server and refuse to continue until the server replies with the
contents. Then the client will override all reads and writes to the
EEPROM/save file. Thus, a client will never overwrite their local save.
Fixes#21
Now a patch can choose to register callbacks for sending and receiving
packets. It's a bit tricky to use but at least it won't collide with
normal packets or other mod packets.
Due to my compile & launch scripts, I was silently ignoring warnings
this whole time. I've fixed my process, and gone back to fixed all of
the warnings I could (even outside of my code).
As reported by somario360:
After grabbing the small box at the same time, one of two results can happen.
There will be a fake cloned box that will only be visually in the other
player's hands, or one player will be stuck in the punching animation until
the other player lets go of the box, in which the box goes into the stuck
player's hands.
Now escapes from action if the grab fails, preventing a softlock.
And now if both players report having the same object, the client
will drop their copy.
Fixes#14
Tuxie will regain its hitbox if dropped through crouching or any other means
Fixed detection of if any mario is far away
Immediately sends an object packet whenever any object is dropped or thrown
Fixes#9
Players are now solid to each other and can push each other
Players can now attack each other (but they do not deal damage)
Players can bounce on top of each other, and they get squished
temporarily
Players are given slightly offset positions when they transition between
areas and levels, so they're no longer on top of one another.
The code was skipping playing the sound of the first punch, and changing
the size of the first for the first punch. Added hacky stuff to the
player packet code to ensure those events are hit.
Fixes#10 reported by somario360
Sleeping animations were desynchronized previously. Now remote goes to
sitting, and to laying down, at the right times. A snoring remote player
will no longer lower your music, and will no longer get stuck snoring
when they wake up.
Fixes#11 reported by somario360
There have been several times where the unpredictable behavior of
a remote player where execute_mario_action() would get caught in
an infinite loop. Now we attempt to detect an infinite hang and
escape from it. The sequence of actions will be recorded into an
errorlog.txt file. In debug mode this infinite hang will cause an
assertion to fail, crashing the game. In normal mode the game will
break out of it and hopefully carry on normally after new packets
come in.
I believe this addresses github issue #12 but I can't be sure.
Reported by somario360:
After I (Luigi) gave the baby penguin to the mother, the start spawned,
but I was stuck in the looking up animation.
My friend (Mario) talked to Bowser after defeating him, Bowser turned into
a key, but he was stuck in the looking up animation after (I was able to
grab the key though, but Bowser was slightly visible) (Also don't mind 0
stars, he loves doing the lobby BLJ)
The issue is the state machine moved on without removing the reading
dialog action. There was no straight forward way to deal with this.
Custom functions were written for each call to dialog to ensure that we
should stay reading the dialog.
Bug reported by somario360:
After I (Luigi) exited the slide in CCM, an error message appeared and ignoring would make it pop up again.
This was due to the sync ID reservation system not being flushed and
reset on area change.
Bug reported by somario360:
When trying to open the cannon in a level (so far tested in BOB & WF) the cannon dialogue will repeat infinitely. Sometimes the cannon will open, but the game will crash after.
The code I had written previously to prevent softlocks ended up causing
them due to a incorrect check of activeFlags.