void call_window_script(augs::lua_state_raii& lua, game_window& window, const std::string& filename) { lua.global_ptr("global_gl_window", &window.window); lua.dofile_and_report_errors(filename); window.window.gl.initialize(); window.window.gl.initialize_fbos(window.get_screen_size()); }
void client_setup::init(const config_lua_table& cfg, game_window& window, const std::string recording_filename, const bool use_alternative_port) { const vec2i screen_size = vec2i(window.get_screen_size()); scene_managers::networked_testbed_client().populate_world_with_entities(initial_hypersomnia); session.systems_audiovisual.get<interpolation_system>().interpolation_speed = cfg.interpolation_speed; detailed_step_log = cfg.tickrate <= 2; if (!hypersomnia.load_from_file("save.state")) { hypersomnia.set_fixed_delta(cfg.tickrate); scene.populate_world_with_entities(hypersomnia); } if (cfg.get_input_recording_mode() != input_recording_type::DISABLED) { if (player.try_to_load_or_save_new_session("sessions/", recording_filename)) { timer.set_stepping_speed_multiplier(cfg.recording_replay_speed); } } session.camera.configure_size(screen_size); session.set_master_gain(cfg.sound_effects_volume); session.configure_input(); receiver.jitter_buffer.set_lower_limit(static_cast<unsigned>(cfg.jitter_buffer_ms / hypersomnia.get_fixed_delta().in_milliseconds())); receiver.misprediction_smoothing_multiplier = cfg.misprediction_smoothing_multiplier; const bool is_replaying = player.is_replaying(); LOG("Is client replaying: %x", is_replaying); const auto port = use_alternative_port ? cfg.alternative_port : cfg.connect_port; const std::string readable_ip = typesafe_sprintf("%x:%x", cfg.connect_address, port); LOG("Connecting to: %x", readable_ip); if (is_replaying || client.connect(cfg.connect_address, port, 15000)) { LOG("Connected successfully to %x", readable_ip); augs::stream welcome; augs::write_object(welcome, network_command::CLIENT_WELCOME_MESSAGE); augs::write_object(welcome, use_alternative_port ? cfg.debug_second_nickname : cfg.nickname); client.post_redundant(welcome); timer.reset_timer(); } else { LOG("Connection failed."); } session.reserve_caches_for_entities(3000); }
void client_setup::process(const config_lua_table& cfg, game_window& window) { init(cfg, window); while (!should_quit) { session.local_entropy_profiler.new_measurement(); auto precollected = window.collect_entropy(!cfg.debug_disable_cursor_clipping); session.local_entropy_profiler.end_measurement(); if (process_exit_key(precollected)) break; process_once(window, precollected); } }
void director_setup::process(const config_lua_table& cfg, game_window& window) { const vec2i screen_size = vec2i(window.get_screen_size()); cosmos hypersomnia(3000); augs::window::event::state events; augs::machine_entropy total_collected_entropy; augs::fixed_delta_timer timer = augs::fixed_delta_timer(5); scene_managers::testbed testbed; testbed.debug_var = cfg.debug_var; if (!hypersomnia.load_from_file("save.state")) { hypersomnia.set_fixed_delta(cfg.tickrate); testbed.populate_world_with_entities(hypersomnia, screen_size); } viewing_session session; session.reserve_caches_for_entities(3000); session.camera.configure_size(screen_size); session.systems_audiovisual.get<interpolation_system>().interpolation_speed = cfg.interpolation_speed; session.set_interpolation_enabled(false); session.set_master_gain(cfg.sound_effects_volume); testbed.configure_view(session); const std::string input_director_file = cfg.director_scenario_filename; const std::string output_director_file = cfg.director_scenario_filename; cosmic_movie_director director; director.load_recording_from_file(input_director_file); enum class director_state { PLAYING, RECORDING } current_director_state = director_state::PLAYING; timer.reset_timer(); int advance_steps_forward = 0; float requested_playing_speed = 0.f; bool unsaved_changes_exist = false; enum class recording_replacement_type { ALL, ONLY_KEYS, ONLY_MOUSE, COUNT }; auto recording_replacement_mode = recording_replacement_type::ALL; std::vector<cosmos> snapshots_for_rewinding; const auto initial_step_number = hypersomnia.get_total_steps_passed(); const double seconds_between_snapshots = 3.0; const auto steps_between_snapshots = static_cast<unsigned>(seconds_between_snapshots / hypersomnia.get_fixed_delta().in_seconds()); unsigned bookmarked_step = 0; const auto get_step_number = [initial_step_number](const cosmos& cosm) { ensure(initial_step_number <= cosm.get_total_steps_passed()); return cosm.get_total_steps_passed() - initial_step_number; }; LOG("Seconds between rewind snapshots: %x", seconds_between_snapshots); LOG("Steps between rewind snapshots: %x", steps_between_snapshots); while (!should_quit) { { augs::machine_entropy new_entropy; session.local_entropy_profiler.new_measurement(); new_entropy.local = window.collect_entropy(!cfg.debug_disable_cursor_clipping); session.local_entropy_profiler.end_measurement(); session.control(new_entropy); process_exit_key(new_entropy.local); if (current_director_state == director_state::RECORDING) { total_collected_entropy += new_entropy; } for (const auto& raw_input : new_entropy.local) { events.apply(raw_input); if (raw_input.was_any_key_pressed()) { if (raw_input.key == key::F2) { current_director_state = director_state::PLAYING; } if (raw_input.key == key::F3) { requested_playing_speed = 0.f; if (current_director_state == director_state::RECORDING) { recording_replacement_mode = static_cast<recording_replacement_type>((static_cast<int>(recording_replacement_mode) + 1) % static_cast<int>(recording_replacement_type::COUNT)); } else { recording_replacement_mode = recording_replacement_type::ALL; current_director_state = director_state::RECORDING; total_collected_entropy.clear(); } } if (raw_input.key == key::F7) { director.save_recording_to_file(output_director_file); unsaved_changes_exist = false; } if (raw_input.key == key::_1) { advance_steps_forward = -1; if (events.is_set(key::LCTRL)) { advance_steps_forward *= 10; } } if (raw_input.key == key::_2) { advance_steps_forward = 1; if (events.is_set(key::LCTRL)) { advance_steps_forward *= 10; } } if (raw_input.key == key::_3) { requested_playing_speed = 0.f; total_collected_entropy.clear(); } if (raw_input.key == key::_4) { requested_playing_speed = 0.1f; total_collected_entropy.clear(); } if (raw_input.key == key::_5) { requested_playing_speed = 1.f; total_collected_entropy.clear(); } if (raw_input.key == key::_6) { requested_playing_speed = 6.f; total_collected_entropy.clear(); } if (raw_input.key == key::_9) { bookmarked_step = get_step_number(hypersomnia); total_collected_entropy.clear(); } if (raw_input.key == key::_0) { advance_steps_forward = static_cast<long long>(bookmarked_step) - static_cast<long long>(get_step_number(hypersomnia)); total_collected_entropy.clear(); } } } testbed.control_character_selection(new_entropy.local); timer.set_stepping_speed_multiplier(requested_playing_speed); } if (advance_steps_forward < 0) { const auto current_step = get_step_number(hypersomnia); const auto rewound_step = static_cast<unsigned>(-advance_steps_forward) > current_step ? 0 : current_step + advance_steps_forward; #if LOG_REWINDING LOG("Current step: %x\nRewound step: %x", current_step, rewound_step); #endif if (rewound_step < current_step) { const size_t resimulated_cosmos_index = rewound_step / steps_between_snapshots; #if LOG_REWINDING LOG_NVPS(snapshots_for_rewinding.size()); LOG_NVPS(resimulated_cosmos_index); #endif if (snapshots_for_rewinding.size() > 1 && resimulated_cosmos_index < snapshots_for_rewinding.size() - 1) { snapshots_for_rewinding.erase(snapshots_for_rewinding.begin() + resimulated_cosmos_index + 1, snapshots_for_rewinding.end()); } hypersomnia = snapshots_for_rewinding.at(resimulated_cosmos_index); #if LOG_REWINDING LOG("Resimulated hypersomnia step: %x", get_step_number(hypersomnia)); #endif while (get_step_number(hypersomnia) < rewound_step) { const guid_mapped_entropy replayed_entropy = director.get_entropy_for_step(get_step_number(hypersomnia)); const cosmic_entropy cosmic_entropy_for_this_advancement = cosmic_entropy(replayed_entropy, hypersomnia); hypersomnia.advance_deterministic_schemata(cosmic_entropy_for_this_advancement, [](auto) {}, [this, &session](const const_logic_step& step) { session.acquire_game_events_for_hud(step); } ); } } advance_steps_forward = 0; } auto steps = timer.count_logic_steps_to_perform(hypersomnia.get_fixed_delta()); steps += advance_steps_forward; advance_steps_forward = 0; const auto selected_character = hypersomnia[testbed.get_selected_character()]; while (steps--) { cosmic_entropy cosmic_entropy_for_this_advancement; const auto current_step = get_step_number(hypersomnia); if (current_step % steps_between_snapshots == 0) { snapshots_for_rewinding.push_back(hypersomnia); } if (current_director_state == director_state::PLAYING) { guid_mapped_entropy replayed_entropy = director.get_entropy_for_step(current_step); cosmic_entropy_for_this_advancement = cosmic_entropy(replayed_entropy, hypersomnia); } else if (current_director_state == director_state::RECORDING) { guid_mapped_entropy& recorded_entropy = director.step_to_entropy[current_step]; auto& target_intents_from_recording = recorded_entropy.entropy_per_entity[selected_character.get_guid()]; auto new_intents = make_intents_for_entity(selected_character, total_collected_entropy.local, session.context); auto mouse_remover = [](const auto& k) { return k.uses_mouse_motion(); }; auto key_remover = [](const auto& k) { return !k.uses_mouse_motion(); }; if (recording_replacement_mode == recording_replacement_type::ALL) { target_intents_from_recording = new_intents; } else if (recording_replacement_mode == recording_replacement_type::ONLY_KEYS) { erase_remove(target_intents_from_recording, key_remover); erase_remove(new_intents, mouse_remover); concatenate(target_intents_from_recording, new_intents); } else if (recording_replacement_mode == recording_replacement_type::ONLY_MOUSE) { erase_remove(target_intents_from_recording, mouse_remover); erase_remove(new_intents, key_remover); concatenate(target_intents_from_recording, new_intents); } else { ensure(false); } cosmic_entropy_for_this_advancement = cosmic_entropy(recorded_entropy, hypersomnia); unsaved_changes_exist = true; } renderer::get_current().clear_logic_lines(); hypersomnia.advance_deterministic_schemata(cosmic_entropy_for_this_advancement, [](auto) {}, [this, &session](const const_logic_step& step) { session.acquire_game_events_for_hud(step); } ); session.resample_state_for_audiovisuals(hypersomnia); total_collected_entropy.clear(); } const auto vdt = session.frame_timer.extract_variable_delta(hypersomnia.get_fixed_delta(), timer); session.advance_audiovisual_systems(hypersomnia, testbed.get_selected_character(), vdt); using namespace augs::gui::text; const auto white_font = style(assets::font_id::GUI_FONT, white); auto director_text = format(L"Welcome to the director setup.", white_font); director_text += format(L"\nMode: ", white_font); if (current_director_state == director_state::PLAYING) { director_text += format(L"Playing", white_font); } else { if (recording_replacement_mode == recording_replacement_type::ALL) { director_text += simple_bbcode(L"[color=red]Recording (replacing all)[/color]", white_font); } else if (recording_replacement_mode == recording_replacement_type::ONLY_KEYS) { director_text += simple_bbcode(L"[color=red]Recording (replacing keys)[/color]", white_font); } else if (recording_replacement_mode == recording_replacement_type::ONLY_MOUSE) { director_text += simple_bbcode(L"[color=red]Recording (replacing mouse)[/color]", white_font); } else { ensure(false); } } director_text += format(typesafe_sprintf(L"\nRequested playing speed: %x", requested_playing_speed), white_font); director_text += format(typesafe_sprintf(L"\nStep number: %x", get_step_number(hypersomnia)), white_font); director_text += format(typesafe_sprintf(L"\nTime: %x", get_step_number(hypersomnia)*hypersomnia.get_fixed_delta().in_seconds()), white_font); director_text += format(typesafe_sprintf(L"\nControlling entity %x of %x", testbed.current_character_index, testbed.characters.size()), white_font); if (bookmarked_step != 0) { director_text += format(typesafe_sprintf(L"\nBookmarked time: %x", bookmarked_step*hypersomnia.get_fixed_delta().in_seconds()), white_font); } if (unsaved_changes_exist) { director_text += simple_bbcode(L"\n[color=yellow]Press F7 to save pending changes.[/color]", white_font); } auto& renderer = augs::renderer::get_current(); renderer.clear_current_fbo(); session.view(renderer, hypersomnia, testbed.get_selected_character(), vdt, director_text); window.swap_buffers(); } if (unsaved_changes_exist) { director.save_recording_to_file(output_director_file + ".unsaved.ent"); } }
void client_setup::process_once(game_window& window, const augs::machine_entropy::local_type& precollected, const bool swap_buffers) { auto step_pred = [this](const cosmic_entropy& entropy, cosmos& cosm) { cosm.advance_deterministic_schemata(entropy, [this](const logic_step) {}, [this](const const_logic_step) {} ); }; auto step_pred_with_effects_response = [this](const cosmic_entropy& entropy, cosmos& cosm) { cosm.advance_deterministic_schemata(entropy, [this](const logic_step) {}, [this](const const_logic_step step) { session.spread_past_infection(step); session.acquire_game_events_for_hud(step); } ); }; augs::machine_entropy new_entropy; new_entropy.local = precollected; session.remote_entropy_profiler.new_measurement(); new_entropy.remote = client.collect_entropy(); session.remote_entropy_profiler.end_measurement(); const bool still_downloading = !complete_state_received || receiver.jitter_buffer.is_still_refilling(); total_collected_entropy += new_entropy; auto steps = timer.count_logic_steps_to_perform(hypersomnia.get_fixed_delta()); while (steps--) { session.unpack_local_steps_profiler.new_measurement(); player.advance_player_and_biserialize(total_collected_entropy); session.unpack_local_steps_profiler.end_measurement(); for (auto& net_event : total_collected_entropy.remote) { if (net_event.message_type == augs::network::message::type::RECEIVE) { auto& stream = net_event.payload; auto to_skip = net_event.messages_to_skip; while (stream.get_unread_bytes() > 0) { network_command command; augs::read_object(stream, command); const bool should_skip = to_skip > 0; if (should_skip) { --to_skip; } if (detailed_step_log && !should_skip) { LOG("Client received command: %x", int(stream.peek<unsigned char>())); } switch (command) { case network_command::COMPLETE_STATE: ensure(!should_skip); cosmic_delta::decode(initial_hypersomnia, stream); hypersomnia = initial_hypersomnia; extrapolated_hypersomnia = initial_hypersomnia; LOG("Decoded cosm at step: %x", hypersomnia.get_total_steps_passed()); unsigned controlled_character_guid; augs::read_object(stream, controlled_character_guid); scene.select_character(hypersomnia.get_entity_by_guid(controlled_character_guid)); complete_state_received = true; break; case network_command::PACKAGED_STEP: { step_packaged_for_network step; augs::read_object(stream, step); if (!should_skip) { receiver.acquire_next_packaged_step(step); } } break; default: LOG("Client received invalid command: %x", int(command)); stream = augs::stream(); break; } } } } if (!still_downloading) { session.sending_commands_and_predict_profiler.new_measurement(); const auto local_cosmic_entropy_for_this_step = cosmic_entropy(hypersomnia[scene.get_selected_character()], total_collected_entropy.local, session.context); receiver.send_commands_and_predict(client, local_cosmic_entropy_for_this_step, extrapolated_hypersomnia, step_pred_with_effects_response); session.sending_commands_and_predict_profiler.end_measurement(); // LOG("Predicting to step: %x; predicted steps: %x", extrapolated_hypersomnia.get_total_steps_passed(), receiver.predicted_steps.size()); session.unpack_remote_steps_profiler.new_measurement(); receiver.unpack_deterministic_steps( session.systems_audiovisual.get<interpolation_system>(), session.systems_audiovisual.get<past_infection_system>(), scene.get_selected_character(), hypersomnia, hypersomnia_last_snapshot, extrapolated_hypersomnia, step_pred); session.unpack_remote_steps_profiler.end_measurement(); session.resample_state_for_audiovisuals(extrapolated_hypersomnia); } if (client.has_timed_out(hypersomnia.get_fixed_delta().in_milliseconds(), 2000)) { LOG("Connection to server timed out."); client.forceful_disconnect(); } session.sending_packets_profiler.new_measurement(); client.send_pending_redundant(); session.sending_packets_profiler.end_measurement(); total_collected_entropy.clear(); } if (!still_downloading) { const auto vdt = session.frame_timer.extract_variable_delta(extrapolated_hypersomnia.get_fixed_delta(), timer); session.advance_audiovisual_systems(extrapolated_hypersomnia, scene.get_selected_character(), vdt); auto& renderer = augs::renderer::get_current(); if (swap_buffers) { renderer.clear_current_fbo(); } session.view(renderer, extrapolated_hypersomnia, scene.get_selected_character(), vdt, client); if (swap_buffers) { window.swap_buffers(); } } }
void determinism_test_setup::process(const config_lua_table& cfg, game_window& window) { const vec2i screen_size = vec2i(window.get_screen_size()); const unsigned cosmoi_count = 1 + cfg.determinism_test_cloned_cosmoi_count; std::vector<cosmos> hypersomnias(cosmoi_count, cosmos(3000)); augs::machine_entropy total_collected_entropy; augs::machine_entropy_player player; augs::fixed_delta_timer timer = augs::fixed_delta_timer(5); std::vector<scene_managers::testbed> testbeds(cosmoi_count); if (augs::file_exists("save.state")) { for (auto& h : hypersomnias) { ensure(h.load_from_file("save.state")); } } else { for (size_t i = 0; i < cosmoi_count; ++i) { hypersomnias[i].set_fixed_delta(cfg.tickrate); testbeds[i].populate_world_with_entities(hypersomnias[i], vec2i(1920, 1080)); } } for (auto& h : hypersomnias) { ensure(h == hypersomnias[0]); } if (cfg.get_input_recording_mode() != input_recording_type::DISABLED) { if (player.try_to_load_or_save_new_session("sessions/", "recorded.inputs")) { timer.set_stepping_speed_multiplier(cfg.recording_replay_speed); } } viewing_session session; session.reserve_caches_for_entities(3000); session.camera.configure_size(screen_size); session.set_interpolation_enabled(false); session.set_master_gain(cfg.sound_effects_volume); for (size_t i = 0; i < cosmoi_count; ++i) { testbeds[i].configure_view(session); } unsigned currently_viewn_cosmos = 0; bool divergence_detected = false; unsigned which_divergent = 0; timer.reset_timer(); while (!should_quit) { augs::machine_entropy new_entropy; new_entropy.local = window.collect_entropy(!cfg.debug_disable_cursor_clipping); if (process_exit_key(new_entropy.local)) break; for (auto& n : new_entropy.local) { if (n.was_any_key_pressed()) { if (n.key == augs::window::event::keys::key::F3) { ++currently_viewn_cosmos; currently_viewn_cosmos %= cosmoi_count; } } } total_collected_entropy += new_entropy; auto steps = timer.count_logic_steps_to_perform(hypersomnias[0].get_fixed_delta()); while (steps--) { if (divergence_detected) { break; } player.advance_player_and_biserialize(total_collected_entropy); for (size_t i = 0; i < cosmoi_count; ++i) { auto& h = hypersomnias[i]; if (i + 1 < cosmoi_count) hypersomnias[i] = hypersomnias[i + 1]; testbeds[i].control_character_selection(total_collected_entropy.local); auto cosmic_entropy_for_this_step = cosmic_entropy(h[testbeds[i].get_selected_character()], total_collected_entropy.local, session.context); renderer::get_current().clear_logic_lines(); h.advance_deterministic_schemata(cosmic_entropy_for_this_step, [](auto) {}, [this, &session](const const_logic_step& step) { session.spread_past_infection(step); } ); } session.resample_state_for_audiovisuals(hypersomnias[0]); auto& first_cosm = hypersomnias[0].reserved_memory_for_serialization; augs::output_stream_reserver first_cosm_reserver; augs::write_object(first_cosm_reserver, hypersomnias[0].significant); first_cosm.reserve(first_cosm_reserver.get_write_pos()); first_cosm.reset_write_pos(); augs::write_object(first_cosm, hypersomnias[0].significant); for (unsigned i = 1; i < cosmoi_count; ++i) { auto& second_cosm = hypersomnias[i].reserved_memory_for_serialization; augs::output_stream_reserver second_cosm_reserver; augs::write_object(second_cosm_reserver, hypersomnias[i].significant); second_cosm.reserve(second_cosm_reserver.get_write_pos()); second_cosm.reset_write_pos(); augs::write_object(second_cosm, hypersomnias[i].significant); if (!(first_cosm == second_cosm)) { divergence_detected = true; which_divergent = i; break; } } total_collected_entropy.clear(); } std::string logged; if (divergence_detected) { logged += typesafe_sprintf("Divergence detected in cosmos: %x (step: %x)\n", which_divergent, hypersomnias[0].get_total_steps_passed()); } logged += typesafe_sprintf("Currently viewn cosmos: %x (F3 to switch)\n", currently_viewn_cosmos); auto& renderer = augs::renderer::get_current(); renderer.clear_current_fbo(); session.view(renderer, hypersomnias[currently_viewn_cosmos], testbeds[currently_viewn_cosmos].get_selected_character(), session.frame_timer.extract_variable_delta(hypersomnias[currently_viewn_cosmos].get_fixed_delta(), timer)); window.swap_buffers(); } }