Closed
Description
What happened
I had this as my cargo.toml:
[package]
name = "top-down-shooter"
version = "0.1.0"
edition = "2021"
[dependencies]
bincode = "1.3.3"
device_query = "2.1.0"
gilrs = "0.10.7"
image = "0.25.2"
macroquad = "0.4.8"
rand = "0.8.5"
rust-embed = "8.5.0"
serde = { version = "1.0.204", features = ["derive"] }
strum = "0.26.3"
strum_macros = "0.26.4"
When I removed rand and image, which I did not need, this issue happened when running cargo check
. It did not happen before I removed these dependencies..
Code
use top_down_shooter::common::*;
use macroquad::prelude::*;
use gilrs::*;
use std::collections::HashMap;
use std::{net::UdpSocket, sync::MutexGuard};
use std::time::{Instant, Duration};
use bincode;
use std::sync::{Arc, Mutex};
use device_query::{DeviceQuery, DeviceState, Keycode};
use strum::IntoEnumIterator;
#[macroquad::main("Game")]
async fn main() {
game().await;
}
/// In the future this function will be called by main once the user starts the game
/// through the menu.
async fn game(/* server_ip: &str */) {
// hashmap (dictionary) that holds the texture for each game object.
// later (when doing animations) find way to do this with rust_embed
let mut game_object_tetures: HashMap<GameObjectType, Texture2D> = HashMap::new();
for game_object_type in GameObjectType::iter() {
game_object_tetures.insert(
game_object_type,
match game_object_type {
GameObjectType::Wall => Texture2D::from_file_with_format(include_bytes!("../../assets/gameobjects/wall.png"), None),
GameObjectType::UnbreakableWall => Texture2D::from_file_with_format(include_bytes!("../../assets/gameobjects/wall.png"), None),
GameObjectType::SniperGirlBullet => Texture2D::from_file_with_format(include_bytes!("../../assets/gameobjects/wall.png"), None),
}
);
}
// player in a mutex because many threads need to access and modify this information safely.
let player: ClientPlayer = ClientPlayer::new();
let player: Arc<Mutex<ClientPlayer>> = Arc::new(Mutex::new(player));
let player_texture: Texture2D = Texture2D::from_file_with_format(include_bytes!("../../assets/player/player1.png"), None);
// modified by network listener thread, accessed by input handler and game thread
let game_objects: Vec<GameObject> = Vec::new();
let game_objects: Arc<Mutex<Vec<GameObject>>> = Arc::new(Mutex::new(game_objects));
// accessed by game thread, modified by network listener thread.
let other_players: Vec<ClientPlayer> = Vec::new();
let other_players: Arc<Mutex<Vec<ClientPlayer>>> = Arc::new(Mutex::new(other_players));
let mut vw: f32 = 10.0;
let mut vh: f32 = 10.0;
// start the input listener and network sender thread.
// with a shared mutex of player.
let input_listener_network_sender_player = Arc::clone(&player);
std::thread::spawn(move || {
input_listener_network_sender(input_listener_network_sender_player);
});
// start the network listener thread.
// give it all necessary references to shared mutexes
let network_listener_player = Arc::clone(&player);
let network_listener_game_objects = Arc::clone(&game_objects);
let network_listener_other_players = Arc::clone(&other_players);
std::thread::spawn(move || {
network_listener(network_listener_player, network_listener_game_objects, network_listener_other_players);
});
// Main thread
loop {
// update vw and vh, used to correctly draw things scale to the screen.
// one vh for ecample is 1% of screen height.
// it's the same as in css.
if screen_height() * (16.0/9.0) > screen_width() {
vw = screen_width() / 100.0;
vh = vw / (16.0/9.0);
} else {
vh = screen_height() / 100.0;
vw = vh * (16.0/9.0);
}
// access and lock all necessary mutexes
let player: Arc<Mutex<ClientPlayer>> = Arc::clone(&player);
let player: MutexGuard<ClientPlayer> = player.lock().unwrap();
let game_objects: Arc<Mutex<Vec<GameObject>>> = Arc::clone(&game_objects);
let game_objects: MutexGuard<Vec<GameObject>> = game_objects.lock().unwrap();
let other_players: Arc<Mutex<Vec<ClientPlayer>>> = Arc::clone(&other_players);
let other_players: MutexGuard<Vec<ClientPlayer>> = other_players.lock().unwrap();
let player_copy = player.clone();
drop(player);
let game_objects_copy = game_objects.clone();
drop(game_objects);
let other_players_copy = other_players.clone();
drop(other_players);
clear_background(BLACK);
draw_rectangle(0.0, 0.0, 100.0 * vw, 100.0 * vh, WHITE);
player_copy.draw(&player_texture, vh);
player_copy.draw_crosshair(vh);
for game_object in game_objects_copy {
let texture = &game_object_tetures[&game_object.object_type];
draw_image(texture, game_object.position.x, game_object.position.y, 10.0, 10.0, vh)
}
draw_text(format!("{} fps", get_fps()).as_str(), 20.0, 20.0, 20.0, DARKGRAY);
next_frame().await;
}
}
/// This thread:
/// - handles input and updates player info
/// - handles sending player info to the server
///
/// The goal is to have a non-fps limited way of giving the server as precise
/// as possible player info, recieveing inputs independently of potentially
/// slow monitors.
fn input_listener_network_sender(player: Arc<Mutex<ClientPlayer>>) -> ! {
// temporary
let server_ip: &str = "0.0.0.0";
let server_ip: String = format!("{}:{}", server_ip, SERVER_LISTEN_PORT);
// create the socket for sending info.
let sending_ip: String = format!("0.0.0.0:{}", CLIENT_SEND_PORT);
let sending_socket: UdpSocket = UdpSocket::bind(sending_ip)
.expect("Could not bind client sender socket");
// initiate gamepad stuff
let mut gilrs = Gilrs::new().expect("Gilrs failed");
let mut active_gamepad: Option<GamepadId> = None;
// temporary
let controller_deadzone: f32 = 0.3;
let mut delta_time_counter: Instant = Instant::now();
let mut delta_time: f32 = delta_time_counter.elapsed().as_secs_f32();
let desired_delta_time: f32 = 1.0 / 300.0; // run this thread at 300Hz
loop {
// println!("network sender Hz: {}", 1.0 / delta_time);
// update active gamepad info
while let Some(Event { id, event: _, time: _ }) = gilrs.next_event() {
active_gamepad = Some(id);
}
let mut player: MutexGuard<ClientPlayer> = player.lock().unwrap();
let mut movement_vector: Vector2 = Vector2::new();
let mut shooting_primary: bool = false;
let mut shooting_secondary: bool = false;
// maybe? temporary
let movement_speed: f32 = 100.0;
// gamepad input handleingVec2 { x: 0.0, y: 0.0 }
if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) {
// Right stick (aim)
match gamepad.axis_data(Axis::RightStickX) {
Some(axis_data) => {
player.aim_direction.x = axis_data.value();
} _ => {}
}
match gamepad.axis_data(Axis::RightStickY) {
Some(axis_data) => {
player.aim_direction.y = -axis_data.value();
} _ => {}
}
// left stick (movement)
match gamepad.axis_data(Axis::LeftStickX) {
Some(axis_data) => {
// crazy rounding shenanigans to round to closest multiple of 0.2
movement_vector.x = ((axis_data.value() * 5.0).round() as i32) as f32 / 5.0;
} _ => {}
}
match gamepad.axis_data(Axis::LeftStickY) {
Some(axis_data) => {
movement_vector.y = ((-axis_data.value() * 5.0).round() as i32) as f32 / 5.0;
// println!("{}", axis_data.value());
} _ => {}
}
// triggers (shooting)
match gamepad.button_data(Button::RightTrigger2) {
Some(button_data) => {
if button_data.value() > 0.2 {
shooting_primary = true;
} else {
shooting_primary = false;
}
} _ => {}
}
match gamepad.button_data(Button::LeftTrigger2) {
Some(button_data) => {
if button_data.value() > 0.2 {
shooting_secondary = true;
} else {
shooting_secondary = false;
}
} _ => {}
}
}
let device_state: DeviceState = DeviceState::new();
let keys: Vec<Keycode> = device_state.get_keys();
// println!("Is A pressed? {}", keys.contains(&Keycode::A));
for key in keys {
match key {
Keycode::W => movement_vector.y = -1.0,
Keycode::A => movement_vector.x = -1.0,
Keycode::S => movement_vector.y = 1.0,
Keycode::D => movement_vector.x = 1.0,
_ => {}
}
}
// println!("brefore {}", movement_vector.magnitude());
// janky but good enough to correct controllers that give weird inputs.
// should not happen on normal controllers anyways.
// also corrects keyboard input.
if movement_vector.magnitude() > 1.0 {
// println!("normalizing");
movement_vector = movement_vector.normalize();
}
// println!("after {}", movement_vector.magnitude());
movement_vector.x *= movement_speed * delta_time;
movement_vector.y *= movement_speed * delta_time;
player.position.x += movement_vector.x;
player.position.y += movement_vector.y;
if player.aim_direction.magnitude() < controller_deadzone {
player.aim_direction = Vector2::new();
}
// create the packet to be sent to server.
let client_packet: ClientPacket = ClientPacket {
position: Vector2 {x: player.position.x, y: player.position.y },
movement: movement_vector,
aim_direction: Vector2 { x: player.aim_direction.x, y: player.aim_direction.y },
shooting_primary,
shooting_secondary,
};
// drop mutexguard ASAP so other threads can use player ASAP.
drop(player);
// send data to server
let serialized: Vec<u8> = bincode::serialize(&client_packet).expect("Failed to serialize message");
sending_socket.send_to(&serialized, server_ip.clone()).expect("Failed to send packet to server.");
// update delta_time and reset counter.
let delta_time_difference: f32 = desired_delta_time - delta_time_counter.elapsed().as_secs_f32();
if delta_time_difference > 0.0 {
std::thread::sleep(Duration::from_secs_f32(delta_time_difference));
}
delta_time = delta_time_counter.elapsed().as_secs_f32();
delta_time_counter = Instant::now();
}
}
fn network_listener(player: Arc<Mutex<ClientPlayer>>, game_objects: Arc<Mutex<Vec<GameObject>>>, other_players: Arc<Mutex<Vec<ClientPlayer>>>) -> ! {
let listening_ip: String = format!("0.0.0.0:{}", CLIENT_LISTEN_PORT);
let listening_socket: UdpSocket = UdpSocket::bind(listening_ip)
.expect("Could not bind client listener socket");
let mut buffer: [u8; 2048] = [0; 2048];
loop {
// recieve packet
let (amt, _src): (usize, std::net::SocketAddr) = listening_socket.recv_from(&mut buffer)
.expect("Listening socket failed to recieve.");
let data: &[u8] = &buffer[..amt];
let recieved_server_info: ServerPacket = bincode::deserialize(data).expect("Could not deserialise server packet.");
// println!("CLIENT: Received from {}: {:?}", src, recieved_server_info);
println!("doing shit");
// if we sent an illegal position, and server does a position override:
if recieved_server_info.player_packet_is_sent_to.override_position {
// gain access to the player mutex
let mut player: MutexGuard<ClientPlayer> = player.lock().unwrap();
println!("overriding!");
player.position = recieved_server_info.player_packet_is_sent_to.position_override;
drop(player); // free mutex guard ASAP for others to access player.
}
let mut game_objects = game_objects.lock().unwrap();
// these for loops are so dumb but Rust won't let me do otherwise.
// empty game_objects
for _ in 0..game_objects.len() {
game_objects.remove(0);
}
// repopulate it with new info
for game_object in recieved_server_info.game_objects {
game_objects.push(game_object);
}
drop(game_objects);
let mut other_players = other_players.lock().unwrap();
for player in recieved_server_info.players {
other_players.push(player);
}
drop(other_players);
}
}
Meta
rustc --version --verbose
:
rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7
Error output
warning: variable `delta_time` is assigned to, but never used
--> src/bin/server.rs:170:11
|
170 | let mut delta_time: f64 = server_counter.elapsed().as_secs_f64();
| ^^^^^^^^^^
|
= note: consider using `_delta_time` instead
= note: `#[warn(unused_variables)]` on by default
warning: value assigned to `delta_time` is never read
--> src/bin/server.rs:248:5
|
248 | delta_time = server_counter.elapsed().as_secs_f64();
| ^^^^^^^^^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` on by default
Checking top-down-shooter v0.1.0 (/home/ornit/Programming/moba)
warning: `top-down-shooter` (bin "server") generated 2 warnings
thread 'rustc' panicked at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/compiler/rustc_query_system/src/dep_graph/serialized.rs:192:9:
assertion `left == right` failed
left: 785297
right: 81801314346770968
stack backtrace:
0: 0x736eacbe0035 - std::backtrace_rs::backtrace::libunwind::trace::h1a07e5dba0da0cd2
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/../../backtrace/src/backtrace/libunwind.rs:105:5
1: 0x736eacbe0035 - std::backtrace_rs::backtrace::trace_unsynchronized::h61b9b8394328c0bc
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x736eacbe0035 - std::sys_common::backtrace::_print_fmt::h1c5e18b460934cff
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:68:5
3: 0x736eacbe0035 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1e1a1972118942ad
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:44:22
4: 0x736eacc2f29b - core::fmt::rt::Argument::fmt::h07af2b4071d536cd
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/fmt/rt.rs:165:63
5: 0x736eacc2f29b - core::fmt::write::hc090a2ffd6b28c4a
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/fmt/mod.rs:1157:21
6: 0x736eacbd4bdf - std::io::Write::write_fmt::h8898bac6ff039a23
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/io/mod.rs:1832:15
7: 0x736eacbdfe0e - std::sys_common::backtrace::_print::h4e80c5803d4ee35b
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:47:5
8: 0x736eacbdfe0e - std::sys_common::backtrace::print::ha96650907276675e
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:34:9
9: 0x736eacbe2779 - std::panicking::default_hook::{{closure}}::h215c2a0a8346e0e0
10: 0x736eacbe24bd - std::panicking::default_hook::h207342be97478370
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:298:9
11: 0x736ea96891b7 - std[3c8ba8ebcf555201]::panicking::update_hook::<alloc[bfbae7e348dce413]::boxed::Box<rustc_driver_impl[c88438ade88661f4]::install_ice_hook::{closure#0}>>::{closure#0}
12: 0x736eacbe2e76 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::ha9c3bc81d312fd83
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/alloc/src/boxed.rs:2036:9
13: 0x736eacbe2e76 - std::panicking::rust_panic_with_hook::hac8bdceee1e4fe2c
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:799:13
14: 0x736eacbe2c24 - std::panicking::begin_panic_handler::{{closure}}::h00d785e82757ce3c
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:664:13
15: 0x736eacbe04f9 - std::sys_common::backtrace::__rust_end_short_backtrace::h1628d957bcd06996
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys_common/backtrace.rs:171:18
16: 0x736eacbe2957 - rust_begin_unwind
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:652:5
17: 0x736eacc2b763 - core::panicking::panic_fmt::hdc63834ffaaefae5
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:72:14
18: 0x736eacc2bc5e - core::panicking::assert_failed_inner::hda4754f94c1c1cb1
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:409:17
19: 0x736ea98d1963 - core[868bc93c3f2beb33]::panicking::assert_failed::<usize, usize>
20: 0x736eab85b9d4 - rustc_incremental[8ea5e04d9752f988]::persist::load::setup_dep_graph
21: 0x736eab826d52 - <rustc_interface[640972162e3c086f]::queries::Queries>::global_ctxt
22: 0x736eab582ef0 - rustc_interface[640972162e3c086f]::interface::run_compiler::<core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>, rustc_driver_impl[c88438ade88661f4]::run_compiler::{closure#0}>::{closure#1}
23: 0x736eab540f8b - std[3c8ba8ebcf555201]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[640972162e3c086f]::util::run_in_thread_with_globals<rustc_interface[640972162e3c086f]::interface::run_compiler<core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>, rustc_driver_impl[c88438ade88661f4]::run_compiler::{closure#0}>::{closure#1}, core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>>
24: 0x736eab540d80 - <<std[3c8ba8ebcf555201]::thread::Builder>::spawn_unchecked_<rustc_interface[640972162e3c086f]::util::run_in_thread_with_globals<rustc_interface[640972162e3c086f]::interface::run_compiler<core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>, rustc_driver_impl[c88438ade88661f4]::run_compiler::{closure#0}>::{closure#1}, core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>>::{closure#0}::{closure#0}, core[868bc93c3f2beb33]::result::Result<(), rustc_span[8c7415e9d33ddd75]::ErrorGuaranteed>>::{closure#2} as core[868bc93c3f2beb33]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
25: 0x736eacbeccab - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h09e5a4c541afa800
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/alloc/src/boxed.rs:2022:9
26: 0x736eacbeccab - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h9c8b03c22f4e7026
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/alloc/src/boxed.rs:2022:9
27: 0x736eacbeccab - std::sys::pal::unix::thread::Thread::new::thread_start::h522bc89a54da820a
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/sys/pal/unix/thread.rs:108:17
28: 0x736eac98c39d - <unknown>
29: 0x736eaca1149c - <unknown>
30: 0x0 - <unknown>
error: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
note: rustc 1.79.0 (129f3b996 2024-06-10) running on x86_64-unknown-linux-gnu
note: compiler flags: --crate-type bin -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED]
note: some of the compiler flags provided by cargo are hidden
query stack during panic:
end of query stack
error: could not compile `top-down-shooter` (bin "game")
Backtrace
Checking top-down-shooter v0.1.0 (/home/ornit/Programming/moba)
warning: variable `delta_time` is assigned to, but never used
--> src/bin/server.rs:170:11
|
170 | let mut delta_time: f64 = server_counter.elapsed().as_secs_f64();
| ^^^^^^^^^^
|
= note: consider using `_delta_time` instead
= note: `#[warn(unused_variables)]` on by default
warning: value assigned to `delta_time` is never read
--> src/bin/server.rs:248:5
|
248 | delta_time = server_counter.elapsed().as_secs_f64();
| ^^^^^^^^^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` on by default
warning: `top-down-shooter` (bin "server") generated 2 warnings
thread 'rustc' panicked at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/compiler/rustc_query_system/src/dep_graph/serialized.rs:192:9:
assertion `left == right` failed
left: 785297
right: 81801314346770968
stack backtrace:
0: rust_begin_unwind
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:652:5
1: core::panicking::panic_fmt
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:72:14
2: core::panicking::assert_failed_inner
at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:409:17
3: core::panicking::assert_failed::<usize, usize>
4: rustc_incremental::persist::load::setup_dep_graph
5: <rustc_interface::queries::Queries>::global_ctxt
6: rustc_interface::interface::run_compiler::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
note: rustc 1.79.0 (129f3b996 2024-06-10) running on x86_64-unknown-linux-gnu
note: compiler flags: --crate-type bin -C embed-bitcode=no -C debuginfo=2 -C incremental=[REDACTED]
note: some of the compiler flags provided by cargo are hidden
query stack during panic:
end of query stack
error: could not compile `top-down-shooter` (bin "game")