Merge pull request #103 from fgsfdsfgs/coop-dev

custom player colors (and other "unstable 3" changes)
This commit is contained in:
djoslin0 2021-04-08 00:11:02 -07:00 committed by GitHub
commit cb0c742514
29 changed files with 473 additions and 109 deletions

View File

@ -2,6 +2,8 @@
Online cooperative multiplayer mod for SM64, aiming to synchronize all entities and every level for two players. Online cooperative multiplayer mod for SM64, aiming to synchronize all entities and every level for two players.
Fork of [sm64pc/sm64ex](https://github.com/sm64pc/sm64ex). Fork of [sm64pc/sm64ex](https://github.com/sm64pc/sm64ex).
Build instructions are available on the [sm64ex wiki](https://github.com/sm64pc/sm64ex/wiki).
Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**. Feel free to report bugs and contribute, but remember, there must be **no upload of any copyrighted asset**.
Run `./extract_assets.py --clean && make clean` or `make distclean` to remove ROM-originated content. Run `./extract_assets.py --clean && make clean` or `make distclean` to remove ROM-originated content.

View File

@ -788,6 +788,7 @@ const GeoLayout luigi_geo[] = {
GEO_OPEN_NODE(), GEO_OPEN_NODE(),
GEO_SCALE(0, 17202), GEO_SCALE(0, 17202),
GEO_OPEN_NODE(), GEO_OPEN_NODE(),
GEO_ASM(0, geo_mario_set_player_colors),
GEO_ASM(0, geo_mirror_mario_backface_culling), GEO_ASM(0, geo_mirror_mario_backface_culling),
GEO_ASM(0, geo_mirror_mario_set_alpha), GEO_ASM(0, geo_mirror_mario_set_alpha),
GEO_SWITCH_CASE(0, geo_switch_mario_stand_run), GEO_SWITCH_CASE(0, geo_switch_mario_stand_run),

View File

@ -3225,7 +3225,8 @@ Gfx mat_luigi_body[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0), gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 0),
gsDPSetTileSize(0, 0, 0, 124, 124), gsDPSetTileSize(0, 0, 0, 124, 124),
gsSPSetLights1(luigi_body_lights), gsSPCopyLightEXT(1, 3), // gsSPSetLights1(luigi_body_lights)
gsSPCopyLightEXT(2, 4), //
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -3265,7 +3266,8 @@ Gfx mat_luigi_cap[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, 0, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0), gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 0, 0, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0),
gsDPSetTileSize(0, 0, 0, 124, 124), gsDPSetTileSize(0, 0, 0, 124, 124),
gsSPSetLights1(luigi_cap_lights), gsSPCopyLightEXT(1, 5), // gsSPSetLights1(luigi_cap_lights)
gsSPCopyLightEXT(2, 6), //
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };

View File

@ -1811,6 +1811,7 @@ const GeoLayout mario_geo[] = {
GEO_OPEN_NODE(), GEO_OPEN_NODE(),
GEO_SCALE(0x00, 16384), GEO_SCALE(0x00, 16384),
GEO_OPEN_NODE(), GEO_OPEN_NODE(),
GEO_ASM(0, geo_mario_set_player_colors),
GEO_ASM(0, geo_mirror_mario_backface_culling), GEO_ASM(0, geo_mirror_mario_backface_culling),
GEO_ASM(0, geo_mirror_mario_set_alpha), GEO_ASM(0, geo_mirror_mario_set_alpha),
GEO_SWITCH_CASE(0, geo_switch_mario_stand_run), GEO_SWITCH_CASE(0, geo_switch_mario_stand_run),

View File

@ -381,8 +381,8 @@ const Gfx mario_butt_dl[] = {
const Gfx mario_butt[] = { const Gfx mario_butt[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_butt_dl), gsSPDisplayList(mario_butt_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -499,8 +499,8 @@ const Gfx mario_left_arm_shared_dl[] = {
// 0x0400D1D8 - 0x0400D1F8 // 0x0400D1D8 - 0x0400D1F8
const Gfx mario_left_arm[] = { const Gfx mario_left_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_left_arm_shared_dl), gsSPDisplayList(mario_left_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -760,8 +760,8 @@ const Gfx mario_right_arm_shared_dl[] = {
// 0x0400DDE8 - 0x0400DE08 // 0x0400DDE8 - 0x0400DE08
const Gfx mario_right_arm[] = { const Gfx mario_right_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_right_arm_shared_dl), gsSPDisplayList(mario_right_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -979,8 +979,8 @@ const Gfx mario_left_thigh_dl[] = {
const Gfx mario_left_thigh[] = { const Gfx mario_left_thigh[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_left_thigh_dl), gsSPDisplayList(mario_left_thigh_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -1160,8 +1160,8 @@ const Gfx mario_right_thigh_shared_dl[] = {
// 0x0400EFB8 - 0x0400EFD8 // 0x0400EFB8 - 0x0400EFD8
const Gfx mario_right_thigh[] = { const Gfx mario_right_thigh[] = {
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_right_thigh_shared_dl), gsSPDisplayList(mario_right_thigh_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -1589,8 +1589,8 @@ const Gfx mario_tshirt_shared_dl[] = {
// 0x04010348 - 0x04010370 // 0x04010348 - 0x04010370
const Gfx mario_torso_dl[] = { const Gfx mario_torso_dl[] = {
gsSPDisplayList(mario_pants_overalls_shared_dl), gsSPDisplayList(mario_pants_overalls_shared_dl),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_tshirt_shared_dl), gsSPDisplayList(mario_tshirt_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -2080,8 +2080,8 @@ const Gfx mario_face_back_hair_cap_on_dl[] = {
// 0x04011960 - 0x040119A0 // 0x04011960 - 0x040119A0
const Gfx mario_face_cap_on_dl[] = { const Gfx mario_face_cap_on_dl[] = {
gsSPDisplayList(mario_face_part_cap_on_dl), gsSPDisplayList(mario_face_part_cap_on_dl),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_face_cap_dl), gsSPDisplayList(mario_face_cap_dl),
gsSPLight(&mario_brown2_lights_group.l, 1), gsSPLight(&mario_brown2_lights_group.l, 1),
gsSPLight(&mario_brown2_lights_group.a, 2), gsSPLight(&mario_brown2_lights_group.a, 2),
@ -3270,8 +3270,8 @@ const Gfx mario_medium_poly_butt_dl[] = {
const Gfx mario_medium_poly_butt[] = { const Gfx mario_medium_poly_butt[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_butt_dl), gsSPDisplayList(mario_medium_poly_butt_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -3322,8 +3322,8 @@ const Gfx mario_medium_poly_left_arm_shared_dl[] = {
// 0x04014840 - 0x04014860 // 0x04014840 - 0x04014860
const Gfx mario_medium_poly_left_arm[] = { const Gfx mario_medium_poly_left_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_left_arm_shared_dl), gsSPDisplayList(mario_medium_poly_left_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -3483,8 +3483,8 @@ const Gfx mario_medium_poly_right_arm_shared_dl[] = {
// 0x04014F40 - 0x04014F60 // 0x04014F40 - 0x04014F60
const Gfx mario_medium_poly_right_arm[] = { const Gfx mario_medium_poly_right_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_right_arm_shared_dl), gsSPDisplayList(mario_medium_poly_right_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -3659,8 +3659,8 @@ const Gfx mario_medium_poly_left_thigh_dl[] = {
const Gfx mario_medium_poly_left_thigh[] = { const Gfx mario_medium_poly_left_thigh[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_left_thigh_dl), gsSPDisplayList(mario_medium_poly_left_thigh_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -3808,8 +3808,8 @@ const Gfx mario_medium_poly_right_thigh_shared_dl[] = {
// 0x04015D00 - 0x04015D20 // 0x04015D00 - 0x04015D20
const Gfx mario_medium_poly_right_thigh[] = { const Gfx mario_medium_poly_right_thigh[] = {
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_right_thigh_shared_dl), gsSPDisplayList(mario_medium_poly_right_thigh_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4081,8 +4081,8 @@ const Gfx mario_medium_poly_tshirt_shared_dl[] = {
// 0x040168A0 - 0x040168C8 // 0x040168A0 - 0x040168C8
const Gfx mario_medium_poly_torso_dl[] = { const Gfx mario_medium_poly_torso_dl[] = {
gsSPDisplayList(mario_medium_poly_pants_overalls_shared_dl), gsSPDisplayList(mario_medium_poly_pants_overalls_shared_dl),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_medium_poly_tshirt_shared_dl), gsSPDisplayList(mario_medium_poly_tshirt_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4149,8 +4149,8 @@ const Gfx mario_low_poly_butt_dl[] = {
const Gfx mario_low_poly_butt[] = { const Gfx mario_low_poly_butt[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_butt_dl), gsSPDisplayList(mario_low_poly_butt_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4196,8 +4196,8 @@ const Gfx mario_low_poly_left_arm_shared_dl[] = {
// 0x04016C70 - 0x04016C90 // 0x04016C70 - 0x04016C90
const Gfx mario_low_poly_left_arm[] = { const Gfx mario_low_poly_left_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_left_arm_shared_dl), gsSPDisplayList(mario_low_poly_left_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4287,8 +4287,8 @@ const Gfx mario_low_poly_right_arm_shared_dl[] = {
// 0x04016FB0 - 0x04016FD0 // 0x04016FB0 - 0x04016FD0
const Gfx mario_low_poly_right_arm[] = { const Gfx mario_low_poly_right_arm[] = {
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_right_arm_shared_dl), gsSPDisplayList(mario_low_poly_right_arm_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4394,8 +4394,8 @@ const Gfx mario_low_poly_left_thigh_dl[] = {
const Gfx mario_low_poly_left_thigh[] = { const Gfx mario_low_poly_left_thigh[] = {
gsDPPipeSync(), gsDPPipeSync(),
gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA), gsDPSetCombineMode(G_CC_SHADEFADEA, G_CC_SHADEFADEA),
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_left_thigh_dl), gsSPDisplayList(mario_low_poly_left_thigh_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4513,8 +4513,8 @@ const Gfx mario_low_poly_right_thigh_shared_dl[] = {
// 0x04017818 - 0x04017838 // 0x04017818 - 0x04017838
const Gfx mario_low_poly_right_thigh[] = { const Gfx mario_low_poly_right_thigh[] = {
gsSPLight(&mario_blue_lights_group.l, 1), gsSPCopyLightEXT(1, 3), // gsSPLight(&mario_blue_lights_group.l, 1),
gsSPLight(&mario_blue_lights_group.a, 2), gsSPCopyLightEXT(2, 4), // gsSPLight(&mario_blue_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_right_thigh_shared_dl), gsSPDisplayList(mario_low_poly_right_thigh_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4684,8 +4684,8 @@ const Gfx mario_low_poly_tshirt_shared_dl[] = {
// 0x04017E78 - 0x04017EA0 // 0x04017E78 - 0x04017EA0
const Gfx mario_low_poly_torso_dl[] = { const Gfx mario_low_poly_torso_dl[] = {
gsSPDisplayList(mario_low_poly_pants_overalls_shared_dl), gsSPDisplayList(mario_low_poly_pants_overalls_shared_dl),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_tshirt_shared_dl), gsSPDisplayList(mario_low_poly_tshirt_shared_dl),
gsSPEndDisplayList(), gsSPEndDisplayList(),
}; };
@ -4854,8 +4854,8 @@ const Gfx mario_low_poly_face_back_hair_cap_on_dl[] = {
// 0x04018420 - 0x04018460 // 0x04018420 - 0x04018460
const Gfx mario_low_poly_face_cap_on_dl[] = { const Gfx mario_low_poly_face_cap_on_dl[] = {
gsSPDisplayList(mario_low_poly_face_part_cap_on_dl), gsSPDisplayList(mario_low_poly_face_part_cap_on_dl),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_low_poly_face_cap_dl), gsSPDisplayList(mario_low_poly_face_cap_dl),
gsSPLight(&mario_brown2_lights_group.l, 1), gsSPLight(&mario_brown2_lights_group.l, 1),
gsSPLight(&mario_brown2_lights_group.a, 2), gsSPLight(&mario_brown2_lights_group.a, 2),
@ -6625,8 +6625,8 @@ const Gfx mario_cap_unused_dl[] = {
gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, mario_texture_m_logo), gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, mario_texture_m_logo),
gsDPLoadSync(), gsDPLoadSync(),
gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 32 * 32 - 1, CALC_DXT(32, G_IM_SIZ_16b_BYTES)), gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 32 * 32 - 1, CALC_DXT(32, G_IM_SIZ_16b_BYTES)),
gsSPLight(&mario_red_lights_group.l, 1), gsSPCopyLightEXT(1, 5), // gsSPLight(&mario_red_lights_group.l, 1),
gsSPLight(&mario_red_lights_group.a, 2), gsSPCopyLightEXT(2, 6), // gsSPLight(&mario_red_lights_group.a, 2),
gsSPDisplayList(mario_cap_unused_m_logo_dl), gsSPDisplayList(mario_cap_unused_m_logo_dl),
gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF),
gsDPPipeSync(), gsDPPipeSync(),

View File

@ -3974,6 +3974,7 @@
<ClCompile Include="..\src\pc\network\packets\packet_keep_alive.c" /> <ClCompile Include="..\src\pc\network\packets\packet_keep_alive.c" />
<ClCompile Include="..\src\pc\network\packets\packet_leaving.c" /> <ClCompile Include="..\src\pc\network\packets\packet_leaving.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_warp.c" /> <ClCompile Include="..\src\pc\network\packets\packet_level_warp.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_warp_2.c" />
<ClCompile Include="..\src\pc\network\packets\packet_network_players.c" /> <ClCompile Include="..\src\pc\network\packets\packet_network_players.c" />
<ClCompile Include="..\src\pc\network\packets\packet_object.c" /> <ClCompile Include="..\src\pc\network\packets\packet_object.c" />
<ClCompile Include="..\src\pc\network\packets\packet_player.c" /> <ClCompile Include="..\src\pc\network\packets\packet_player.c" />

View File

@ -15087,6 +15087,9 @@
<ClCompile Include="..\src\game\characters.c"> <ClCompile Include="..\src\game\characters.c">
<Filter>Source Files\src\game</Filter> <Filter>Source Files\src\game</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\pc\network\packets\packet_level_warp_2.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\actors\common0.h"> <ClCompile Include="..\actors\common0.h">

View File

@ -18,9 +18,9 @@ fi
#exit #exit
# no debug, direct # no debug, direct
#$FILE --server 27015 --configfile sm64config_server.txt & $FILE --server 27015 --configfile sm64config_server.txt &
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & $FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
#exit exit
# debug on server # debug on server
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt & #$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &

View File

@ -12,26 +12,6 @@ if [ ! -f "$FILE" ]; then
FILE=./build/us_pc/sm64.us.f3dex2e FILE=./build/us_pc/sm64.us.f3dex2e
fi fi
# no debug, discord
#$FILE --discord 2 --configfile sm64config_server.txt &
#$FILE --discord 1 --configfile sm64config_client.txt &
#exit
# no debug, direct
#$FILE --server 27015 --configfile sm64config_server.txt &
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
#exit
# debug on server
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_server.txt' -ex 'quit'
#exit
###################
# debug on client #
###################
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_p1.txt' -ex 'quit'
$FILE --server 27015 --configfile sm64config_p1.txt & $FILE --server 27015 --configfile sm64config_p1.txt &
sleep 2 sleep 2
$FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt & $FILE --client 127.0.0.1 27015 --configfile sm64config_p2.txt &
@ -39,4 +19,7 @@ sleep 2
$FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt & $FILE --client 127.0.0.1 27015 --configfile sm64config_p3.txt &
sleep 2 sleep 2
$FILE --client 127.0.0.1 27015 --configfile sm64config_p4.txt & $FILE --client 127.0.0.1 27015 --configfile sm64config_p4.txt &
#sleep 2
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --server 27015 --configfile sm64config_p1.txt' -ex 'quit'
#winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p4.txt' -ex 'quit' #winpty cgdb $FILE -ex 'break debug_breakpoint_here' -ex 'run --client 127.0.0.1 27015 --configfile sm64config_p4.txt' -ex 'quit'

View File

@ -118,6 +118,11 @@
#define G_SPECIAL_2 0xd4 #define G_SPECIAL_2 0xd4
#define G_SPECIAL_3 0xd3 #define G_SPECIAL_3 0xd3
#ifdef F3DEX_GBI_2E
/* extended commands */
#define G_COPYMEM 0xd2
#endif
#define G_VTX 0x01 #define G_VTX 0x01
#define G_MODIFYVTX 0x02 #define G_MODIFYVTX 0x02
#define G_CULLDL 0x03 #define G_CULLDL 0x03
@ -1790,6 +1795,22 @@ typedef union {
(uintptr_t)(adrs) \ (uintptr_t)(adrs) \
}} }}
#ifdef F3DEX_GBI_2E
#define gCopyMemEXT(pkt, c, idx, dst, src, len) \
{ \
Gfx *_g = (Gfx *)(pkt); \
_g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL((src)/8,16,8)| \
_SHIFTL((dst)/8,8,8)|_SHIFTL((idx),0,8)); \
_g->words.w1 = (uintptr_t)(((len)-1)/8); \
}
#define gsCopyMemEXT(c, idx, dst, src, len) \
{{ \
(_SHIFTL((c),24,8)|_SHIFTL((src)/8,16,8)| \
_SHIFTL((dst)/8,8,8)|_SHIFTL((idx),0,8)), \
(uintptr_t)(((len)-1)/8) \
}}
#endif
#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0) #define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0)
#define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0) #define gsSPNoOp() gsDma0p(G_SPNOOP, 0, 0)
@ -2541,6 +2562,17 @@ typedef union {
gsDma1p( G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0) gsDma1p( G_MOVEMEM, l, sizeof(Light),((n)-1)*2+G_MV_L0)
#endif /* F3DEX_GBI_2 */ #endif /* F3DEX_GBI_2 */
/*
* EXTENDED COMMAND
* Copy one light's parameters to the other.
*/
#ifdef F3DEX_GBI_2E
# define gSPCopyLightEXT(pkt, dst, src) \
gCopyMemEXT((pkt),G_COPYMEM,G_MV_LIGHT,(dst)*24+24,(src)*24+24,sizeof(Light))
# define gsSPCopyLightEXT(dst, src) \
gsCopyMemEXT( G_COPYMEM,G_MV_LIGHT,(dst)*24+24,(src)*24+24,sizeof(Light))
#endif
/* /*
* gSPLightColor changes color of light without recalculating light direction * gSPLightColor changes color of light without recalculating light direction
* col is a 32 bit word with r,g,b,a (alpha is ignored) * col is a 32 bit word with r,g,b,a (alpha is ignored)

View File

@ -392,7 +392,7 @@ struct MarioState
// HOWEVER, simply increasing this to 3 will not magically work // HOWEVER, simply increasing this to 3 will not magically work
// many things will have to be overhauled! // many things will have to be overhauled!
#ifdef UNSTABLE_BRANCH #ifdef UNSTABLE_BRANCH
#define MAX_PLAYERS 4 #define MAX_PLAYERS 16
#else #else
#define MAX_PLAYERS 2 #define MAX_PLAYERS 2
#endif #endif

View File

@ -257,6 +257,15 @@ void load_area(s32 index) {
load_obj_warp_nodes(); load_obj_warp_nodes();
geo_call_global_function_nodes(&gCurrentArea->unk04->node, GEO_CONTEXT_AREA_LOAD); geo_call_global_function_nodes(&gCurrentArea->unk04->node, GEO_CONTEXT_AREA_LOAD);
} }
if (!network_is_warp_2_duplicate()) {
if (gNetworkType != NT_NONE) {
network_send_level_warp_2(TRUE, gNetworkPlayerLocal->globalIndex);
}
if (gNetworkType == NT_CLIENT) {
sCurrPlayMode = PLAY_MODE_SYNC_LEVEL;
}
}
} }
void unload_area(void) { void unload_area(void) {
@ -442,15 +451,8 @@ void render_game(void) {
} }
// only render 'synchronizing' text if we've been waiting for a while // only render 'synchronizing' text if we've been waiting for a while
static u8 syncLevelTime = 0;
if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) {
if (syncLevelTime < 30) { render_sync_level_screen();
syncLevelTime++;
} else {
render_sync_level_screen();
}
} else {
syncLevelTime = 0;
} }
D_8032CE74 = NULL; D_8032CE74 = NULL;

View File

@ -5,6 +5,7 @@
#include "chat.h" #include "chat.h"
#include "game_init.h" #include "game_init.h"
#include "ingame_menu.h" #include "ingame_menu.h"
#include "mario_misc.h"
#include "segment2.h" #include "segment2.h"
#include "gfx_dimensions.h" #include "gfx_dimensions.h"
#include "config.h" #include "config.h"
@ -23,6 +24,7 @@ struct ChatMessage {
u8 dialog[CHAT_DIALOG_MAX]; u8 dialog[CHAT_DIALOG_MAX];
enum ChatMessageType type; enum ChatMessageType type;
u16 life; u16 life;
u8 color[3];
}; };
static char inputMessage[CHAT_DIALOG_MAX] = { 0 }; static char inputMessage[CHAT_DIALOG_MAX] = { 0 };
@ -70,21 +72,34 @@ static void render_chat_message(struct ChatMessage* chatMessage, u8 index) {
u8 textR, textG, textB; u8 textR, textG, textB;
switch (chatMessage->type) { switch (chatMessage->type) {
case CMT_LOCAL: textR = 200; textG = 200; textB = 255; break; case CMT_LOCAL: textR = 200; textG = 200; textB = 255; break;
case CMT_INPUT: textR = 0; textG = 0; textB = 0; break; case CMT_INPUT: textR = 0; textG = 0; textB = 0; break;
case CMT_SYSTEM: textR = 255; textG = 255; textB = 190; break; case CMT_SYSTEM: textR = 255; textG = 255; textB = 190; break;
default: textR = 255; textG = 255; textB = 255; default: textR = 255; textG = 255; textB = 255; break;
} }
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
gDPSetEnvColor(gDisplayListHead++, textR, textG, textB, 255 * alphaScale); gDPSetEnvColor(gDisplayListHead++, textR, textG, textB, 255 * alphaScale);
print_generic_string(CHAT_X, CHAT_Y, chatMessage->dialog); print_generic_string(CHAT_X, CHAT_Y, chatMessage->dialog);
if (chatMessage->type == CMT_REMOTE || chatMessage->type == CMT_SYSTEM) {
// if it's someone else's message, highlight the icon with their color
u8 starR = chatMessage->color[0];
u8 starG = chatMessage->color[1];
u8 starB = chatMessage->color[2];
gDPSetEnvColor(gDisplayListHead++, starR, starG, starB, 255 * alphaScale);
create_dl_translation_matrix(MENU_MTX_PUSH, CHAT_X, CHAT_Y, 0.0f);
render_generic_char(chatMessage->dialog[0]);
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
gSPDisplayList(gDisplayListHead++, dl_ia_text_end); gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
} }
void chat_add_message(char* ascii, enum ChatMessageType chatMessageType) { void chat_add_message_ext(char* ascii, enum ChatMessageType chatMessageType, const u8 color[3]) {
u8 character = '?'; u8 character = '?';
switch (chatMessageType) { switch (chatMessageType) {
case CMT_INPUT: case CMT_INPUT:
@ -98,10 +113,18 @@ void chat_add_message(char* ascii, enum ChatMessageType chatMessageType) {
str_ascii_to_dialog(ascii, &msg->dialog[2], MIN(strlen(ascii), CHAT_DIALOG_MAX - 3)); str_ascii_to_dialog(ascii, &msg->dialog[2], MIN(strlen(ascii), CHAT_DIALOG_MAX - 3));
msg->life = (sSelectedFileNum != 0) ? CHAT_LIFE_MAX : CHAT_LIFE_MAX / 3; msg->life = (sSelectedFileNum != 0) ? CHAT_LIFE_MAX : CHAT_LIFE_MAX / 3;
msg->type = chatMessageType; msg->type = chatMessageType;
msg->color[0] = color[0];
msg->color[1] = color[1];
msg->color[2] = color[2];
onMessageIndex = (onMessageIndex + 1) % CHAT_MESSAGES_MAX; onMessageIndex = (onMessageIndex + 1) % CHAT_MESSAGES_MAX;
play_sound((msg->type == CMT_LOCAL) ? SOUND_MENU_MESSAGE_DISAPPEAR : SOUND_MENU_MESSAGE_APPEAR, gDefaultSoundArgs); play_sound((msg->type == CMT_LOCAL) ? SOUND_MENU_MESSAGE_DISAPPEAR : SOUND_MENU_MESSAGE_APPEAR, gDefaultSoundArgs);
} }
void chat_add_message(char* ascii, enum ChatMessageType chatMessageType) {
const u8 defaultColor[3] = { 255, 255, 255 };
chat_add_message_ext(ascii, chatMessageType, defaultColor);
}
static void chat_stop_input(void) { static void chat_stop_input(void) {
sInChatInput = FALSE; sInChatInput = FALSE;
keyboard_stop_text_input(); keyboard_stop_text_input();
@ -112,7 +135,8 @@ static void chat_send_input(void) {
keyboard_stop_text_input(); keyboard_stop_text_input();
if (strlen(gTextInput) == 0) { return; } if (strlen(gTextInput) == 0) { return; }
chat_add_message(gTextInput, CMT_LOCAL); chat_add_message(gTextInput, CMT_LOCAL);
network_send_chat(gTextInput); // our message has the same color as our shirt
network_send_chat(gTextInput, get_player_color(gNetworkPlayerLocal->globalIndex, 0));
} }
void chat_start_input(void) { void chat_start_input(void) {

View File

@ -10,6 +10,7 @@ enum ChatMessageType {
void render_chat(void); void render_chat(void);
void chat_add_message(char* ascii, enum ChatMessageType chatMessageType); void chat_add_message(char* ascii, enum ChatMessageType chatMessageType);
void chat_add_message_ext(char* ascii, enum ChatMessageType chatMessageType, const u8 color[3]);
void chat_start_input(void); void chat_start_input(void);
#endif #endif

View File

@ -53,6 +53,10 @@ u8 gControlledWarpGlobalIndex = 0;
extern s8 sReceivedLoadedActNum; extern s8 sReceivedLoadedActNum;
u8 gRejectInstantWarp = 0; u8 gRejectInstantWarp = 0;
s16 gChangeLevel = -1;
s16 gChangeAreaIndex = -1;
s16 gChangeActNum = -1;
#ifdef VERSION_JP #ifdef VERSION_JP
const char *credits01[] = { "1GAME DIRECTOR", "SHIGERU MIYAMOTO" }; const char *credits01[] = { "1GAME DIRECTOR", "SHIGERU MIYAMOTO" };
const char *credits02[] = { "2ASSISTANT DIRECTORS", "YOSHIAKI KOIZUMI", "TAKASHI TEZUKA" }; const char *credits02[] = { "2ASSISTANT DIRECTORS", "YOSHIAKI KOIZUMI", "TAKASHI TEZUKA" };
@ -1090,15 +1094,9 @@ s32 play_mode_normal(void) {
} }
} else if (!gReceiveWarp.received) { } else if (!gReceiveWarp.received) {
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) { if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) {
set_play_mode(PLAY_MODE_SYNC_LEVEL); set_play_mode(PLAY_MODE_CHANGE_LEVEL);
network_send_level_warp_begin();
} else if (sTransitionTimer != 0) { } else if (sTransitionTimer != 0) {
if (sWarpDest.type == WARP_TYPE_CHANGE_AREA) { set_play_mode(PLAY_MODE_CHANGE_AREA);
set_play_mode(PLAY_MODE_SYNC_LEVEL);
network_send_level_warp_begin();
} else {
set_play_mode(PLAY_MODE_CHANGE_AREA);
}
} else if (sCurrPlayMode == PLAY_MODE_NORMAL && pressed_pause()) { } else if (sCurrPlayMode == PLAY_MODE_NORMAL && pressed_pause()) {
lower_background_noise(1); lower_background_noise(1);
cancel_rumble(); cancel_rumble();
@ -1129,8 +1127,7 @@ s32 play_mode_paused(void) {
fade_into_special_warp(0, 0); fade_into_special_warp(0, 0);
gSavedCourseNum = COURSE_NONE; gSavedCourseNum = COURSE_NONE;
} }
set_play_mode(PLAY_MODE_SYNC_LEVEL); set_play_mode(PLAY_MODE_CHANGE_LEVEL);
network_send_level_warp_begin();
} else if (gPauseScreenMode == 3) { } else if (gPauseScreenMode == 3) {
// We should only be getting "int 3" to here // We should only be getting "int 3" to here
initiate_warp(LEVEL_CASTLE, 1, 0x1F, 0); initiate_warp(LEVEL_CASTLE, 1, 0x1F, 0);
@ -1150,7 +1147,7 @@ s32 play_mode_sync_level(void) {
set_menu_mode(-1); set_menu_mode(-1);
gCameraMovementFlags &= ~CAM_MOVE_PAUSE_SCREEN; gCameraMovementFlags &= ~CAM_MOVE_PAUSE_SCREEN;
check_received_warp(); //check_received_warp();
return 0; return 0;
} }
@ -1262,6 +1259,15 @@ static s32 play_mode_unused(void) {
s32 update_level(void) { s32 update_level(void) {
s32 changeLevel = 0; s32 changeLevel = 0;
if (gChangeLevel != -1) {
gHudDisplay.flags = HUD_DISPLAY_NONE;
sTransitionTimer = 0;
sTransitionUpdate = NULL;
changeLevel = gChangeLevel;
gChangeLevel = -1;
return changeLevel;
}
switch (sCurrPlayMode) { switch (sCurrPlayMode) {
case PLAY_MODE_NORMAL: case PLAY_MODE_NORMAL:
changeLevel = play_mode_normal(); changeLevel = play_mode_normal();

View File

@ -76,6 +76,10 @@ extern s16 sTransitionTimer;
extern void (*sTransitionUpdate)(s16 *); extern void (*sTransitionUpdate)(s16 *);
extern u8 unused3[4]; extern u8 unused3[4];
extern s16 gChangeLevel;
extern s16 gChangeAreaIndex;
extern s16 gChangeActNum;
struct WarpDest { struct WarpDest {
u8 type; u8 type;
u8 levelNum; u8 levelNum;

View File

@ -2123,7 +2123,7 @@ static void init_single_mario(struct MarioState* m) {
} }
// set mario/luigi model // set mario/luigi model
enum CharacterType characterType = (gNetworkPlayers[0].globalIndex == 1) ? CT_LUIGI : CT_MARIO; enum CharacterType characterType = (globalIndex == 0) ? CT_MARIO : CT_LUIGI;
m->character = &gCharacters[characterType]; m->character = &gCharacters[characterType];
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[m->character->modelId]; m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[m->character->modelId];
} }

View File

@ -23,6 +23,7 @@
#include "save_file.h" #include "save_file.h"
#include "skybox.h" #include "skybox.h"
#include "sound_init.h" #include "sound_init.h"
#include "pc/network/network.h"
#define TOAD_STAR_1_REQUIREMENT 12 #define TOAD_STAR_1_REQUIREMENT 12
#define TOAD_STAR_2_REQUIREMENT 25 #define TOAD_STAR_2_REQUIREMENT 25
@ -51,6 +52,11 @@ enum UnlockDoorStarStates {
UNLOCK_DOOR_STAR_DONE UNLOCK_DOOR_STAR_DONE
}; };
struct PlayerColor {
Lights1 shirt;
Lights1 pants;
};
/** /**
* The eye texture on succesive frames of Mario's blink animation. * The eye texture on succesive frames of Mario's blink animation.
* He intentionally blinks twice each time. * He intentionally blinks twice each time.
@ -72,12 +78,76 @@ static s8 gMarioAttackScaleAnimation[3 * 6] = {
struct MarioBodyState gBodyStates[MAX_PLAYERS]; struct MarioBodyState gBodyStates[MAX_PLAYERS];
struct GraphNodeObject gMirrorMario[MAX_PLAYERS]; // copy of Mario's geo node for drawing mirror Mario struct GraphNodeObject gMirrorMario[MAX_PLAYERS]; // copy of Mario's geo node for drawing mirror Mario
// ambient color is always half the diffuse color, so we can pull a macro
#define DEFINE_PLAYER_COLOR(sr, sg, sb, pr, pg, pb) \
{ \
gdSPDefLights1((sr >> 1), (sg >> 1), (sb >> 1), sr, sg, sb, 0x28, 0x28, 0x28), \
gdSPDefLights1((pr >> 1), (pg >> 1), (pb >> 1), pr, pg, pb, 0x28, 0x28, 0x28), \
}
struct PlayerColor gPlayerColors[] = {
// default mario
DEFINE_PLAYER_COLOR(0xff, 0x00, 0x00, /**/ 0x00, 0x00, 0xff),
// default luigi
DEFINE_PLAYER_COLOR(0x00, 0x98, 0x00, /**/ 0x00, 0x00, 0xfe),
#if MAX_PLAYERS > 2
// fake waluigi
DEFINE_PLAYER_COLOR(0x6d, 0x3c, 0x9a, /**/ 0x2c, 0x26, 0x3f),
// fake wario
DEFINE_PLAYER_COLOR(0xf9, 0xeb, 0x30, /**/ 0x7f, 0x20, 0x7a),
// light blue
DEFINE_PLAYER_COLOR(0x00, 0xdf, 0xff, /**/ 0x00, 0x00, 0xf0),
// sponge
DEFINE_PLAYER_COLOR(0xff, 0x7f, 0x00, /**/ 0x00, 0x7f, 0xa0),
// blue man group
DEFINE_PLAYER_COLOR(0x00, 0x00, 0xf0, /**/ 0x00, 0x00, 0x4f),
// thanks doc
DEFINE_PLAYER_COLOR(0xff, 0x00, 0xff, /**/ 0x00, 0xff, 0x00),
// white
DEFINE_PLAYER_COLOR(0xff, 0xff, 0xff, /**/ 0x10, 0x10, 0x10),
// grey
DEFINE_PLAYER_COLOR(0x6f, 0x6f, 0x6f, /**/ 0xe0, 0xe0, 0xe0),
#endif
};
static const size_t gNumPlayerColors = sizeof(gPlayerColors) / sizeof(*gPlayerColors);
// This whole file is weirdly organized. It has to be the same file due // This whole file is weirdly organized. It has to be the same file due
// to rodata boundaries and function aligns, which means the programmer // to rodata boundaries and function aligns, which means the programmer
// treated this like a "misc" file for vaguely Mario related things // treated this like a "misc" file for vaguely Mario related things
// (message NPC related things, the Mario head geo, and Mario geo // (message NPC related things, the Mario head geo, and Mario geo
// functions) // functions)
/**
* Set the Light1 struct from player colors.
* The 4th component is the shade factor (difference between ambient and diffuse),
* usually set to 1.
*/
void set_player_colors(u8 globalIndex, const u8 shirt[4], const u8 pants[4]) {
// choose the last color in the table for extra players
if (globalIndex >= gNumPlayerColors) globalIndex = gNumPlayerColors - 1;
const u8 pAmb[3] = { pants[0] >> pants[4], pants[1] >> pants[4], pants[2] >> pants[4] };
const u8 sAmb[3] = { shirt[0] >> shirt[4], shirt[1] >> shirt[4], shirt[2] >> shirt[4] };
gPlayerColors[globalIndex].pants =
(Lights1) gdSPDefLights1(pAmb[0], pAmb[1], pAmb[2], pants[0], pants[1], pants[2], 0x28, 0x28, 0x28);
gPlayerColors[globalIndex].shirt =
(Lights1) gdSPDefLights1(sAmb[0], sAmb[1], sAmb[2], shirt[0], shirt[1], shirt[2], 0x28, 0x28, 0x28);
}
/**
* Return the specified color for player globalIndex.
* 0 = shirt, 1 = pants
* Returns RGB, not RGBA!
*/
u8 *get_player_color(u8 globalIndex, const int which) {
// choose the last color in the table for extra players
if (globalIndex >= gNumPlayerColors) globalIndex = gNumPlayerColors - 1;
if (which == 0)
return gPlayerColors[globalIndex].shirt.l[0].l.col;
else
return gPlayerColors[globalIndex].pants.l[0].l.col;
}
/** /**
* Geo node script that draws Mario's head on the title screen. * Geo node script that draws Mario's head on the title screen.
*/ */
@ -405,7 +475,8 @@ Gfx* geo_switch_mario_eyes(s32 callContext, struct GraphNode* node, UNUSED Mat4*
Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) { Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) {
Mat4 * curTransform = mtx; Mat4 * curTransform = mtx;
struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node; struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node;
struct MarioBodyState* bodyState = geo_get_body_state(); u8 plrIdx = geo_get_processing_object_index();
struct MarioBodyState* bodyState = &gBodyStates[plrIdx];
s32 action = bodyState->action; s32 action = bodyState->action;
if (callContext == GEO_CONTEXT_RENDER) { if (callContext == GEO_CONTEXT_RENDER) {
@ -418,6 +489,11 @@ Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) {
rotNode->rotation[0] = bodyState->torsoAngle[1]; rotNode->rotation[0] = bodyState->torsoAngle[1];
rotNode->rotation[1] = bodyState->torsoAngle[2]; rotNode->rotation[1] = bodyState->torsoAngle[2];
rotNode->rotation[2] = bodyState->torsoAngle[0]; rotNode->rotation[2] = bodyState->torsoAngle[0];
if (plrIdx != 0) {
// only interpolate angles for the local player
vec3s_copy(rotNode->prevRotation, rotNode->rotation);
rotNode->prevTimestamp = gGlobalTimer;
}
// update torso position in bodyState // update torso position in bodyState
get_pos_from_transform_mtx(bodyState->torsoPos, *curTransform, *gCurGraphNodeCamera->matrixPtr); get_pos_from_transform_mtx(bodyState->torsoPos, *curTransform, *gCurGraphNodeCamera->matrixPtr);
} }
@ -429,7 +505,8 @@ Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) {
*/ */
Gfx* geo_mario_head_rotation(s32 callContext, struct GraphNode* node, UNUSED Mat4* c) { Gfx* geo_mario_head_rotation(s32 callContext, struct GraphNode* node, UNUSED Mat4* c) {
struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node; struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node;
struct MarioBodyState* bodyState = geo_get_body_state(); u8 plrIdx = geo_get_processing_object_index();
struct MarioBodyState* bodyState = &gBodyStates[plrIdx];
s32 action = bodyState->action; s32 action = bodyState->action;
if (callContext == GEO_CONTEXT_RENDER) { if (callContext == GEO_CONTEXT_RENDER) {
@ -449,6 +526,12 @@ Gfx* geo_mario_head_rotation(s32 callContext, struct GraphNode* node, UNUSED Mat
vec3s_set(bodyState->headAngle, 0, 0, 0); vec3s_set(bodyState->headAngle, 0, 0, 0);
vec3s_set(rotNode->rotation, 0, 0, 0); vec3s_set(rotNode->rotation, 0, 0, 0);
} }
if (plrIdx != 0) {
// only interpolate angles for the local player
vec3s_copy(rotNode->prevRotation, rotNode->rotation);
rotNode->prevTimestamp = gGlobalTimer;
}
} }
return NULL; return NULL;
} }
@ -707,4 +790,32 @@ Gfx* geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode* node,
asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8); asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8);
} }
return gfx; return gfx;
} }
/**
* Generate DL that sets player color depending on player number.
*/
Gfx* geo_mario_set_player_colors(s32 callContext, struct GraphNode* node, UNUSED Mat4* c) {
struct GraphNodeGenerated* asGenerated = (struct GraphNodeGenerated*) node;
Gfx* gfx = NULL;
u8 index = geo_get_processing_object_index();
u8 colorIndex = gNetworkPlayers[index].globalIndex;
struct MarioBodyState* bodyState = &gBodyStates[index];
if (callContext == GEO_CONTEXT_RENDER) {
// extra players get last color
if (colorIndex >= gNumPlayerColors) colorIndex = gNumPlayerColors - 1;
gfx = alloc_display_list(5 * sizeof(*gfx));
// put the player colors into lights 3, 4, 5, 6
// they will be later copied to lights 1, 2 with gsSPCopyLightEXT
gSPLight(gfx + 0, &gPlayerColors[colorIndex].pants.l, 3);
gSPLight(gfx + 1, &gPlayerColors[colorIndex].pants.a, 4);
gSPLight(gfx + 2, &gPlayerColors[colorIndex].shirt.l, 5);
gSPLight(gfx + 3, &gPlayerColors[colorIndex].shirt.a, 6);
gSPEndDisplayList(gfx + 4);
// put on transparent layer if vanish effect, opaque otherwise
const u32 layer = ((bodyState->modelState >> 8) & 1) ? LAYER_TRANSPARENT : LAYER_OPAQUE;
asGenerated->fnNode.node.flags = (asGenerated->fnNode.node.flags & 0xFF) | (layer << 8);
}
return gfx;
}

View File

@ -9,6 +9,9 @@
extern struct GraphNodeObject gMirrorMario[MAX_PLAYERS]; extern struct GraphNodeObject gMirrorMario[MAX_PLAYERS];
extern struct MarioBodyState gBodyStates[MAX_PLAYERS]; extern struct MarioBodyState gBodyStates[MAX_PLAYERS];
void set_player_colors(u8 globalIndex, const u8 shirt[4], const u8 pants[4]);
u8 *get_player_color(u8 globalIndex, const int which);
Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *c); Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *c);
void bhv_toad_message_loop(void); void bhv_toad_message_loop(void);
void bhv_toad_message_init(void); void bhv_toad_message_init(void);
@ -27,5 +30,6 @@ Gfx *geo_mario_rotate_wing_cap_wings(s32 callContext, struct GraphNode *node, UN
Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 *mtx); Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 *mtx);
Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); Gfx *geo_render_mirror_mario(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
Gfx *geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c); Gfx *geo_mirror_mario_backface_culling(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
Gfx *geo_mario_set_player_colors(s32 callContext, struct GraphNode *node, UNUSED Mat4 *c);
#endif // MARIO_MISC_H #endif // MARIO_MISC_H

View File

@ -47,7 +47,7 @@
#define RATIO_Y (gfx_current_dimensions.height / (2.0f * HALF_SCREEN_HEIGHT)) #define RATIO_Y (gfx_current_dimensions.height / (2.0f * HALF_SCREEN_HEIGHT))
#define MAX_BUFFERED 256 #define MAX_BUFFERED 256
#define MAX_LIGHTS 2 #define MAX_LIGHTS 8
#define MAX_VERTICES 64 #define MAX_VERTICES 64
#ifdef EXTERNAL_DATA #ifdef EXTERNAL_DATA
@ -1123,6 +1123,10 @@ static void gfx_sp_movemem(uint8_t index, uint8_t offset, const void* data) {
case G_MV_L0: case G_MV_L0:
case G_MV_L1: case G_MV_L1:
case G_MV_L2: case G_MV_L2:
case G_MV_L3:
case G_MV_L4:
case G_MV_L5:
case G_MV_L6:
// NOTE: reads out of bounds if it is an ambient light // NOTE: reads out of bounds if it is an ambient light
memcpy(rsp.current_lights + (index - G_MV_L0) / 2, data, sizeof(Light_t)); memcpy(rsp.current_lights + (index - G_MV_L0) / 2, data, sizeof(Light_t));
break; break;
@ -1130,6 +1134,18 @@ static void gfx_sp_movemem(uint8_t index, uint8_t offset, const void* data) {
} }
} }
#ifdef F3DEX_GBI_2E
static void gfx_sp_copymem(uint8_t idx, uint8_t dstofs, uint8_t srcofs, uint8_t words) {
if (idx == G_MV_LIGHT) {
const int srcidx = srcofs / 24 - 2;
const int dstidx = dstofs / 24 - 2;
if (srcidx <= MAX_LIGHTS && dstidx <= MAX_LIGHTS) {
memcpy(rsp.current_lights + dstidx, rsp.current_lights + srcidx, sizeof(Light_t));
}
}
}
#endif
static void gfx_sp_moveword(uint8_t index, uint16_t offset, uint32_t data) { static void gfx_sp_moveword(uint8_t index, uint16_t offset, uint32_t data) {
switch (index) { switch (index) {
case G_MW_NUMLIGHT: case G_MW_NUMLIGHT:
@ -1538,6 +1554,11 @@ static void gfx_run_dl(Gfx* cmd) {
gfx_sp_moveword(C0(0, 8), C0(8, 16), cmd->words.w1); gfx_sp_moveword(C0(0, 8), C0(8, 16), cmd->words.w1);
#endif #endif
break; break;
#ifdef F3DEX_GBI_2E
case (uint8_t)G_COPYMEM:
gfx_sp_copymem(C0(0, 8), C0(8, 8) * 8, C0(16, 8) * 8, C1(0, 8));
break;
#endif
case (uint8_t)G_TEXTURE: case (uint8_t)G_TEXTURE:
#ifdef F3DEX_GBI_2 #ifdef F3DEX_GBI_2
gfx_sp_texture(C1(16, 16), C1(0, 16), C0(11, 3), C0(8, 3), C0(1, 7)); gfx_sp_texture(C1(16, 16), C1(0, 16), C0(11, 3), C0(8, 3), C0(1, 7));

View File

@ -18,7 +18,7 @@ static void on_lobby_create_callback(UNUSED void* data, enum EDiscordResult resu
gCurActivity.type = DiscordActivityType_Playing; gCurActivity.type = DiscordActivityType_Playing;
snprintf(gCurActivity.party.id, 128, "%lld", lobby->id); snprintf(gCurActivity.party.id, 128, "%lld", lobby->id);
gCurActivity.party.size.current_size = 1; gCurActivity.party.size.current_size = 1;
gCurActivity.party.size.max_size = 2; gCurActivity.party.size.max_size = MAX_PLAYERS;
char secretJoin[128] = ""; char secretJoin[128] = "";
snprintf(secretJoin, 128, "%lld:%s", lobby->id, lobby->secret); snprintf(secretJoin, 128, "%lld:%s", lobby->id, lobby->secret);
@ -59,7 +59,7 @@ void discord_lobby_create(void) {
struct IDiscordLobbyTransaction* txn = { 0 }; struct IDiscordLobbyTransaction* txn = { 0 };
DISCORD_REQUIRE(app.lobbies->get_lobby_create_transaction(app.lobbies, &txn)); DISCORD_REQUIRE(app.lobbies->get_lobby_create_transaction(app.lobbies, &txn));
txn->set_capacity(txn, 2); txn->set_capacity(txn, MAX_PLAYERS);
txn->set_type(txn, DiscordLobbyType_Public); txn->set_type(txn, DiscordLobbyType_Public);
//txn->set_metadata(txn, "a", "123"); //txn->set_metadata(txn, "a", "123");
@ -94,4 +94,4 @@ struct IDiscordLobbyEvents* discord_lobby_initialize(void) {
events.on_member_disconnect = on_member_disconnect; events.on_member_disconnect = on_member_disconnect;
events.on_network_message = discord_network_on_message; events.on_network_message = discord_network_on_message;
return &events; return &events;
} }

View File

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include "network_player.h" #include "network_player.h"
#include "game/chat.h" #include "game/chat.h"
#include "game/mario_misc.h"
#include "pc/debuglog.h" #include "pc/debuglog.h"
struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 }; struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 };
@ -105,7 +106,7 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
gNetworkSystem->save_id(i); gNetworkSystem->save_id(i);
for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; }
if (type == NPT_SERVER) { gNetworkPlayerServer = np; } if (type == NPT_SERVER) { gNetworkPlayerServer = np; }
else { chat_add_message("player connected", CMT_SYSTEM); } else { chat_add_message_ext("player connected", CMT_SYSTEM, get_player_color(np->globalIndex, 0)); }
LOG_INFO("player connected, local %d, global %d", i, np->globalIndex); LOG_INFO("player connected, local %d, global %d", i, np->globalIndex);
extern s16 sCurrPlayMode; extern s16 sCurrPlayMode;
if (gNetworkType == NT_SERVER && sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { if (gNetworkType == NT_SERVER && sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) {
@ -142,7 +143,7 @@ u8 network_player_disconnected(u8 globalIndex) {
gNetworkSystem->clear_id(i); gNetworkSystem->clear_id(i);
for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; } for (int j = 0; j < MAX_SYNC_OBJECTS; j++) { gSyncObjects[j].rxEventId[i] = 0; }
LOG_INFO("player disconnected, local %d, global %d", i, globalIndex); LOG_INFO("player disconnected, local %d, global %d", i, globalIndex);
chat_add_message("player disconnected", CMT_SYSTEM); chat_add_message_ext("player disconnected", CMT_SYSTEM, get_player_color(globalIndex, 0));
return i; return i;
} }
return UNKNOWN_GLOBAL_INDEX; return UNKNOWN_GLOBAL_INDEX;

View File

@ -56,6 +56,7 @@ void packet_receive(struct Packet* p) {
case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break; case PACKET_INSTANT_WARP: network_receive_instant_warp(p); break;
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break; case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
case PACKET_DEATH: network_receive_death(p); break; case PACKET_DEATH: network_receive_death(p); break;
case PACKET_LEVEL_WARP_2: network_receive_level_warp_2(p); break;
/// ///
case PACKET_CUSTOM: network_receive_custom(p); break; case PACKET_CUSTOM: network_receive_custom(p); break;
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]); default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);

View File

@ -33,6 +33,7 @@ enum PacketType {
PACKET_INSTANT_WARP, PACKET_INSTANT_WARP,
PACKET_NETWORK_PLAYERS, PACKET_NETWORK_PLAYERS,
PACKET_DEATH, PACKET_DEATH,
PACKET_LEVEL_WARP_2,
/// ///
PACKET_CUSTOM = 255, PACKET_CUSTOM = 255,
}; };
@ -140,7 +141,7 @@ void network_send_custom(u8 customId, bool reliable, bool levelAreaMustMatch, vo
void network_receive_custom(struct Packet* p); void network_receive_custom(struct Packet* p);
// packet_chat.c // packet_chat.c
void network_send_chat(char* message); void network_send_chat(char* message, u8 rgb[3]);
void network_receive_chat(struct Packet* p); void network_receive_chat(struct Packet* p);
// packet_kick.c // packet_kick.c
@ -171,4 +172,9 @@ void network_receive_network_players(struct Packet* p);
void network_send_death(void); void network_send_death(void);
void network_receive_death(struct Packet* p); void network_receive_death(struct Packet* p);
// packet_level_warp_2.c
void network_send_level_warp_2(u8 eventBegins, u8 controlledGlobalIndex);
void network_receive_level_warp_2(struct Packet* p);
u8 network_is_warp_2_duplicate(void);
#endif #endif

View File

@ -17,10 +17,11 @@ static void print_sync_object_table(void) {
} }
#endif #endif
void network_send_chat(char* message) { void network_send_chat(char* message, u8 rgb[3]) {
u16 messageLength = strlen(message); u16 messageLength = strlen(message);
struct Packet p; struct Packet p;
packet_init(&p, PACKET_CHAT, true, false); packet_init(&p, PACKET_CHAT, true, false);
packet_write(&p, rgb, 3 * sizeof(u8));
packet_write(&p, &messageLength, sizeof(u16)); packet_write(&p, &messageLength, sizeof(u16));
packet_write(&p, message, messageLength * sizeof(u8)); packet_write(&p, message, messageLength * sizeof(u8));
network_send(&p); network_send(&p);
@ -34,13 +35,15 @@ void network_send_chat(char* message) {
void network_receive_chat(struct Packet* p) { void network_receive_chat(struct Packet* p) {
u16 remoteMessageLength = 0; u16 remoteMessageLength = 0;
char remoteMessage[255] = { 0 }; char remoteMessage[255] = { 0 };
u8 rgb[3] = { 255, 255, 255};
packet_read(p, rgb, 3 * sizeof(u8));
packet_read(p, &remoteMessageLength, sizeof(u16)); packet_read(p, &remoteMessageLength, sizeof(u16));
if (remoteMessageLength > 255) { remoteMessageLength = 254; } if (remoteMessageLength > 255) { remoteMessageLength = 254; }
packet_read(p, &remoteMessage, remoteMessageLength * sizeof(u8)); packet_read(p, &remoteMessage, remoteMessageLength * sizeof(u8));
// add the message // add the message
chat_add_message(remoteMessage, CMT_REMOTE); chat_add_message_ext(remoteMessage, CMT_REMOTE, rgb);
LOG_INFO("rx chat: %s", remoteMessage); LOG_INFO("rx chat: %s", remoteMessage);
#ifdef DEVELOPMENT #ifdef DEVELOPMENT

View File

@ -0,0 +1,143 @@
#include "../network.h"
#include "game/level_update.h"
#include "game/object_list_processor.h"
//#define DISABLE_MODULE_LOG
#include "pc/debuglog.h"
#define SERVER_RETAIN_WARP_SECONDS 1
extern u8 gControlledWarpGlobalIndex;
extern float gPaintingMarioYEntry;
#pragma pack(1)
struct PacketLevelWarp2Data {
s16 levelNum;
s16 areaIndex;
s16 actNum;
u8 warpType;
u8 warpLevelNum;
u8 warpAreaIdx;
u8 warpNodeId;
u32 warpArg;
s8 inWarpCheckpoint;
s16 ttcSpeedSetting;
s16 D_80339EE0;
f32 paintingMarioYEntry;
u8 controlledWarpGlobalIndex;
};
struct PacketLevelWarp2Data sSavedLevelWarp2Data = { 0 };
static clock_t sSavedClockTime = 0;
static void populate_packet_data(struct PacketLevelWarp2Data* data) {
data->levelNum = gCurrLevelNum;
data->areaIndex = gCurrAreaIndex;
data->actNum = gCurrActNum;
data->warpType = sWarpDest.type;
data->warpLevelNum = sWarpDest.levelNum;
data->warpAreaIdx = sWarpDest.areaIdx;
data->warpNodeId = sWarpDest.nodeId;
data->warpArg = sWarpDest.arg;
data->inWarpCheckpoint = gInWarpCheckpoint;
data->ttcSpeedSetting = gTTCSpeedSetting;
data->D_80339EE0 = D_80339EE0;
data->paintingMarioYEntry = gPaintingMarioYEntry;
data->controlledWarpGlobalIndex = gControlledWarpGlobalIndex;
}
void network_send_level_warp_2(u8 eventBegins, u8 controlledGlobalIndex) {
struct PacketLevelWarp2Data data = { 0 };
if (eventBegins) {
gControlledWarpGlobalIndex = controlledGlobalIndex;
populate_packet_data(&data);
if (gNetworkType == NT_SERVER) {
sSavedLevelWarp2Data = data;
sSavedClockTime = clock();
}
} else {
data = sSavedLevelWarp2Data;
}
struct Packet p;
packet_init(&p, PACKET_LEVEL_WARP_2, true, false);
packet_write(&p, &data, sizeof(struct PacketLevelWarp2Data));
if (gNetworkType == NT_SERVER) {
network_send(&p);
} else {
network_send_to(gNetworkPlayerServer->localIndex, &p);
}
LOG_INFO("send warp: %d, %d, %d", gCurrLevelNum, gCurrAreaIndex, gCurrActNum);
}
static void do_warp(struct PacketLevelWarp2Data* data) {
if (gCurrLevelNum != data->levelNum ) { gChangeLevel = data->levelNum; }
sWarpDest.type = data->warpType;
sWarpDest.levelNum = data->warpLevelNum;
sWarpDest.areaIdx = data->warpAreaIdx;
sWarpDest.nodeId = data->warpNodeId;
sWarpDest.arg = data->warpArg;
gInWarpCheckpoint = data->inWarpCheckpoint;
gTTCSpeedSetting = data->ttcSpeedSetting;
D_80339EE0 = data->D_80339EE0;
gPaintingMarioYEntry = data->paintingMarioYEntry;
gControlledWarpGlobalIndex = data->controlledWarpGlobalIndex;
gCurrLevelNum = data->levelNum;
gCurrAreaIndex = data->areaIndex;
gCurrActNum = data->actNum;
LOG_INFO("do warp: %d, %d, %d", gCurrLevelNum, gCurrAreaIndex, gCurrActNum);
}
void network_receive_level_warp_2(struct Packet* p) {
struct PacketLevelWarp2Data remote = { 0 };
packet_read(p, &remote, sizeof(struct PacketLevelWarp2Data));
LOG_INFO("rx warp: %d, %d, %d", remote.levelNum, remote.areaIndex, remote.actNum);
u8 levelOrAreaDifference = (gCurrLevelNum != remote.levelNum) || (gCurrAreaIndex != remote.areaIndex);
if (gNetworkType == NT_SERVER) {
f32 elapsed = (clock() - sSavedClockTime) / (f32)CLOCKS_PER_SEC;
if (elapsed < SERVER_RETAIN_WARP_SECONDS || !levelOrAreaDifference) {
network_send_level_warp_2(FALSE, gNetworkPlayerLocal->globalIndex);
return;
}
}
if (levelOrAreaDifference) {
do_warp(&remote);
}
if (gNetworkType == NT_CLIENT) {
sSavedLevelWarp2Data = remote;
sSavedClockTime = clock();
}
if (gNetworkType == NT_SERVER) {
network_send_level_warp_2(TRUE, remote.controlledWarpGlobalIndex);
} else {
sCurrPlayMode = PLAY_MODE_NORMAL;
network_on_init_level();
}
}
u8 network_is_warp_2_duplicate(void) {
struct PacketLevelWarp2Data data = { 0 };
populate_packet_data(&data);
if (data.levelNum == 1 && data.areaIndex == 1) { return TRUE; }
if (gNetworkType == NT_SERVER) {
f32 elapsed = (clock() - sSavedClockTime) / (f32)CLOCKS_PER_SEC;
if (elapsed >= SERVER_RETAIN_WARP_SECONDS) { return FALSE; }
}
return (memcmp(&sSavedLevelWarp2Data, &data, sizeof(struct PacketLevelWarp2Data)) == 0);
}

View File

@ -10,6 +10,7 @@
#include "engine/surface_collision.h" #include "engine/surface_collision.h"
#include "game/object_list_processor.h" #include "game/object_list_processor.h"
#include "game/chat.h" #include "game/chat.h"
#include "game/mario_misc.h"
#include "pc/configfile.h" #include "pc/configfile.h"
#pragma pack(1) #pragma pack(1)
@ -336,7 +337,7 @@ void network_receive_player(struct Packet* p) {
// inform of player death // inform of player death
if (oldData.action != ACT_BUBBLED && data.action == ACT_BUBBLED) { if (oldData.action != ACT_BUBBLED && data.action == ACT_BUBBLED) {
chat_add_message("player died", CMT_SYSTEM); chat_add_message_ext("player died", CMT_SYSTEM, get_player_color(globalIndex, 0));
} }
// action changed, reset timer // action changed, reset timer
@ -345,7 +346,7 @@ void network_receive_player(struct Packet* p) {
} }
// set model // set model
enum CharacterType characterType = (np->globalIndex == 1) ? CT_LUIGI : CT_MARIO; enum CharacterType characterType = (np->globalIndex == 0) ? CT_MARIO : CT_LUIGI;
m->character = &gCharacters[characterType]; m->character = &gCharacters[characterType];
m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[m->character->modelId]; m->marioObj->header.gfx.sharedChild = gLoadedGraphNodes[m->character->modelId];
} }

View File

@ -27,6 +27,17 @@ SOCKET socket_initialize(void) {
return INVALID_SOCKET; return INVALID_SOCKET;
} }
#if MAX_PLAYERS > 4
// on windows, the send buffer for the socket needs to be increased
// for the many players case to avoid WSAEWOULDBLOCK on send
// not actually sure this is the "proper" way to fix it
int bufsiz = 128 * 1024; // 128kb, default is apparently 8kb or 16kb
rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (const char *)&bufsiz, sizeof(bufsiz));
if (rc != NO_ERROR) {
LOG_ERROR("setsockopt(SO_SNDBUF) failed with error: %d", rc);
}
#endif
return sock; return sock;
} }

View File

@ -2,7 +2,7 @@
#define VERSION_H #define VERSION_H
#define UNSTABLE_BRANCH #define UNSTABLE_BRANCH
#define VERSION_NUMBER 2 #define VERSION_NUMBER 3
#define MAX_VERSION_LENGTH 10 #define MAX_VERSION_LENGTH 10
char* get_version(void); char* get_version(void);