Improve lag compensation

This commit is contained in:
MysterD 2023-04-03 13:55:03 -07:00
parent 3d13b893aa
commit fce88728d2
15 changed files with 282 additions and 219 deletions

View file

@ -37,6 +37,7 @@ in_files = [
"src/game/sound_init.h", "src/game/sound_init.h",
"src/pc/djui/djui_hud_utils.h", "src/pc/djui/djui_hud_utils.h",
"src/pc/network/network_player.h", "src/pc/network/network_player.h",
"src/pc/network/lag_compensation.h",
"include/behavior_table.h", "include/behavior_table.h",
"src/pc/lua/utils/smlua_obj_utils.h", "src/pc/lua/utils/smlua_obj_utils.h",
"src/pc/lua/utils/smlua_misc_utils.h", "src/pc/lua/utils/smlua_misc_utils.h",

View file

@ -4010,6 +4010,22 @@ function take_damage_and_knock_back(m, o)
-- ... -- ...
end end
--- @return nil
function lag_compensation_clear()
-- ...
end
--- @param otherNp NetworkPlayer
--- @return MarioState
function lag_compensation_get_local_state(otherNp)
-- ...
end
--- @return nil
function lag_compensation_store()
-- ...
end
--- @param courseNum integer --- @param courseNum integer
--- @param levelNum integer --- @param levelNum integer
--- @param areaIndex integer --- @param areaIndex integer
@ -5614,17 +5630,6 @@ function network_player_from_global_index(globalIndex)
-- ... -- ...
end end
--- @return nil
function network_player_local_restore_lag_state()
-- ...
end
--- @param otherNp NetworkPlayer
--- @return nil
function network_player_local_set_lag_state(otherNp)
-- ...
end
--- @param np NetworkPlayer --- @param np NetworkPlayer
--- @param part PlayerParts --- @param part PlayerParts
--- @param out Color --- @param out Color

View file

@ -21,7 +21,7 @@ const f32 font_normal_widths[] = {
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */ /* a b c d e f g h i j k l m n o p q r s t u v w x y z */
0.3000f, 0.3125f, 0.3125f, 0.3125f, 0.3125f, 0.3000f, 0.3750f, 0.3125f, 0.2200f, 0.3125f, 0.3125f, 0.1700f, 0.4350f, 0.3125f, 0.3000f, 0.3000f, 0.3125f, 0.2700f, 0.3125f, 0.3125f, 0.3125f, 0.2750f, 0.4375f, 0.3750f, 0.3125f, 0.3125f, 0.3000f, 0.3125f, 0.3125f, 0.3125f, 0.3125f, 0.3000f, 0.3750f, 0.3125f, 0.2200f, 0.3125f, 0.3125f, 0.1700f, 0.4350f, 0.3125f, 0.3000f, 0.3000f, 0.3125f, 0.2700f, 0.3125f, 0.3125f, 0.3125f, 0.2750f, 0.4375f, 0.3750f, 0.3125f, 0.3125f,
/* { | } ~ DEL */ /* { | } ~ DEL */
0.3125f, 0.2500f, 0.3125f, 0.5000f, 0.2000f, 0.3125f, 0.2500f, 0.3125f, 0.5000f, 0.3125f,
}; };
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////

View file

@ -3299,6 +3299,68 @@
<br /> <br />
---
# functions from lag_compensation.h
<br />
## [lag_compensation_clear](#lag_compensation_clear)
### Lua Example
`lag_compensation_clear()`
### Parameters
- None
### Returns
- None
### C Prototype
`void lag_compensation_clear(void);`
[:arrow_up_small:](#)
<br />
## [lag_compensation_get_local_state](#lag_compensation_get_local_state)
### Lua Example
`local MarioStateValue = lag_compensation_get_local_state(otherNp)`
### Parameters
| Field | Type |
| ----- | ---- |
| otherNp | [NetworkPlayer](structs.md#NetworkPlayer) |
### Returns
[MarioState](structs.md#MarioState)
### C Prototype
`struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp);`
[:arrow_up_small:](#)
<br />
## [lag_compensation_store](#lag_compensation_store)
### Lua Example
`lag_compensation_store()`
### Parameters
- None
### Returns
- None
### C Prototype
`void lag_compensation_store(void);`
[:arrow_up_small:](#)
<br />
--- ---
# functions from level_info.h # functions from level_info.h
@ -8186,44 +8248,6 @@
<br /> <br />
## [network_player_local_restore_lag_state](#network_player_local_restore_lag_state)
### Lua Example
`network_player_local_restore_lag_state()`
### Parameters
- None
### Returns
- None
### C Prototype
`void network_player_local_restore_lag_state(void);`
[:arrow_up_small:](#)
<br />
## [network_player_local_set_lag_state](#network_player_local_set_lag_state)
### Lua Example
`network_player_local_set_lag_state(otherNp)`
### Parameters
| Field | Type |
| ----- | ---- |
| otherNp | [NetworkPlayer](structs.md#NetworkPlayer) |
### Returns
- None
### C Prototype
`void network_player_local_set_lag_state(struct NetworkPlayer* otherNp);`
[:arrow_up_small:](#)
<br />
## [network_player_palette_to_color](#network_player_palette_to_color) ## [network_player_palette_to_color](#network_player_palette_to_color)
### Lua Example ### Lua Example

View file

@ -792,6 +792,13 @@
<br /> <br />
- lag_compensation.h
- [lag_compensation_clear](functions-3.md#lag_compensation_clear)
- [lag_compensation_get_local_state](functions-3.md#lag_compensation_get_local_state)
- [lag_compensation_store](functions-3.md#lag_compensation_store)
<br />
- level_info.h - level_info.h
- [get_level_name](functions-3.md#get_level_name) - [get_level_name](functions-3.md#get_level_name)
- [get_level_name_ascii](functions-3.md#get_level_name_ascii) - [get_level_name_ascii](functions-3.md#get_level_name_ascii)
@ -1085,8 +1092,6 @@
- [network_player_color_to_palette](functions-3.md#network_player_color_to_palette) - [network_player_color_to_palette](functions-3.md#network_player_color_to_palette)
- [network_player_connected_count](functions-3.md#network_player_connected_count) - [network_player_connected_count](functions-3.md#network_player_connected_count)
- [network_player_from_global_index](functions-3.md#network_player_from_global_index) - [network_player_from_global_index](functions-3.md#network_player_from_global_index)
- [network_player_local_restore_lag_state](functions-3.md#network_player_local_restore_lag_state)
- [network_player_local_set_lag_state](functions-3.md#network_player_local_set_lag_state)
- [network_player_palette_to_color](functions-3.md#network_player_palette_to_color) - [network_player_palette_to_color](functions-3.md#network_player_palette_to_color)
- [network_player_set_description](functions-3.md#network_player_set_description) - [network_player_set_description](functions-3.md#network_player_set_description)

View file

@ -105,49 +105,46 @@ function mario_local_hammer_check(m)
-- check for hammer attacks -- check for hammer attacks
for i = 1, (MAX_PLAYERS - 1) do for i = 1, (MAX_PLAYERS - 1) do
local m2 = gMarioStates[i] local mattacker = gMarioStates[i]
local np2 = gNetworkPlayers[i] local npattacker = gNetworkPlayers[i]
local s2 = gPlayerSyncTable[i] local sattacker = gPlayerSyncTable[i]
if passes_pvp_interaction_checks(m2, m) ~= 0 then local cmvictim = lag_compensation_get_local_state(npattacker)
network_player_local_set_lag_state(np2)
if s2.item == ITEM_HAMMER and mario_hammer_is_attack(m2.action) and passes_pvp_interaction_checks(m2, m) ~= 0 and global_index_hurts_mario_state(np2.globalIndex, m) then
local pos = mario_hammer_position(m2)
local dist = vec3f_dist(pos, m.pos)
if dist <= 165 then
local yOffset = 100
if m2.action == ACT_JUMP_KICK then
yOffset = yOffset + 100
end
local vel = { if sattacker.item == ITEM_HAMMER and mario_hammer_is_attack(mattacker.action) and passes_pvp_interaction_checks(mattacker, cmvictim) ~= 0 and passes_pvp_interaction_checks(mattacker, m) ~= 0 and global_index_hurts_mario_state(npattacker.globalIndex, m) then
x = m.pos.x - m2.pos.x, local pos = mario_hammer_position(mattacker)
y = (m.pos.y + yOffset) - m2.pos.y, local dist = vec3f_dist(pos, cmvictim.pos)
z = m.pos.z - m2.pos.z, if dist <= 165 then
} local yOffset = 100
vec3f_normalize(vel) if mattacker.action == ACT_JUMP_KICK then
vec3f_mul(vel, 75 + 70 * (1 - mario_health_float(m))) yOffset = yOffset + 100
end
network_player_local_restore_lag_state() local vel = {
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0) x = cmvictim.pos.x - mattacker.pos.x,
m.invincTimer = 30 y = (cmvictim.pos.y + yOffset) - mattacker.pos.y,
m.knockbackTimer = 10 z = cmvictim.pos.z - mattacker.pos.z,
m.vel.x = vel.x }
m.vel.y = vel.y vec3f_normalize(vel)
m.vel.z = vel.z vec3f_mul(vel, 75 + 70 * (1 - mario_health_float(cmvictim)))
m.faceAngle.y = atan2s(vel.z, vel.x) + 0x8000
s2.ammo = s2.ammo - 1
send_arena_hammer_hit(np.globalIndex, np2.globalIndex) set_mario_action(m, ACT_BACKWARD_AIR_KB, 0)
e.lastDamagedByGlobal = np2.globalIndex m.invincTimer = 30
m.knockbackTimer = 10
m.vel.x = vel.x
m.vel.y = vel.y
m.vel.z = vel.z
m.faceAngle.y = atan2s(vel.z, vel.x) + 0x8000
sattacker.ammo = sattacker.ammo - 1
if m2.action == ACT_PUNCHING or m2.action == ACT_MOVE_PUNCHING or m2.action == ACT_GROUND_POUND then send_arena_hammer_hit(np.globalIndex, npattacker.globalIndex)
m.hurtCounter = 12 e.lastDamagedByGlobal = npattacker.globalIndex
else
m.hurtCounter = 8 if mattacker.action == ACT_PUNCHING or mattacker.action == ACT_MOVE_PUNCHING or mattacker.action == ACT_GROUND_POUND then
end m.hurtCounter = 12
else
m.hurtCounter = 8
end end
end end
network_player_local_restore_lag_state()
end end
end end

View file

@ -17,13 +17,15 @@ end
function bhv_arena_bobomb_intersects_player(obj, m, pos, radius) function bhv_arena_bobomb_intersects_player(obj, m, pos, radius)
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner) local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
network_player_local_set_lag_state(ownerNp) local cm = m
if m.playerIndex == 0 then
cm = lag_compensation_get_local_state(ownerNp)
end
local mPos1 = { x = m.pos.x, y = m.pos.y + 50, z = m.pos.z } local mPos1 = { x = cm.pos.x, y = cm.pos.y + 50, z = cm.pos.z }
local mPos2 = { x = m.pos.x, y = m.pos.y + 150, z = m.pos.z } local mPos2 = { x = cm.pos.x, y = cm.pos.y + 150, z = cm.pos.z }
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius) local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
network_player_local_restore_lag_state()
return ret return ret
end end

View file

@ -18,17 +18,17 @@ function bhv_arena_cannon_ball_init(obj)
end end
function bhv_arena_cannon_ball_intersects_local(obj, pos) function bhv_arena_cannon_ball_intersects_local(obj, pos)
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner) local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
network_player_local_set_lag_state(ownerNp) local cm = gMarioStates[0]
if gMarioStates[0].playerIndex == 0 then
cm = lag_compensation_get_local_state(ownerNp)
end
local m = gMarioStates[0] local mPos1 = { x = cm.pos.x, y = cm.pos.y + 50, z = cm.pos.z }
local mPos1 = { x = m.pos.x, y = m.pos.y + 50, z = m.pos.z } local mPos2 = { x = cm.pos.x, y = cm.pos.y + 150, z = cm.pos.z }
local mPos2 = { x = m.pos.x, y = m.pos.y + 150, z = m.pos.z }
local radius = clamp(obj.oArenaCannonBallSize * 250, 75, 250) local radius = clamp(obj.oArenaCannonBallSize * 250, 75, 250)
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius) local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
network_player_local_restore_lag_state()
return ret return ret
end end

View file

@ -389,6 +389,14 @@ void adjust_analog_stick(struct Controller *controller) {
controller->stickY *= 64 / controller->stickMag; controller->stickY *= 64 / controller->stickMag;
controller->stickMag = 64; controller->stickMag = 64;
} }
/*extern bool gDebugToggle;
if (gDebugToggle) {
controller->stickX = 64;
controller->stickY = 0;
controller->stickMag = 64;
}*/
} }
// if a demo sequence exists, this will run the demo // if a demo sequence exists, this will run the demo

View file

@ -29,6 +29,7 @@
#include "pc/configfile.h" #include "pc/configfile.h"
#include "pc/network/network.h" #include "pc/network/network.h"
#include "pc/network/lag_compensation.h"
#include "pc/lua/smlua_hooks.h" #include "pc/lua/smlua_hooks.h"
#include "pc/cheats.h" #include "pc/cheats.h"
@ -1412,39 +1413,38 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
// make sure it passes pvp checks before rollback // make sure it passes pvp checks before rollback
if (!passes_pvp_interaction_checks(attacker, victim)) { return FALSE; } if (!passes_pvp_interaction_checks(attacker, victim)) { return FALSE; }
// set my local player to the state I was in when they attacked // grab the lag compensation version of the victim
struct MarioState* cVictim = NULL;
if (victim->playerIndex == 0) { if (victim->playerIndex == 0) {
network_player_local_set_lag_state(&gNetworkPlayers[victim->playerIndex]); cVictim = lag_compensation_get_local_state(&gNetworkPlayers[attacker->playerIndex]);
} }
if (cVictim == NULL) { cVictim = victim; }
// make sure we overlap // make sure we overlap
f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f; f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f;
if (!detect_player_hitbox_overlap(attacker, victim, overlapScale)) { if (!detect_player_hitbox_overlap(attacker, cVictim, overlapScale)) {
network_player_local_restore_lag_state();
return FALSE; return FALSE;
} }
// see if it was an attack // see if it was an attack
u32 interaction = determine_interaction(attacker, victim->marioObj); u32 interaction = determine_interaction(attacker, cVictim->marioObj);
if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, victim)) { if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, cVictim)) {
network_player_local_restore_lag_state();
return FALSE; return FALSE;
} }
// call the lua hook // call the lua hook
bool allow = true; bool allow = true;
smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, attacker, victim, &allow); smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, attacker, cVictim, &allow);
if (!allow) { if (!allow) {
// Lua blocked the interaction // Lua blocked the interaction
network_player_local_restore_lag_state();
return FALSE; return FALSE;
} }
// determine if slide attack should be ignored // determine if slide attack should be ignored
if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(victim)) { if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(cVictim)) {
// determine the difference in velocities // determine the difference in velocities
Vec3f velDiff; Vec3f velDiff;
vec3f_dif(velDiff, attacker->vel, victim->vel); vec3f_dif(velDiff, attacker->vel, cVictim->vel);
if (attacker->action == ACT_SLIDE_KICK_SLIDE || attacker->action == ACT_SLIDE_KICK) { if (attacker->action == ACT_SLIDE_KICK_SLIDE || attacker->action == ACT_SLIDE_KICK) {
// if the difference vectors are not different enough, do not attack // if the difference vectors are not different enough, do not attack
@ -1455,14 +1455,9 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
} }
// if the victim is going faster, do not attack // if the victim is going faster, do not attack
if (vec3f_length(victim->vel) > vec3f_length(attacker->vel)) { return FALSE; } if (vec3f_length(cVictim->vel) > vec3f_length(attacker->vel)) { return FALSE; }
} }
// restore to current state
u32 victimAction = victim->action;
u32 victimFlags = victim->flags;
network_player_local_restore_lag_state();
// determine if ground pound should be ignored // determine if ground pound should be ignored
if (attacker->action == ACT_GROUND_POUND) { if (attacker->action == ACT_GROUND_POUND) {
// not moving down yet? // not moving down yet?
@ -1473,7 +1468,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
if (victim->playerIndex == 0) { if (victim->playerIndex == 0) {
victim->interactObj = attacker->marioObj; victim->interactObj = attacker->marioObj;
if (interaction & INT_KICK) { if (interaction & INT_KICK) {
if (victimAction == ACT_FIRST_PERSON) { if (victim->action == ACT_FIRST_PERSON) {
// without this branch, the player will be stuck in first person // without this branch, the player will be stuck in first person
raise_background_noise(2); raise_background_noise(2);
set_camera_mode(victim->area->camera, -1, 1); set_camera_mode(victim->area->camera, -1, 1);
@ -1481,7 +1476,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
} }
set_mario_action(victim, ACT_FREEFALL, 0); set_mario_action(victim, ACT_FREEFALL, 0);
} }
if (!(victimFlags & MARIO_METAL_CAP)) { if (!(victim->flags & MARIO_METAL_CAP)) {
attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction); attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction);
if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; } if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; }
} }
@ -2250,7 +2245,6 @@ void mario_process_interactions(struct MarioState *m) {
if (&gMarioStates[i] == m) { continue; } if (&gMarioStates[i] == m) { continue; }
interact_player_pvp(m, &gMarioStates[i]); interact_player_pvp(m, &gMarioStates[i]);
} }
network_player_local_restore_lag_state();
} }
if (m->invincTimer > 0 && !sDelayInvincTimer) { if (m->invincTimer > 0 && !sDelayInvincTimer) {

View file

@ -20,6 +20,7 @@
#include "src/game/sound_init.h" #include "src/game/sound_init.h"
#include "src/pc/djui/djui_hud_utils.h" #include "src/pc/djui/djui_hud_utils.h"
#include "src/pc/network/network_player.h" #include "src/pc/network/network_player.h"
#include "src/pc/network/lag_compensation.h"
#include "include/behavior_table.h" #include "include/behavior_table.h"
#include "src/pc/lua/utils/smlua_obj_utils.h" #include "src/pc/lua/utils/smlua_obj_utils.h"
#include "src/pc/lua/utils/smlua_misc_utils.h" #include "src/pc/lua/utils/smlua_misc_utils.h"
@ -12643,6 +12644,57 @@ int smlua_func_take_damage_and_knock_back(lua_State* L) {
return 1; return 1;
} }
////////////////////////
// lag_compensation.h //
////////////////////////
int smlua_func_lag_compensation_clear(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_clear", 0, top);
return 0;
}
lag_compensation_clear();
return 1;
}
int smlua_func_lag_compensation_get_local_state(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_get_local_state", 1, top);
return 0;
}
struct NetworkPlayer* otherNp = (struct NetworkPlayer*)smlua_to_cobject(L, 1, LOT_NETWORKPLAYER);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "lag_compensation_get_local_state"); return 0; }
smlua_push_object(L, LOT_MARIOSTATE, lag_compensation_get_local_state(otherNp));
return 1;
}
int smlua_func_lag_compensation_store(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_store", 0, top);
return 0;
}
lag_compensation_store();
return 1;
}
////////////////// //////////////////
// level_info.h // // level_info.h //
////////////////// //////////////////
@ -18659,38 +18711,6 @@ int smlua_func_network_player_from_global_index(lua_State* L) {
return 1; return 1;
} }
int smlua_func_network_player_local_restore_lag_state(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 0) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "network_player_local_restore_lag_state", 0, top);
return 0;
}
network_player_local_restore_lag_state();
return 1;
}
int smlua_func_network_player_local_set_lag_state(lua_State* L) {
if (L == NULL) { return 0; }
int top = lua_gettop(L);
if (top != 1) {
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "network_player_local_set_lag_state", 1, top);
return 0;
}
struct NetworkPlayer* otherNp = (struct NetworkPlayer*)smlua_to_cobject(L, 1, LOT_NETWORKPLAYER);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "network_player_local_set_lag_state"); return 0; }
network_player_local_set_lag_state(otherNp);
return 1;
}
int smlua_func_network_player_palette_to_color(lua_State* L) { int smlua_func_network_player_palette_to_color(lua_State* L) {
if (L == NULL) { return 0; } if (L == NULL) { return 0; }
@ -29910,6 +29930,11 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "passes_pvp_interaction_checks", smlua_func_passes_pvp_interaction_checks); smlua_bind_function(L, "passes_pvp_interaction_checks", smlua_func_passes_pvp_interaction_checks);
smlua_bind_function(L, "take_damage_and_knock_back", smlua_func_take_damage_and_knock_back); smlua_bind_function(L, "take_damage_and_knock_back", smlua_func_take_damage_and_knock_back);
// lag_compensation.h
smlua_bind_function(L, "lag_compensation_clear", smlua_func_lag_compensation_clear);
smlua_bind_function(L, "lag_compensation_get_local_state", smlua_func_lag_compensation_get_local_state);
smlua_bind_function(L, "lag_compensation_store", smlua_func_lag_compensation_store);
// level_info.h // level_info.h
smlua_bind_function(L, "get_level_name", smlua_func_get_level_name); smlua_bind_function(L, "get_level_name", smlua_func_get_level_name);
smlua_bind_function(L, "get_level_name_ascii", smlua_func_get_level_name_ascii); smlua_bind_function(L, "get_level_name_ascii", smlua_func_get_level_name_ascii);
@ -30174,8 +30199,6 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "network_player_color_to_palette", smlua_func_network_player_color_to_palette); smlua_bind_function(L, "network_player_color_to_palette", smlua_func_network_player_color_to_palette);
smlua_bind_function(L, "network_player_connected_count", smlua_func_network_player_connected_count); smlua_bind_function(L, "network_player_connected_count", smlua_func_network_player_connected_count);
smlua_bind_function(L, "network_player_from_global_index", smlua_func_network_player_from_global_index); smlua_bind_function(L, "network_player_from_global_index", smlua_func_network_player_from_global_index);
smlua_bind_function(L, "network_player_local_restore_lag_state", smlua_func_network_player_local_restore_lag_state);
smlua_bind_function(L, "network_player_local_set_lag_state", smlua_func_network_player_local_set_lag_state);
smlua_bind_function(L, "network_player_palette_to_color", smlua_func_network_player_palette_to_color); smlua_bind_function(L, "network_player_palette_to_color", smlua_func_network_player_palette_to_color);
smlua_bind_function(L, "network_player_set_description", smlua_func_network_player_set_description); smlua_bind_function(L, "network_player_set_description", smlua_func_network_player_set_description);

View file

@ -0,0 +1,59 @@
#include "types.h"
#include "network_player.h"
#include "lag_compensation.h"
#include "pc/debuglog.h"
#include "game/object_helpers.h"
#include "behavior_table.h"
#include "model_ids.h"
#define MAX_LOCAL_STATE_HISTORY 20
struct StateHistory {
struct MarioState m;
struct Object marioObj;
struct MarioBodyState bodyState;
};
static struct StateHistory sLocalStateHistory[MAX_LOCAL_STATE_HISTORY] = { 0 };
static bool sLocalStateHistoryReady = false;
static u32 sLocalStateHistoryIndex = 0;
void lag_compensation_clear(void) {
sLocalStateHistoryReady = false;
sLocalStateHistoryIndex = 0;
}
void lag_compensation_store(void) {
if (!gMarioStates[0].marioBodyState) { return; }
if (!gMarioStates[0].marioObj) { return; }
struct StateHistory* sh = &sLocalStateHistory[sLocalStateHistoryIndex];
memcpy(&sh->m, &gMarioStates[0], sizeof(struct MarioState));
memcpy(&sh->marioObj, gMarioStates[0].marioObj, sizeof(struct Object));
memcpy(&sh->bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
sh->m.marioObj = &sh->marioObj;
sh->m.marioBodyState = &sh->bodyState;
if (sLocalStateHistoryIndex + 1 >= MAX_LOCAL_STATE_HISTORY) {
sLocalStateHistoryReady = true;
}
sLocalStateHistoryIndex = (sLocalStateHistoryIndex + 1) % MAX_LOCAL_STATE_HISTORY;
}
struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp) {
if (!otherNp) { return NULL; }
if (gNetworkType == NT_NONE) { return NULL; }
if (!sLocalStateHistoryReady) { return NULL; }
s32 pingToTicks = (otherNp->ping / 1000.0f) * 30;
if (pingToTicks > (MAX_LOCAL_STATE_HISTORY-1)) {
pingToTicks = (MAX_LOCAL_STATE_HISTORY-1);
}
//LOG_INFO("Ping: %s :: %u :: %d", otherNp->name, otherNp->ping, pingToTicks);
if (pingToTicks == 0) { return NULL; }
s32 index = (s32)sLocalStateHistoryIndex - pingToTicks;
while (index < 0) { index += MAX_LOCAL_STATE_HISTORY; }
index = index % MAX_LOCAL_STATE_HISTORY;
return &sLocalStateHistory[index].m;
}

View file

@ -0,0 +1,8 @@
#ifndef NETWORK_LAG_COMPENSATION_H
#define NETWORK_LAG_COMPENSATION_H
void lag_compensation_clear(void);
void lag_compensation_store(void);
struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp);
#endif

View file

@ -10,32 +10,19 @@
#include "game/hardcoded.h" #include "game/hardcoded.h"
#include "game/object_helpers.h" #include "game/object_helpers.h"
#include "pc/lua/smlua_hooks.h" #include "pc/lua/smlua_hooks.h"
#include "lag_compensation.h"
struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 }; struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 };
struct NetworkPlayer *gNetworkPlayerLocal = NULL; struct NetworkPlayer *gNetworkPlayerLocal = NULL;
struct NetworkPlayer *gNetworkPlayerServer = NULL; struct NetworkPlayer *gNetworkPlayerServer = NULL;
static char sDefaultPlayerName[] = "Player"; static char sDefaultPlayerName[] = "Player";
#define MAX_LOCAL_PLAYER_STATES 20
struct LagState {
struct MarioState m;
struct MarioBodyState bodyState;
};
static struct LagState sLocalPlayerStates[MAX_LOCAL_PLAYER_STATES] = { 0 };
static struct LagState sLocalPlayerTmpState = { 0 };
static bool sLocalPlayerTmpStateSet = false;
static bool sLocalPlayerStatesReady = false;
static u32 sLocalPlayerStateIndex = 0;
void network_player_init(void) { void network_player_init(void) {
gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0; gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0;
gNetworkPlayers[0].palette = configPlayerPalette; gNetworkPlayers[0].palette = configPlayerPalette;
gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex; gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex;
gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette; gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette;
sLocalPlayerTmpStateSet = false; lag_compensation_clear();
sLocalPlayerStatesReady = false;
sLocalPlayerStateIndex = 0;
} }
void network_player_update_model(u8 localIndex) { void network_player_update_model(u8 localIndex) {
@ -160,55 +147,8 @@ void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts
out[2] = np->palette.parts[part][2]; out[2] = np->palette.parts[part][2];
} }
static void network_player_local_save_state(void) {
if (!gMarioStates[0].marioBodyState) { return; }
memcpy(&sLocalPlayerStates[sLocalPlayerStateIndex].m, &gMarioStates[0], sizeof(struct MarioState));
memcpy(&sLocalPlayerStates[sLocalPlayerStateIndex].bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
if (sLocalPlayerStateIndex + 1 >= MAX_LOCAL_PLAYER_STATES) {
sLocalPlayerStatesReady = true;
}
sLocalPlayerStateIndex = (sLocalPlayerStateIndex + 1) % MAX_LOCAL_PLAYER_STATES;
}
void network_player_local_set_lag_state(struct NetworkPlayer* otherNp) {
if (!otherNp) { return; }
if (gNetworkType == NT_NONE) { return; }
if (!sLocalPlayerStatesReady) { return; }
s32 pingToTicks = (otherNp->ping / 1000.0f) * 30;
pingToTicks += 2;
if (pingToTicks > (MAX_LOCAL_PLAYER_STATES-1)) {
pingToTicks = (MAX_LOCAL_PLAYER_STATES-1);
}
if (pingToTicks == 0) { return; }
s32 index = (s32)sLocalPlayerStateIndex - pingToTicks;
while (index < 0) { index += MAX_LOCAL_PLAYER_STATES; }
index = index % MAX_LOCAL_PLAYER_STATES;
memcpy(&sLocalPlayerTmpState.m, &gMarioStates[0], sizeof(struct MarioState));
memcpy(&sLocalPlayerTmpState.bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
memcpy(&gMarioStates[0], &sLocalPlayerStates[index].m, sizeof(struct MarioState));
memcpy(gMarioStates[0].marioBodyState, &sLocalPlayerStates[index].bodyState, sizeof(struct MarioBodyState));
sLocalPlayerTmpStateSet = true;
}
void network_player_local_restore_lag_state(void) {
if (!sLocalPlayerTmpStateSet) { return; }
memcpy(&gMarioStates[0], &sLocalPlayerTmpState.m, sizeof(struct MarioState));
memcpy(gMarioStates[0].marioBodyState, &sLocalPlayerTmpState.bodyState, sizeof(struct MarioBodyState));
sLocalPlayerTmpStateSet = false;
}
void network_player_update(void) { void network_player_update(void) {
network_player_local_save_state(); lag_compensation_store();
network_player_local_restore_lag_state();
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct NetworkPlayer *np = &gNetworkPlayers[i]; struct NetworkPlayer *np = &gNetworkPlayers[i];

View file

@ -79,9 +79,6 @@ struct NetworkPlayer* get_network_player_smallest_global(void);
void network_player_color_to_palette(struct NetworkPlayer *np, enum PlayerParts part, Color color); void network_player_color_to_palette(struct NetworkPlayer *np, enum PlayerParts part, Color color);
void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts part, Color out); void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts part, Color out);
void network_player_local_set_lag_state(struct NetworkPlayer* otherNp);
void network_player_local_restore_lag_state(void);
void network_player_update(void); void network_player_update(void);
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name); u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name);