Skip to content

Commit

Permalink
Fix multiple crashes related to netcode and others.
Browse files Browse the repository at this point in the history
- simulation receiver accessing predicted entropies out of range if the client falls back in simuating the game
- wrong std::optional access
- unset ids in arena mode gui
- wrong faction access
- wrong comparison operator (only debug)
  • Loading branch information
geneotech committed Jun 20, 2021
1 parent cd4046c commit 71b3442
Show file tree
Hide file tree
Showing 19 changed files with 109 additions and 60 deletions.
31 changes: 20 additions & 11 deletions src/application/network/simulation_receiver.h
Expand Up @@ -148,7 +148,7 @@ class simulation_receiver {
}

{
auto p_i = static_cast<std::size_t>(0);
auto num_total_accepted_entropies = static_cast<std::size_t>(0);

for (std::size_t i = 0; i < entropies.size(); ++i) {
/* If a new player was added, always reinfer. */
Expand Down Expand Up @@ -216,10 +216,20 @@ class simulation_receiver {

advance_referential(actual_server_entropy);

if (!repredict) {
const auto& predicted_server_entropy = predicted_entropies[p_i];
const bool already_found_reason_to_repredict = repredict;

if (shall_reinfer || !(actual_server_entropy == predicted_server_entropy)) {
if (!already_found_reason_to_repredict) {
if (num_total_accepted_entropies < predicted_entropies.size())
{
const auto& predicted_server_entropy = predicted_entropies[num_total_accepted_entropies];

if (shall_reinfer || !(actual_server_entropy == predicted_server_entropy)) {
repredict = true;
}
}
else
{
LOG("The client has fallen back behind the server. Repredicting the world just in case.");
repredict = true;
}
}
Expand All @@ -235,25 +245,24 @@ class simulation_receiver {
repredict = true;
}

p_i += num_accepted;
num_total_accepted_entropies += num_accepted;
}
}

erase_first_n(incoming_contexts, entropies.size());
entropies.clear();

const auto& total_accepted = p_i;
result.total_accepted = total_accepted;
result.total_accepted = num_total_accepted_entropies;

auto& predicted = predicted_entropies;

// LOG("TA: %x", total_accepted);
// LOG("TA: %x", num_total_accepted_entropies);

if (total_accepted <= predicted.size()) {
erase_first_n(predicted, total_accepted);
if (num_total_accepted_entropies <= predicted.size()) {
erase_first_n(predicted, num_total_accepted_entropies);
}
else {
LOG_NVPS(total_accepted, predicted.size());
LOG_NVPS(num_total_accepted_entropies, predicted.size());
result.malicious_server = true;
return result;
}
Expand Down
1 change: 1 addition & 0 deletions src/application/setups/client/client_setup.cpp
Expand Up @@ -1100,6 +1100,7 @@ bool client_setup::requires_cursor() const {
void client_setup::ensure_handler() {
wait_for_demo_flush();
flush_demo_steps();
wait_for_demo_flush();
}

void client_setup::wait_for_demo_flush() {
Expand Down
4 changes: 2 additions & 2 deletions src/application/setups/editor/gui/editor_pathed_asset_gui.cpp
Expand Up @@ -347,7 +347,7 @@ void editor_pathed_asset_gui<asset_id_type>::perform(
text_disabled(typesafe_sprintf("%x", resolved_path.string()));

if constexpr(is_image_type) {
const auto& entry = game_atlas.at(currently_viewed_entry->id).diffuse;
const auto& entry = game_atlas.find_or(currently_viewed_entry->id).diffuse;

const bool is_missing =
range_of_currently_viewed == std::addressof(missing_paths)
Expand Down Expand Up @@ -432,7 +432,7 @@ void editor_pathed_asset_gui<asset_id_type>::perform(
}

if constexpr(is_image_type) {
const auto& entry = game_atlas.at(id).diffuse;
const auto& entry = game_atlas.find_or(id).diffuse;

if (entry.exists()) {
if (ImGui::IsItemHovered()) {
Expand Down
Expand Up @@ -35,7 +35,7 @@ bool frames_prologue_widget::handle_prologue(const std::string&, plain_animation
const auto considered_time = std::fmod(total_time, total_duration);
const auto current_frame = ::calc_current_frame(anim, considered_time);

const auto& entry = game_atlas.at(current_frame->image_id);
const auto& entry = game_atlas.find_or(current_frame->image_id);

const auto is = vec2i(entry.get_original_size());

Expand Down
Expand Up @@ -49,7 +49,7 @@ struct image_color_picker_widget {

auto perform_widget = [&]() {
const auto zoom = 4;
const auto& entry = game_atlas.at(id).diffuse;
const auto& entry = game_atlas.find_or(id).diffuse;

if (const auto picked = image_color_picker(zoom, entry, current_preview.image)) {
object.emplace_back(*picked);
Expand Down Expand Up @@ -85,7 +85,7 @@ struct image_color_picker_widget {

auto perform_widget = [&]() {
const auto zoom = 4;
const auto& entry = game_atlas.at(id).diffuse;
const auto& entry = game_atlas.find_or(id).diffuse;

if (const auto picked = image_color_picker(zoom, entry, current_preview.image)) {
object = *picked;
Expand Down
Expand Up @@ -44,7 +44,7 @@ struct image_offset_widget {
auto iw = scoped_item_width(80);

auto perform_widget = [&]() {
const auto& entry = game_atlas.at(id);
const auto& entry = game_atlas.find_or(id);

const auto is = vec2i(entry.get_original_size());
const auto zoom = 4;
Expand Down
Expand Up @@ -42,7 +42,7 @@ struct non_standard_shape_widget {
object.clear();
}

const auto& entry = game_atlas.at(id);
const auto& entry = game_atlas.find_or(id);

const auto is = vec2i(entry.get_original_size());
const auto zoom = 4;
Expand Down
2 changes: 1 addition & 1 deletion src/game/detail/flavour_presentation.h
Expand Up @@ -117,7 +117,7 @@ ltrb aabb_of_game_image_with_attachments(
ltrb result;

auto get_entry = [&](const auto id) {
return images_in_atlas.at(id).diffuse;
return images_in_atlas.find_or(id).diffuse;
};

auto contain = [&](
Expand Down
4 changes: 2 additions & 2 deletions src/game/detail/physics/shape_overlapping.hpp
Expand Up @@ -56,7 +56,7 @@ auto shape_overlaps_entity(
si,
shape_transform,
fixture
); result->overlap) {
); result != std::nullopt && result->overlap) {
return result;
}

Expand Down Expand Up @@ -164,7 +164,7 @@ auto circular_sector_overlaps_entity(
&shape,
shape_transform,
handle
); result && result->overlap) {
); result != std::nullopt && result->overlap) {
return result;
}

Expand Down
17 changes: 17 additions & 0 deletions src/game/enums/faction_type.h
Expand Up @@ -29,11 +29,28 @@ struct per_actual_faction {
std::array<T, 3> items;
// END GEN INTROSPECTOR

static bool is_actual_faction(const faction_type t)
{
return t == faction_type::METROPOLIS || t == faction_type::ATLANTIS || t == faction_type::RESISTANCE;
}

T& operator[](const faction_type t) {
if (!is_actual_faction(t))
{
// Default to Atlantis
return items[static_cast<int>(faction_type::ATLANTIS) - 1];
}

return items[static_cast<int>(t) - 1];
}

const T& operator[](const faction_type t) const {
if (!is_actual_faction(t))
{
// Default to Atlantis
return items[static_cast<int>(faction_type::ATLANTIS) - 1];
}

return items[static_cast<int>(t) - 1];
}
};
40 changes: 17 additions & 23 deletions src/game/modes/bomb_defusal.cpp
Expand Up @@ -555,7 +555,7 @@ std::size_t bomb_defusal::num_players_in(const faction_type faction) const {
return total;
}

void bomb_defusal::assign_free_color_to_best_uncolored(const const_input_type in, const faction_type previous_faction, const rgba free_color) {
void bomb_defusal::assign_free_color_to_best_uncolored(const const_input_type in, const faction_type in_faction, const rgba free_color) {
const auto fallback_color = in.rules.excess_player_color;

if (free_color == rgba::zero) {
Expand All @@ -566,34 +566,28 @@ void bomb_defusal::assign_free_color_to_best_uncolored(const const_input_type in
return;
}

auto& best_uncolored_player_of_this_faction = maximum_of(
players,
[&](const auto& a, const auto& b) {
if (a.second.assigned_color != fallback_color) {
return true;
}
bool found_any_player = false;
int best_score = std::numeric_limits<int>::min();
mode_player_id best_player = mode_player_id();

if (b.second.assigned_color != fallback_color) {
return false;
}

if (a.second.get_faction() != previous_faction) {
return true;
}
for_each_player_in(in_faction, [&](const auto& mode_id, const auto& data) {
if (data.get_faction() == in_faction && data.assigned_color == fallback_color) {
const int score = data.stats.calc_score();

if (b.second.get_faction() != previous_faction) {
return false;
if (score > best_score || !found_any_player)
{
best_score = score;
best_player = mode_id;
found_any_player = true;
}

return a.second.stats.calc_score() < b.second.stats.calc_score();
}
);

auto& best = best_uncolored_player_of_this_faction.second;
return callback_result::CONTINUE;
});

if (best.assigned_color == fallback_color) {
if (best.get_faction() == previous_faction) {
best.assigned_color = free_color;
if (found_any_player) {
if (const auto entry = find(best_player)) {
entry->assigned_color = free_color;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/test_scenes/scenes/testbed.cpp
Expand Up @@ -208,6 +208,7 @@ namespace test_scenes {
rs.view.logos[faction_type::ATLANTIS] = to_image_id(test_scene_image_id::ATLANTIS_LOGO);
rs.view.logos[faction_type::RESISTANCE] = to_image_id(test_scene_image_id::RESISTANCE_LOGO);
rs.view.headshot_icons[faction_type::METROPOLIS] = to_image_id(test_scene_image_id::HEADSHOT_ICON);
rs.view.headshot_icons[faction_type::ATLANTIS] = to_image_id(test_scene_image_id::HEADSHOT_ICON);
rs.view.headshot_icons[faction_type::RESISTANCE] = to_image_id(test_scene_image_id::HEADSHOT_ICON);

rs.view.square_logos[faction_type::METROPOLIS] = to_image_id(test_scene_image_id::METROPOLIS_SQUARE_LOGO);
Expand Down
5 changes: 5 additions & 0 deletions src/view/audiovisual_state/systems/sound_system.cpp
Expand Up @@ -256,6 +256,11 @@ void sound_system::generic_sound_cache::update_properties(const update_propertie

const auto& cosm = listening_character.get_cosmos();
const auto maybe_transform = in.find_transform(positioning);

if (maybe_transform == std::nullopt)
{
return;
}

augs::update_multiple_properties cmd;

Expand Down
8 changes: 4 additions & 4 deletions src/view/mode_gui/arena/arena_buy_menu_gui.cpp
Expand Up @@ -38,7 +38,7 @@ void game_image_with_attachments(
const auto lt_offset = -precalculated_aabb.left_top();

auto get_entry = [&](const auto id) {
return images_in_atlas.at(id).diffuse;
return images_in_atlas.find_or(id).diffuse;
};

auto draw = [&](
Expand Down Expand Up @@ -212,7 +212,7 @@ result_type arena_buy_menu_gui::perform_imgui(const input_type in) {

centered_text(window_name);

if (const auto& entry = in.images_in_atlas.at(in.money_icon).diffuse; entry.exists()) {
if (const auto& entry = in.images_in_atlas.find_or(in.money_icon).diffuse; entry.exists()) {
game_image_button("#moneyicon", entry);
ImGui::SameLine();
}
Expand All @@ -231,7 +231,7 @@ result_type arena_buy_menu_gui::perform_imgui(const input_type in) {
};

auto draw_owned_weapon = [&](const item_flavour_id& f_id) {
if (const auto& entry = in.images_in_atlas.at(::image_of(cosm, f_id)).diffuse; entry.exists()) {
if (const auto& entry = in.images_in_atlas.find_or(::image_of(cosm, f_id)).diffuse; entry.exists()) {
const auto image_padding = vec2(0, 4);
const auto size = vec2(entry.get_original_size());
game_image(entry, size, white, image_padding);
Expand Down Expand Up @@ -381,7 +381,7 @@ result_type arena_buy_menu_gui::perform_imgui(const input_type in) {
const bool learnt = subject.template get<components::sentience>().is_learnt(s_id);

const auto image = ::get_spell_image(cosm, s_id);
const auto& entry = in.images_in_atlas.at(image).diffuse;
const auto& entry = in.images_in_atlas.find_or(image).diffuse;

if (!entry.exists()) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/view/mode_gui/arena/arena_choose_team_gui.cpp
Expand Up @@ -110,7 +110,7 @@ std::optional<mode_commands::team_choice> arena_choose_team_gui::perform_imgui(c
return augs::imgui::colors_nha::standard();
}();

const auto& entry = in.images_in_atlas.at(in.button_logos[f]).diffuse;
const auto& entry = in.images_in_atlas.find_or(in.button_logos[f]).diffuse;
const bool button_confirmed = entry.exists() && game_image_button(label, entry, color_scheme);

if (!is_full) {
Expand Down
9 changes: 5 additions & 4 deletions src/view/mode_gui/arena/arena_mode_gui.cpp
Expand Up @@ -39,7 +39,7 @@ void draw_weapon_flavour_with_attachments(
const auto& attachment_image,
const auto& attachment_offset
) {
const auto& entry = images_in_atlas.at(attachment_image).diffuse;
const auto& entry = images_in_atlas.find_or(attachment_image).diffuse;
const auto final_pos = lt_pos + lt_offset + attachment_offset.pos;

augs::detail_sprite(output_buffer, entry, final_pos, attachment_offset.rotation, white);
Expand Down Expand Up @@ -72,7 +72,8 @@ tool_layout_meta make_tool_layout(
using T = remove_cref<decltype(tool)>;

auto from_image = [&](const auto image_id) {
const auto& entry = images_in_atlas.at(image_id).diffuse;
//LOG_NVPS(image_id.get_cache_index(), static_cast<std::size_t>(image_id.get_cache_index()), images_in_atlas.size());
const auto& entry = images_in_atlas.find_or(image_id).diffuse;

auto meta = tool_layout_meta();

Expand Down Expand Up @@ -516,7 +517,7 @@ void arena_gui_state::draw_mode_gui(
return 0;
}();

const auto& avatar_atlas_entry = in.avatars_in_atlas.at(killer_player_id.value);
const auto avatar_atlas_entry = in.avatars_in_atlas.at(killer_player_id.value);
const bool avatars_enabled = logically_set(in.general_atlas, in.avatar_atlas);
const bool avatar_displayed = avatar_atlas_entry.exists() && avatars_enabled;

Expand Down Expand Up @@ -787,7 +788,7 @@ void arena_gui_state::draw_mode_gui(
const bool was_headshot = ko.origin.circumstances.headshot;
const auto headshot_icon = mode_input.rules.view.headshot_icons[ko.victim.faction];

const auto& headshot_entry = in.images_in_atlas.at(headshot_icon).diffuse;
const auto& headshot_entry = in.images_in_atlas.find_or(headshot_icon).diffuse;
const auto headshot_icon_size = was_headshot ? headshot_entry.get_original_size() : vec2u::zero;

const auto times_padded = was_headshot ? 3 : 2;
Expand Down
6 changes: 3 additions & 3 deletions src/view/mode_gui/arena/arena_scoreboard_gui.cpp
Expand Up @@ -343,7 +343,7 @@ void arena_scoreboard_gui::draw_gui(

if (sorted_players.size() > 0) {
if (const auto& head_image = mode_input.rules.view.logos[faction]; head_image.is_set()) {
if (const auto& entry = draw_in.images_in_atlas.at(head_image).diffuse; entry.exists()) {
if (const auto& entry = draw_in.images_in_atlas.find_or(head_image).diffuse; entry.exists()) {
const auto size = entry.get_original_size();
auto head_orig = ltrbi(vec2i::zero, size).place_in_center_of(faction_bg_orig);

Expand Down Expand Up @@ -554,7 +554,7 @@ void arena_scoreboard_gui::draw_gui(
if (icon != std::nullopt) {
const auto icon_image = mode_input.rules.view.icons.at(*icon);

if (const auto& entry = draw_in.images_in_atlas.at(icon_image).diffuse; entry.exists()) {
if (const auto& entry = draw_in.images_in_atlas.find_or(icon_image).diffuse; entry.exists()) {
const auto size = entry.get_original_size();

const auto& c = *current_column;
Expand Down Expand Up @@ -599,7 +599,7 @@ void arena_scoreboard_gui::draw_gui(
next_col();

if (avatars_enabled) {
if (const auto& entry = in.avatars_in_atlas.at(player_id.value); entry.exists()) {
if (const auto entry = in.avatars_in_atlas.at(player_id.value); entry.exists()) {
const auto& c = *current_column;
const auto& cell_orig = ltrbi(c.l + 1, 1, c.r, cell_h);

Expand Down
2 changes: 1 addition & 1 deletion src/view/mode_gui/arena/arena_spectator_gui.cpp
Expand Up @@ -97,7 +97,7 @@ void arena_spectator_gui::draw_gui(

auto& avatar_triangles = in.renderer.dedicated[augs::dedicated_buffer::SPECTATOR_AVATAR].triangles;

const auto& avatar_atlas_entry = in.avatars_in_atlas.at(now_spectating.value);
const auto avatar_atlas_entry = in.avatars_in_atlas.at(now_spectating.value);
const bool avatars_enabled = logically_set(in.general_atlas, in.avatar_atlas);
const bool avatar_displayed = avatar_atlas_entry.exists() && avatars_enabled;

Expand Down

0 comments on commit 71b3442

Please sign in to comment.