M Cargo.lock => Cargo.lock +3 -2
@@ 511,9 511,9 @@ dependencies = [
[[package]]
name = "async-tungstenite"
-version = "0.21.0"
+version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6d2c69d237cf761215175f390021344f5530101cca8164d69878b8a1779e80c"
+checksum = "ce01ac37fdc85f10a43c43bc582cbd566720357011578a935761075f898baf58"
dependencies = [
"futures-io",
"futures-util",
@@ 3436,6 3436,7 @@ dependencies = [
"log",
"nalgebra",
"parking_lot 0.12.1",
+ "protobuf 3.2.0",
"rand",
"rapier2d-f64",
"reqwest",
M api/src/config.rs => api/src/config.rs +1 -1
@@ 32,7 32,7 @@ pub struct StarkingdomsApiConfig {
pub base: String,
pub game: String,
pub realms: HashMap<String, StarkingdomsApiConfigRealm>,
- pub servers: Vec<String>
+ pub servers: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug)]
M api/src/main.rs => api/src/main.rs +1 -1
@@ 1,5 1,6 @@
use crate::config::CONFIG;
use crate::error::{APIError, APIErrorsResponse};
+use actix_cors::Cors;
use actix_request_identifier::RequestIdentifier;
use actix_web::http::header::HeaderValue;
use actix_web::web::{Data, JsonConfig};
@@ 9,7 10,6 @@ use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use starkingdoms_api_migration::{Migrator, MigratorTrait};
use std::error::Error;
use std::time::Duration;
-use actix_cors::Cors;
use tera::Tera;
pub mod config;
M api/src/routes/mod.rs => api/src/routes/mod.rs +1 -1
@@ 2,4 2,4 @@ pub mod beamin;
pub mod beamout;
pub mod callback;
pub mod select_realm;
-pub mod server_list;>
\ No newline at end of file
+pub mod server_list;
M api/src/routes/select_realm.rs => api/src/routes/select_realm.rs +1 -1
@@ 16,7 16,7 @@ pub struct RealmsListTemplateContext {
#[get("/select-realm")]
pub async fn select_realm(state: Data<AppState>) -> HttpResponse {
- let context = match Context::from_serialize(&RealmsListTemplateContext {
+ let context = match Context::from_serialize(RealmsListTemplateContext {
back_to: format!("{}/callback", CONFIG.base),
realms: CONFIG.realms.clone(),
}) {
M api/src/routes/server_list.rs => api/src/routes/server_list.rs +4 -4
@@ 1,11 1,11 @@
-use actix_web::{get};
+use crate::config::CONFIG;
+use actix_web::get;
use actix_web::web::Json;
use serde::Serialize;
-use crate::config::CONFIG;
#[derive(Serialize)]
pub struct ServerListResponse {
- pub servers: Vec<String>
+ pub servers: Vec<String>,
}
#[get("server-list")]
@@ 13,4 13,4 @@ pub async fn server_list() -> Json<ServerListResponse> {
Json(ServerListResponse {
servers: CONFIG.servers.clone(),
})
-}>
\ No newline at end of file
+}
M client/index.html => client/index.html +0 -4
@@ 115,9 115,5 @@
width: 100%;
}
- .w-90 {
- width: 90%;
- }
-
</style>
</html>
M protocol/src/lib.rs => protocol/src/lib.rs +18 -15
@@ 1,11 1,11 @@
use crate::message_c2s::{
MessageC2SAuthenticateAndBeamOut, MessageC2SChat, MessageC2SGoodbye, MessageC2SHello,
MessageC2SInput, MessageC2SModuleDetach, MessageC2SModuleGrabBegin, MessageC2SModuleGrabEnd,
- MessageC2SMouseInput, MessageC2SPing
+ MessageC2SMouseInput, MessageC2SPing,
};
use crate::message_s2c::{
- MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModulesUpdate,
- MessageS2CModuleAdd, MessageS2CModuleRemove, MessageS2CModuleTreeUpdate,
+ MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModuleAdd,
+ MessageS2CModuleRemove, MessageS2CModuleTreeUpdate, MessageS2CModulesUpdate,
MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong,
};
use crate::planet::PlanetType;
@@ 50,7 50,7 @@ impl TryFrom<&[u8]> for MessageC2S {
type Error = Box<dyn Error>;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
- let pkt = starkingdoms_protocol::PacketWrapper::parse_from_bytes(value)?;
+ let pkt = PacketWrapper::parse_from_bytes(value)?;
let deser_pkt = match pkt.packet_id {
_id if _id == message_c2s::message_c2shello::Packet_info::type_.value() as i64 => {
@@ 84,17 84,23 @@ impl TryFrom<&[u8]> for MessageC2S {
_id if _id
== message_c2s::message_c2smodule_grab_begin::Packet_info::type_.value() as i64 =>
{
- MessageC2S::ModuleGrabBegin(MessageC2SModuleGrabBegin::parse_from_bytes(&pkt.packet_data)?)
+ MessageC2S::ModuleGrabBegin(MessageC2SModuleGrabBegin::parse_from_bytes(
+ &pkt.packet_data,
+ )?)
}
_id if _id
== message_c2s::message_c2smodule_grab_end::Packet_info::type_.value() as i64 =>
{
- MessageC2S::ModuleGrabEnd(MessageC2SModuleGrabEnd::parse_from_bytes(&pkt.packet_data)?)
+ MessageC2S::ModuleGrabEnd(MessageC2SModuleGrabEnd::parse_from_bytes(
+ &pkt.packet_data,
+ )?)
}
_id if _id
== message_c2s::message_c2smodule_detach::Packet_info::type_.value() as i64 =>
{
- MessageC2S::ModuleDetach(MessageC2SModuleDetach::parse_from_bytes(&pkt.packet_data)?)
+ MessageC2S::ModuleDetach(MessageC2SModuleDetach::parse_from_bytes(
+ &pkt.packet_data,
+ )?)
}
_id => {
return Err(format!("Unrecognized C2S packet {}", _id).into());
@@ 201,18 207,15 @@ impl TryFrom<&[u8]> for MessageS2C {
)?)
}
_id if _id
- == message_s2c::message_s2cmodule_tree_update::Packet_info::type_.value() as i64 =>
+ == message_s2c::message_s2cmodule_tree_update::Packet_info::type_.value()
+ as i64 =>
{
MessageS2C::ModuleTreeUpdate(MessageS2CModuleTreeUpdate::parse_from_bytes(
&pkt.packet_data,
)?)
}
- _id if _id
- == message_s2c::message_s2cmodule_add::Packet_info::type_.value() as i64 =>
- {
- MessageS2C::ModuleAdd(MessageS2CModuleAdd::parse_from_bytes(
- &pkt.packet_data,
- )?)
+ _id if _id == message_s2c::message_s2cmodule_add::Packet_info::type_.value() as i64 => {
+ MessageS2C::ModuleAdd(MessageS2CModuleAdd::parse_from_bytes(&pkt.packet_data)?)
}
_id if _id
== message_s2c::message_s2cmodule_remove::Packet_info::type_.value() as i64 =>
@@ 287,7 290,7 @@ impl TryInto<Vec<u8>> for MessageS2C {
}
}
-impl planet::PlanetType {
+impl PlanetType {
pub fn as_texture_id(&self) -> String {
match self {
PlanetType::Earth => "earth".to_string(),
M server/Cargo.toml => server/Cargo.toml +3 -1
@@ 17,7 17,7 @@ serde_json = "1"
futures = { version = "0.3", default-features = false }
tungstenite = { version = "0.19.0", default-features = false }
-async-tungstenite = "0.21.0"
+async-tungstenite = "0.22.1"
log = "0.4"
simple_logger = "4.1"
@@ 28,6 28,8 @@ nalgebra = "0.32.2"
rand = "0.8.5"
reqwest = "0.11.16"
+protobuf = "3.2.0"
+
parking_lot = { version = "0.12.1", features = ["deadlock_detection"] }
[build-dependencies]
M server/src/api.rs => server/src/api.rs +3 -3
@@ 31,7 31,7 @@ pub async fn load_player_data_from_api(
};
let res = client
- .post(format!("{}/beamin", std::env::var("STK_API_URL").unwrap()))
+ .post(format!("{}/beamin", std::env::var("STK_API_URL")?))
.header("Content-Type", "application/json")
.body(serde_json::to_string(&req_body)?)
.send()
@@ 75,11 75,11 @@ pub async fn save_player_data_to_api(
api_token: internal_token.to_owned(),
user_auth_realm_id: user_id.to_owned(),
user_auth_token: token.to_owned(),
- data: data.to_owned(),
+ data: data.clone(),
};
let res = client
- .post(format!("{}/beamout", std::env::var("STK_API_URL").unwrap()))
+ .post(format!("{}/beamout", std::env::var("STK_API_URL")?))
.header("Content-Type", "application/json")
.body(serde_json::to_string(&req_body)?)
.send()
M server/src/entity.rs => server/src/entity.rs +14 -17
@@ 1,12 1,14 @@
use std::{collections::HashMap, net::SocketAddr, sync::atomic::AtomicU32};
use nalgebra::Vector2;
+use protobuf::SpecialFields;
use starkingdoms_protocol::planet::PlanetType;
use crate::{
manager::{ClientHandlerMessage, Player},
+ module::{AttachedModule, Module},
planet::Planet,
- SCALE, module::{Module, AttachedModule},
+ SCALE,
};
pub type EntityId = u32;
@@ 15,9 17,7 @@ static mut ENTITY_ID_COUNT: AtomicU32 = AtomicU32::new(0);
pub fn get_entity_id() -> EntityId {
let last_entity_id = unsafe { &ENTITY_ID_COUNT };
let id = last_entity_id.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
- if id > 4_147_483_600 {
- panic!("No remaining entity ids")
- };
+ assert!(id <= 4_147_483_600, "No remaining entity ids");
id
}
@@ 27,8 27,8 @@ pub struct EntityHandler {
}
impl EntityHandler {
- pub fn new() -> EntityHandler {
- EntityHandler {
+ pub fn new() -> Self {
+ Self {
entities: Entities::new(),
}
}
@@ 71,7 71,7 @@ impl EntityHandler {
}
}
pub fn get_player_id(&self, addr: SocketAddr) -> Option<EntityId> {
- for (id, entity) in self.entities.iter() {
+ for (id, entity) in &self.entities {
if let Entity::Player(player) = entity {
if player.addr == addr {
return Some(*id);
@@ 83,10 83,7 @@ impl EntityHandler {
pub fn get_player(&self, addr: SocketAddr) -> Option<Player> {
let players = self.get_players();
let player = players.iter().find(|p| p.0 == addr);
- match player {
- Some(p) => Some(p.1.clone()),
- None => None,
- }
+ player.map(|p| p.1.clone())
}
pub fn get_modules(&self) -> Vec<Module> {
let mut modules = Vec::new();
@@ 99,9 96,9 @@ impl EntityHandler {
}
pub fn get_modules_id(&self) -> Vec<(EntityId, Module)> {
let mut modules = Vec::new();
- for (id, entity) in self.entities.clone().into_iter() {
+ for (id, entity) in self.entities.clone() {
if let Entity::Module(module) = entity {
- modules.push((id as u32, module.clone()));
+ modules.push((id, module.clone()));
}
}
modules
@@ 122,7 119,7 @@ impl EntityHandler {
None
}
pub fn get_from_module(&self, p_module: &Module) -> Option<EntityId> {
- for (id, entity) in self.entities.iter() {
+ for (id, entity) in &self.entities {
if let Entity::Module(module) = entity {
if module.handle == p_module.handle {
return Some(*id);
@@ 146,8 143,8 @@ impl EntityHandler {
}
None
}
- pub fn get_id_from_attached(&self, p_module: AttachedModule) -> Option<EntityId> {
- for (id, entity) in self.entities.iter() {
+ pub fn get_id_from_attached(&self, p_module: &AttachedModule) -> Option<EntityId> {
+ for (id, entity) in &self.entities {
if let Entity::AttachedModule(module) = entity {
if module.handle == p_module.handle {
return Some(*id);
@@ 177,7 174,7 @@ impl EntityHandler {
x: planet.position.0 * SCALE,
y: planet.position.1 * SCALE,
radius: planet.radius * SCALE, // DO NOT * SCALE. THIS VALUE IS NOT SCALED! YES IT IS
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
});
}
M server/src/handler.rs => server/src/handler.rs +148 -71
@@ 1,8 1,6 @@
use crate::api::{load_player_data_from_api, save_player_data_to_api};
use crate::entity::{get_entity_id, Entity, EntityHandler};
-use crate::manager::{
- ClientHandlerMessage, ClientManager, Player, PhysicsData,
-};
+use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player};
use crate::module::{AttachedModule, Module};
use crate::{recv, send, SCALE};
use async_std::net::TcpStream;
@@ 14,12 12,13 @@ use log::{error, info, warn};
use nalgebra::{point, vector, Vector2};
use rand::Rng;
use rapier2d_f64::prelude::{
- Collider, ColliderBuilder, MassProperties, RigidBodyBuilder, RigidBodyType, Isometry,
+ Collider, ColliderBuilder, Isometry, MassProperties, RigidBodyBuilder, RigidBodyType,
};
use starkingdoms_protocol::goodbye_reason::GoodbyeReason;
use starkingdoms_protocol::message_s2c::{
- MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModulesUpdate,
- MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong, MessageS2CModuleAdd, MessageS2CModuleTreeUpdate, MessageS2CModuleRemove,
+ MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModuleAdd,
+ MessageS2CModuleRemove, MessageS2CModuleTreeUpdate, MessageS2CModulesUpdate,
+ MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong,
};
use starkingdoms_protocol::state::State;
@@ 29,6 28,7 @@ use std::f64::consts::PI;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
+use protobuf::SpecialFields;
use tungstenite::Message;
pub async fn handle_client(
@@ 123,6 123,8 @@ pub async fn handle_client(
match pkt {
MessageC2S::Hello(pkt) => {
info!("client sent hello");
+ // there is no way to not use unwrap here :/
+ #[allow(clippy::unwrap_used)]
if !matches!(pkt.next_state.unwrap(), State::Play) {
error!(
"client sent unexpected state {:?} (expected: Play)",
@@ 130,7 132,7 @@ pub async fn handle_client(
);
let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
reason: GoodbyeReason::UnexpectedNextState.into(),
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
})
.try_into()?;
send!(client_tx, msg).await?;
@@ 186,7 188,7 @@ pub async fn handle_client(
let msg = MessageS2C::Hello(MessageS2CHello {
version: pkt.version,
given_username: pkt.requested_username.clone(),
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
next_state: pkt.next_state,
})
.try_into()?;
@@ 252,7 254,7 @@ pub async fn handle_client(
let player_data = match load_player_data_from_api(
&pkt.token,
&pkt.user,
- &std::env::var("STK_API_KEY").unwrap(),
+ &std::env::var("STK_API_KEY")?,
)
.await
{
@@ 317,7 319,6 @@ pub async fn handle_client(
},
2,
);*/
-
}
}
MessageC2S::Goodbye(pkt) => {
@@ 331,7 332,7 @@ pub async fn handle_client(
);
let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
reason: GoodbyeReason::UnexpectedPacket.into(),
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
})
.try_into()?;
send!(client_tx, msg).await?;
@@ 347,7 348,7 @@ pub async fn handle_client(
);
let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
reason: GoodbyeReason::UnexpectedPacket.into(),
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
})
.try_into()?;
send!(client_tx, msg).await?;
@@ 388,11 389,12 @@ pub async fn handle_client(
let mut handle = entities.write().await;
let id = handle
.get_player_id(remote_addr)
- .expect("could not get player id");
+ .ok_or("could not get player id")?;
+
if let Entity::Player(ref mut me) = handle
.entities
.get_mut(&id)
- .expect("player disconnected but continued to send packets")
+ .ok_or("player disconnected but continued to send packets")?
{
me.input.up = p.up_pressed;
me.input.down = p.down_pressed;
@@ 410,7 412,7 @@ pub async fn handle_client(
.read()
.await
.get_player(remote_addr)
- .expect("Player sending messages after disconnect");
+ .ok_or("Player sending messages after disconnect")?;
if Some(p.token) != player.auth_token || Some(p.user_id) != player.auth_user
{
@@ 420,9 422,9 @@ pub async fn handle_client(
match save_player_data_to_api(
&player.as_api_data(),
- &player.auth_token.unwrap(),
- &player.auth_user.unwrap(),
- &std::env::var("STK_API_KEY").unwrap(),
+ &player.auth_token.ok_or("Tried to beamout without an auth token")?,
+ &player.auth_user.ok_or("Tried to beamout without setting a user")?,
+ &std::env::var("STK_API_KEY")?,
)
.await
{
@@ 451,19 453,24 @@ pub async fn handle_client(
//debug!("[{}] detach: {:?}", remote_addr, p);
//debug!("[{}] {:?}", remote_addr, entities.entities);
- if let Some(Entity::AttachedModule(p_module)) = entities.entities.get_mut(&p.module_id) {
+ if let Some(Entity::AttachedModule(p_module)) =
+ entities.entities.get_mut(&p.module_id)
+ {
module = Some(p_module.clone());
} else {
warn!("[{}] attempted to detach nonexistent module", remote_addr);
continue;
}
- let player_id = entities.get_player_id(remote_addr).unwrap();
- let module_id = AttachedModule::detach(&mut data_handle, &mut entities,
- player_id,
- module.unwrap());
- let module = entities.get_module_from_id(module_id).unwrap();
- let body = data_handle.rigid_body_set.get(module.handle).unwrap();
+ let player_id = entities.get_player_id(remote_addr).ok_or("player does not exist")?;
+ let module_id = AttachedModule::detach(
+ &mut data_handle,
+ &mut entities,
+ player_id,
+ module.ok_or("cannot detach module that doesn't exist")?,
+ ).ok_or("detach failed")?;
+ let module = entities.get_module_from_id(module_id).ok_or("player does not exist")?;
+ let body = data_handle.rigid_body_set.get(module.handle).ok_or("module rigidbody does not exist")?;
let prot_module = starkingdoms_protocol::module::Module {
module_type: module.module_type.into(),
rotation: body.rotation().angle(),
@@ 471,17 478,23 @@ pub async fn handle_client(
y: body.translation().y * SCALE,
id: module_id,
flags: module.flags,
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
};
let msg = MessageS2C::ModuleRemove(MessageS2CModuleRemove {
module: Some(prot_module).into(),
- special_fields: Default::default(),
+ special_fields: SpecialFields::default(),
})
.try_into()?;
send!(client_tx, msg).await?;
}
MessageC2S::ModuleGrabBegin(p) => {
- if let Entity::Module(_module) = entities.write().await.entities.get_mut(&p.module_id).unwrap() {
+ if let Entity::Module(_module) = entities
+ .write()
+ .await
+ .entities
+ .get_mut(&p.module_id)
+ .ok_or("module does not exist")?
+ {
//debug!("[{}] grab begin: {:?}, flags: {}", remote_addr, p, module.flags);
}
}
@@ 490,75 503,139 @@ pub async fn handle_client(
let mut module: Option<Module> = None;
let mut did_attach = false;
let mut attached_id = None;
- if let Entity::Module(p_module) = entities.entities.get_mut(&p.module_id).unwrap() {
+ if let Entity::Module(p_module) =
+ entities.entities.get_mut(&p.module_id).ok_or("module does not exist")?
+ {
module = Some(p_module.clone());
//debug!("[{}] grab end: {:?}", remote_addr, p);
}
let mut data_handle = data.write().await;
- let player_id = entities.get_player_id(remote_addr).unwrap();
- let player = entities.get_player(remote_addr).unwrap();
- let body = data_handle.rigid_body_set.get(player.handle).unwrap();
- let (x, y) = (body.translation().x - p.worldpos_x/SCALE, body.translation().y - p.worldpos_y/SCALE);
+ let player_id = entities.get_player_id(remote_addr).ok_or("player entity does not exist")?;
+ let player = entities.get_player(remote_addr).ok_or("player does not exist")?;
+ let body = data_handle.rigid_body_set.get(player.handle).ok_or("player rigidbody does not exist")?;
+ let (x, y) = (
+ body.translation().x - p.worldpos_x / SCALE,
+ body.translation().y - p.worldpos_y / SCALE,
+ );
let angle = -body.rotation().angle();
- let (x, y) = (x*angle.cos() - y*angle.sin(), x*angle.sin() + y*angle.cos());
+ let (x, y) = (
+ x.mul_add(angle.cos(), -y * angle.sin()),
+ x.mul_add(angle.sin(), y * angle.cos()),
+ );
if 1.5 < y && y < 3. && -2. < x && x < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- player_id,
- player_id, module.clone().unwrap(), 2));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ player_id,
+ player_id,
+ module.clone().ok_or("module is None")?,
+ 2,
+ ));
did_attach = true;
} else if -3. < y && y < -1.5 && -2. < x && x < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- player_id,
- player_id, module.clone().unwrap(), 0));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ player_id,
+ player_id,
+ module.clone().ok_or("module is None")?,
+ 0,
+ ));
did_attach = true;
} else if -3. < x && x < -1.5 && -2. < y && y < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- player_id,
- player_id, module.clone().unwrap(), 3));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ player_id,
+ player_id,
+ module.clone().ok_or("module is None")?,
+ 3,
+ ));
did_attach = true;
} else if 1.5 < x && x < 3. && -2. < y && y < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- player_id,
- player_id, module.clone().unwrap(), 1));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ player_id,
+ player_id,
+ module.clone().ok_or("module is None")?,
+ 1,
+ ));
did_attach = true;
}
let modules = player.search_modules(&entities);
for attached in modules {
- let body = data_handle.rigid_body_set.get(attached.handle).unwrap();
- let (x, y) = (body.translation().x - p.worldpos_x/SCALE, body.translation().y - p.worldpos_y/SCALE);
+ let body = data_handle.rigid_body_set.get(attached.handle).ok_or("attached module rigidbody does not exist")?;
+ let (x, y) = (
+ body.translation().x - p.worldpos_x / SCALE,
+ body.translation().y - p.worldpos_y / SCALE,
+ );
let angle = -body.rotation().angle();
- let (x, y) = (x*angle.cos() - y*angle.sin(), x*angle.sin() + y*angle.cos());
- let parent_id = entities.get_id_from_attached(attached).unwrap();
+ let (x, y) = (
+ x.mul_add(angle.cos(), -y * angle.sin()),
+ x.mul_add(angle.sin(), y * angle.cos()),
+ );
+ let parent_id = entities.get_id_from_attached(&attached).ok_or("attached module does not exist")?;
+
+ // ghostly: this is cursed as hell
+ // please find a better way in the future lmao
if 1.5 < y && y < 3. && -2. < x && x < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- parent_id,
- player_id, module.clone().unwrap(), 2));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ parent_id,
+ player_id,
+ module.clone().ok_or("module does not exist")?,
+ 2,
+ ));
did_attach = true;
} else if -3. < x && x < -1.5 && -2. < y && y < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- parent_id,
- player_id, module.clone().unwrap(), 3));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ parent_id,
+ player_id,
+ module.clone().ok_or("module does not exist")?,
+ 3,
+ ));
did_attach = true;
} else if 1.5 < x && x < 3. && -2. < y && y < 2. {
- attached_id = Some(AttachedModule::attach(&mut data_handle, &mut entities,
- parent_id,
- player_id, module.clone().unwrap(), 1));
+ attached_id = Some(AttachedModule::attach(
+ &mut data_handle,
+ &mut entities,
+ parent_id,
+ player_id,
+ module.clone().ok_or("module does not exist")?,
+ 1,
+ ));
did_attach = true;
}
}
- if did_attach == false {
- let body = data_handle.rigid_body_set.get_mut(module.unwrap().handle).unwrap();
- body.set_position(Isometry::new(Vector2::new(p.worldpos_x/SCALE, p.worldpos_y/SCALE),body.rotation().angle()), true);
+ if !did_attach {
+ let body = data_handle
+ .rigid_body_set
+ .get_mut(module.ok_or("module does not exist")?.handle)
+ .ok_or("module rigidbody does not exist")?;
+ body.set_position(
+ Isometry::new(
+ Vector2::new(p.worldpos_x / SCALE, p.worldpos_y / SCALE),
+ body.rotation().angle(),
+ ),
+ true,
+ );
+ } else if let Some(Ok(id)) = attached_id {
+ let prot_module = entities
+ .get_attached_from_id(id)
+ .ok_or("attached module does not exist")?
+ .to_protocol(&entities, &data_handle.rigid_body_set);
+ let msg = MessageS2C::ModuleAdd(MessageS2CModuleAdd {
+ module: Some(prot_module.ok_or("attached module does not exist")?).into(),
+ special_fields: SpecialFields::default(),
+ })
+ .try_into()?;
+ send!(client_tx, msg).await?;
} else {
- if let Some(Ok(id)) = attached_id {
- let prot_module = entities.get_attached_from_id(id).unwrap().to_protocol(&entities, &mut data_handle.rigid_body_set);
- let msg = MessageS2C::ModuleAdd(MessageS2CModuleAdd {
- module: Some(prot_module).into(),
- special_fields: Default::default(),
- })
- .try_into()?;
- send!(client_tx, msg).await?;
- }
+ warn!("attached ID does not exist");
}
}
},
M server/src/main.rs => server/src/main.rs +62 -40
@@ 1,3 1,19 @@
+// StarKingdoms.IO, an open source browser game
+// Copyright (C) 2023 ghostly_zsh (and contributors, depending on the license you choose)
+//
+// <license disclaimer here>
+
+#![warn(clippy::pedantic)]
+#![warn(clippy::nursery)]
+#![deny(clippy::unwrap_used)]
+#![deny(clippy::expect_used)]
+#![allow(clippy::must_use_candidate)]
+#![allow(clippy::too_many_lines)]
+#![allow(clippy::module_name_repetitions)]
+#![allow(clippy::missing_errors_doc)]
+#![allow(clippy::missing_safety_doc)]
+#![allow(clippy::missing_panics_doc)]
+
use crate::entity::Entity;
use crate::handler::handle_client;
use crate::manager::{ClientHandler, ClientManager};
@@ 12,17 28,18 @@ use lazy_static::lazy_static;
use log::{error, info, warn, Level};
use manager::PhysicsData;
use nalgebra::vector;
+use parking_lot::deadlock::check_deadlock;
use rapier2d_f64::prelude::{
BroadPhase, CCDSolver, ColliderSet, ImpulseJointSet, IntegrationParameters, IslandManager,
MultibodyJointSet, NarrowPhase, RigidBodySet,
};
use serde::{Deserialize, Serialize};
use starkingdoms_protocol::PROTOCOL_VERSION;
+use std::collections::HashMap;
use std::error::Error;
use std::net::SocketAddr;
use std::thread;
use std::time::Duration;
-use parking_lot::deadlock::check_deadlock;
pub mod handler;
pub mod manager;
@@ 31,9 48,9 @@ pub mod timer;
pub mod macros;
pub mod api;
pub mod entity;
+pub mod module;
pub mod orbit;
pub mod planet;
-pub mod module;
const SCALE: f64 = 10.0;
@@ 58,7 75,7 @@ async fn _handle_request(
mgr: ClientManager,
entities: Arc<RwLock<EntityHandler>>,
physics_data: Arc<RwLock<PhysicsData>>,
-) -> Result<(), Box<dyn Error>> {
+) -> Result<(), Box<dyn Error + Sync + Send>> {
let mut peek_buf = [0u8; 9];
loop {
@@ 78,10 95,9 @@ async fn _handle_request(
channel: env!("STK_CHANNEL").to_string(),
build: env!("STK_BUILD").to_string(),
},
- players: CMGR.usernames.read().await.len() as u32,
+ players: u32::try_from(CMGR.usernames.read().await.len())?,
description: env!("STK_SLP_DESCRIPTION").to_string(),
- })
- .unwrap();
+ })?;
let resp_str = format!(
"HTTP/1.0 200 OK\nAccess-Control-Allow-Origin: *\nContent-Length: {}\n\n{}",
@@ 130,9 146,11 @@ async fn _handle_request(
{
Ok(_) => (),
Err(e) if e.is::<async_tungstenite::tungstenite::error::Error>() => {
- let e = e
- .downcast::<async_tungstenite::tungstenite::error::Error>()
- .unwrap();
+ #[allow(clippy::expect_used)]
+ let e = {
+ e.downcast::<async_tungstenite::tungstenite::error::Error>().expect("unable to convert between types safely")
+ };
+
if matches!(*e, async_tungstenite::tungstenite::Error::ConnectionClosed) {
info!("[{}] connection closed normally", remote_addr);
} else {
@@ 156,14 174,12 @@ async fn _handle_request(
let mut collider_set = data.collider_set.clone();
let mut impulse_joint_set = data.impulse_joint_set.clone();
let mut multibody_joint_set = data.multibody_joint_set.clone();
- let player_id = match entity_write.get_player_id(remote_addr) {
- Some(s) => s,
- None => {
+ let Some(player_id) = entity_write.get_player_id(remote_addr) else {
warn!("[{}] player missing from entities.players", remote_addr);
return Err("Player missing from entities.players".into());
- }
};
- if let Entity::Player(player) = entity_write.entities.get(&player_id).unwrap() {
+
+ if let Some(Entity::Player(player)) = entity_write.entities.get(&player_id) {
rigid_body_set.remove(
player.handle,
&mut island_manager,
@@ 181,9 197,13 @@ async fn _handle_request(
&mut multibody_joint_set,
true,
);
- let module_id = entity_write.get_id_from_attached(module).unwrap();
+ let module_id = entity_write
+ .get_id_from_attached(&module)
+ .ok_or("Tried to remove nonexistent module")?;
entity_write.entities.remove(&module_id);
}
+ } else {
+ warn!("tried to remove player that doesnt exist: #{}", player_id);
}
data.rigid_body_set = rigid_body_set;
data.collider_set = collider_set;
@@ 198,8 218,8 @@ async fn _handle_request(
lazy_static! {
static ref CMGR: ClientManager = ClientManager {
- handlers: Arc::new(RwLock::new(Default::default())),
- usernames: Arc::new(RwLock::new(Default::default())),
+ handlers: Arc::new(RwLock::new(HashMap::default())),
+ usernames: Arc::new(RwLock::new(HashMap::default())),
};
static ref DATA: Arc<RwLock<PhysicsData>> = Arc::new(RwLock::new(PhysicsData {
gravity: vector![0.0, 0.0],
@@ 224,9 244,13 @@ lazy_static! {
pub const PANIC_ON_DEADLOCK: bool = true;
+//noinspection ALL
#[async_std::main]
async fn main() {
- simple_logger::init_with_level(Level::Debug).expect("Unable to start logging service");
+ #[allow(clippy::expect_used)]
+ {
+ simple_logger::init_with_level(Level::Debug).expect("Unable to start logging service");
+ }
info!(
"StarKingdoms server (v: {}, build {}) - initializing",
@@ 247,31 271,29 @@ async fn main() {
info!("Starting deadlock detector...");
- thread::spawn(move || {
- loop {
- thread::sleep(Duration::from_secs(10));
- let deadlocks = check_deadlock();
- if deadlocks.is_empty() {
- continue;
- }
+ thread::spawn(move || loop {
+ thread::sleep(Duration::from_secs(10));
+ let deadlocks = check_deadlock();
+ if deadlocks.is_empty() {
+ continue;
+ }
- error!("---- DEADLOCK DETECTED ----");
- error!("{} deadlocks were detected.", deadlocks.len());
- for (i, threads) in deadlocks.iter().enumerate() {
- error!("-= Deadlock #{}", i);
- for t in threads {
- error!("-= Thread ID = {:#?}", t.thread_id());
- error!("-= Backtrace:\n{:#?}", t.backtrace());
- }
- }
- if PANIC_ON_DEADLOCK {
- error!("StarKingdoms is configured to panic when deadlocks are detected.");
- error!("Bye!");
- panic!("Deadlock detected on one or more threads");
- } else {
- error!("StarKingdoms is not configured to panic when deadlocks are detected.");
+ error!("---- DEADLOCK DETECTED ----");
+ error!("{} deadlocks were detected.", deadlocks.len());
+ for (i, threads) in deadlocks.iter().enumerate() {
+ error!("-= Deadlock #{}", i);
+ for t in threads {
+ error!("-= Thread ID = {:#?}", t.thread_id());
+ error!("-= Backtrace:\n{:#?}", t.backtrace());
}
}
+ if PANIC_ON_DEADLOCK {
+ error!("StarKingdoms is configured to panic when deadlocks are detected.");
+ error!("Bye!");
+ panic!("Deadlock detected on one or more threads");
+ } else {
+ error!("StarKingdoms is not configured to panic when deadlocks are detected.");
+ }
});
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
M server/src/manager.rs => server/src/manager.rs +14 -13
@@ 1,13 1,10 @@
use async_std::channel::Sender;
use async_std::sync::RwLock;
-
use rapier2d_f64::na::Vector2;
use rapier2d_f64::prelude::{
- BroadPhase, CCDSolver, ColliderSet,
- ImpulseJointSet, IntegrationParameters, IslandManager,
- MultibodyJointSet, NarrowPhase, PhysicsPipeline, RigidBodyHandle,
- RigidBodySet,
+ BroadPhase, CCDSolver, ColliderSet, ImpulseJointSet, IntegrationParameters, IslandManager,
+ MultibodyJointSet, NarrowPhase, PhysicsPipeline, RigidBodyHandle, RigidBodySet,
};
use starkingdoms_protocol::api::APISavedPlayerData;
@@ 18,7 15,7 @@ use std::sync::Arc;
use crate::entity::{Entity, EntityHandler, EntityId};
-use crate::module::{Attachment, AttachedModule};
+use crate::module::{AttachedModule, Attachment};
#[derive(Clone)]
pub struct ClientManager {
@@ 45,25 42,29 @@ impl Player {
pub fn search_modules(&self, entities: &EntityHandler) -> Vec<AttachedModule> {
let mut modules = Vec::new();
for attachment in self.children.iter().flatten() {
- if let Entity::AttachedModule(child_module) =
- entities.entities.get(&attachment.child).unwrap()
+ if let Some(Entity::AttachedModule(child_module)) =
+ entities.entities.get(&attachment.child)
{
modules.append(&mut child_module.search_modules(entities));
}
}
modules
}
- pub fn find_parent(&self, module: AttachedModule, entities: &EntityHandler) -> Option<(u8, EntityId)> {
+ pub fn find_parent(
+ &self,
+ module: &AttachedModule,
+ entities: &EntityHandler,
+ ) -> Option<(u8, EntityId)> {
for (slot, attachment) in self.children.iter().enumerate() {
if let Some(attachment) = attachment {
if let Entity::AttachedModule(child_module) =
- entities.entities.get(&attachment.child).unwrap()
+ entities.entities.get(&attachment.child)?
{
- if *child_module == module {
- return Some((slot as u8, entities.get_player_id(self.addr).unwrap()));
+ if *child_module == *module {
+ return Some((u8::try_from(slot).ok()?, entities.get_player_id(self.addr)?));
}
let parent = child_module.find_parent(module.clone(), entities);
- if let Some(_) = parent {
+ if parent.is_some() {
return parent;
}
}
M server/src/module.rs => server/src/module.rs +93 -127
@@ 1,11 1,18 @@
+use std::error::Error;
use std::f64::consts::PI;
-
-use nalgebra::{Vector2, point, vector, Isometry2, Unit};
-use rapier2d_f64::prelude::{RigidBodyHandle, Real, MassProperties, ColliderBuilder, RigidBodyBuilder, FixedJointBuilder, ImpulseJointHandle, RigidBodySet};
+use nalgebra::{point, vector, Isometry2, Unit, Vector2};
+use rapier2d_f64::prelude::{
+ ColliderBuilder, FixedJointBuilder, ImpulseJointHandle, MassProperties, Real, RigidBodyBuilder,
+ RigidBodyHandle, RigidBodySet,
+};
use starkingdoms_protocol::module::ModuleType;
-use crate::{entity::{EntityId, EntityHandler, Entity, get_entity_id}, manager::PhysicsData, SCALE};
+use crate::{
+ entity::{get_entity_id, Entity, EntityHandler, EntityId},
+ manager::PhysicsData,
+ SCALE,
+};
#[derive(Debug, Clone)]
pub struct Module {
@@ 37,79 44,53 @@ impl AttachedModule {
player_id: EntityId,
module: Module,
attachment_slot: usize,
- ) -> Result<EntityId, ()> {
+ ) -> Result<EntityId, Box<dyn Error + Send + Sync>> {
let mut entity_map = entities.entities.clone();
let parent_entity = entity_map
.get_mut(&parent)
- .expect("parent id does not exist");
+ .ok_or("parent id does not exist")?;
let parent_handle = match parent_entity {
Entity::Player(player) => {
- if let Some(_child) = &player.children[attachment_slot] {
- return Err(());
- } else {
- player.handle
+ if player.children[attachment_slot].is_some() {
+ return Err("already attached".into());
}
- },
+ player.handle
+ }
Entity::AttachedModule(module) => {
- if let Some(_child) = &module.children[attachment_slot] {
- return Err(());
- } else {
- module.handle
+ if module.children[attachment_slot].is_some() {
+ return Err("already attached".into());
}
- },
+ module.handle
+ }
_ => {
panic!("unexpected parent");
}
};
- let parent_body = data.rigid_body_set.get(parent_handle).expect("Parent body does not exist");
+ let parent_body = data
+ .rigid_body_set
+ .get(parent_handle).ok_or("parent body does not exist")?;
let parent_pos = vector![parent_body.translation().x, parent_body.translation().y];
let parent_angle = parent_body.rotation().angle();
- let parent_linvel = parent_body.linvel().clone();
+ let parent_linvel = *parent_body.linvel();
let parent_angvel = parent_body.angvel();
let (anchor, rotation) = match attachment_slot {
- 0 => {
- (point![
- 0. / SCALE,
- 53. / SCALE
- ], PI)
- }
- 1 => {
- (point![
- -53. / SCALE,
- 0. / SCALE
- ], -PI/2.)
- }
- 2 => {
- (point![
- 0. / SCALE,
- -53. / SCALE
- ], 0.)
- }
- 3 => {
- (point![
- 53. / SCALE,
- 0. / SCALE
- ], PI/2.)
- }
- _ => {
- (point![
- 0. / SCALE,
- 53. / SCALE
- ], 0.)
- }
+ 0 => (point![0. / SCALE, 53. / SCALE], PI),
+ 1 => (point![-53. / SCALE, 0. / SCALE], -PI / 2.),
+ 2 => (point![0. / SCALE, -53. / SCALE], 0.),
+ 3 => (point![53. / SCALE, 0. / SCALE], PI / 2.),
+ _ => (point![0. / SCALE, 53. / SCALE], 0.),
};
if let Some(id) = entities.get_from_module(&module) {
- let relative_pos =
- vector![anchor.x * (parent_body.rotation().angle()).cos() +
- anchor.y * -(parent_body.rotation().angle()).sin(),
- anchor.x * (parent_body.rotation().angle()).sin() +
- anchor.y * (parent_body.rotation().angle()).cos()];
+ let relative_pos = vector![
+ anchor.x.mul_add((parent_body.rotation().angle()).cos(), anchor.y * -(parent_body.rotation().angle()).sin()),
+ anchor.x.mul_add((parent_body.rotation().angle()).sin(), anchor.y * (parent_body.rotation().angle()).cos())
+ ];
let module_pos = parent_pos + relative_pos;
- let module_body = data.rigid_body_set.get_mut(module.handle).unwrap();
+ let module_body = data.rigid_body_set.get_mut(module.handle).ok_or("module body does not exist")?;
module_body.set_translation(module_pos, true);
module_body.set_rotation(Unit::from_angle(parent_angle + rotation), true);
module_body.set_linvel(parent_linvel, true);
@@ 123,7 104,7 @@ impl AttachedModule {
let attach_joint_handle =
data.impulse_joint_set
.insert(parent_handle, module.handle, attach_joint, true);
- let attached_module = AttachedModule {
+ let attached_module = Self {
handle: module.handle,
module_type: module.module_type,
player_id,
@@ 152,23 133,22 @@ impl AttachedModule {
entities.entities = entity_map;
return Ok(attached_id);
}
- Err(())
+ Err("entity does not exist".into())
}
pub fn detach(
data: &mut PhysicsData,
entities: &mut EntityHandler,
player_id: EntityId,
- module: AttachedModule,
- ) -> EntityId {
+ module: Self,
+ ) -> Option<EntityId> {
let mut entity_map = entities.entities.clone();
// player not in parent search
// also no parents included in parent search
- let player = entities.get_player_from_id(player_id).unwrap();
- let (slot, parent_id) = player.find_parent(module.clone(), entities).unwrap();
+ let player = entities.get_player_from_id(player_id)?;
+ let (slot, parent_id) = player.find_parent(&module, entities)?;
let parent_entity = entity_map
- .get_mut(&parent_id)
- .expect("parent id does not exist");
+ .get_mut(&parent_id)?;
match parent_entity {
Entity::Player(ref mut player) => {
@@ 195,28 175,28 @@ impl AttachedModule {
lifetime: 0.,
flags: 0,
};
- entity_map.remove(&entities.get_id_from_attached(module.clone()).unwrap());
+ entity_map.remove(&entities.get_id_from_attached(&module)?);
let id = get_entity_id();
entity_map.insert(id, Entity::Module(new_module));
for element in tree {
for child in element.clone().children {
if let Some(child) = child {
data.impulse_joint_set.remove(child.connection, true);
- let child_body = entities.get_attached_from_id(child.child).unwrap();
+ let child_body = entities.get_attached_from_id(child.child)?;
let new_module = Module {
handle: child_body.handle,
module_type: child_body.module_type,
lifetime: 0.,
flags: 0,
};
- entity_map.remove(&entities.get_id_from_attached(child_body.clone()).unwrap());
+ entity_map.remove(&entities.get_id_from_attached(&child_body)?);
let attached_id = get_entity_id();
entity_map.insert(attached_id, Entity::Module(new_module));
}
}
}
entities.entities = entity_map;
- id
+ Some(id)
}
pub fn attach_new(
data: &mut PhysicsData,
@@ 225,12 205,11 @@ impl AttachedModule {
player_id: EntityId,
module: ModuleTemplate,
attachment_slot: usize,
- ) -> EntityId {
+ ) -> Option<EntityId> {
let mut entity_map = entities.entities.clone();
let parent_entity = entity_map
- .get_mut(&parent)
- .expect("parent id does not exist");
+ .get_mut(&parent)?;
let parent_handle = match parent_entity {
Entity::Player(player) => player.handle,
Entity::AttachedModule(module) => module.handle,
@@ 239,47 218,23 @@ impl AttachedModule {
}
};
- let parent_body = data.rigid_body_set.get(parent_handle).expect("Parent body does not exist");
+ let parent_body = data
+ .rigid_body_set
+ .get(parent_handle)?;
let parent_pos = vector![parent_body.translation().x, parent_body.translation().y];
let (anchor, rotation) = match attachment_slot {
- 0 => {
- (point![
- 0. / SCALE,
- 53. / SCALE
- ], PI)
- }
- 1 => {
- (point![
- -53. / SCALE,
- 0. / SCALE
- ], -PI/2.)
- }
- 2 => {
- (point![
- 0. / SCALE,
- -53. / SCALE
- ], 0.)
- }
- 3 => {
- (point![
- 53. / SCALE,
- 0. / SCALE
- ], PI/2.)
- }
- _ => {
- (point![
- 0. / SCALE,
- 53. / SCALE
- ], 0.)
- }
+ 0 => (point![0. / SCALE, 53. / SCALE], PI),
+ 1 => (point![-53. / SCALE, 0. / SCALE], -PI / 2.),
+ 2 => (point![0. / SCALE, -53. / SCALE], 0.),
+ 3 => (point![53. / SCALE, 0. / SCALE], PI / 2.),
+ _ => (point![0. / SCALE, 53. / SCALE], 0.),
};
- let relative_pos =
- vector![anchor.x * (parent_body.rotation().angle()).cos() +
- anchor.y * -(parent_body.rotation().angle()).sin(),
- anchor.x * (parent_body.rotation().angle()).sin() +
- anchor.y * (parent_body.rotation().angle()).cos()];
+ let relative_pos = vector![
+ anchor.x.mul_add((parent_body.rotation().angle()).cos(), anchor.y * -(parent_body.rotation().angle()).sin()),
+ anchor.x.mul_add((parent_body.rotation().angle()).sin(), anchor.y * (parent_body.rotation().angle()).cos())
+ ];
let module_pos = parent_pos + relative_pos;
// create attachment module
@@ 305,7 260,7 @@ impl AttachedModule {
let attach_joint_handle =
data.impulse_joint_set
.insert(parent_handle, attached_handle, attach_joint, true);
- let attached_module = AttachedModule {
+ let attached_module = Self {
handle: attached_handle,
module_type: module.module_type,
player_id,
@@ 331,7 286,7 @@ impl AttachedModule {
};
entity_map.insert(attached_id, Entity::AttachedModule(attached_module));
entities.entities = entity_map;
- attached_id
+ Some(attached_id)
}
// TODO: remove this function
pub fn to_module(&self) -> Module {
@@ 343,17 298,24 @@ impl AttachedModule {
}
}
// TODO: this one too
- pub fn to_module_id(&self, entities: &EntityHandler) -> (EntityId, Module) {
- (entities.get_id_from_attached(self.clone()).unwrap(), Module {
- handle: self.handle,
- module_type: self.module_type,
- lifetime: 10.,
- flags: 1,
- })
+ pub fn to_module_id(&self, entities: &EntityHandler) -> Option<(EntityId, Module)> {
+ Some((
+ entities.get_id_from_attached(self)?,
+ Module {
+ handle: self.handle,
+ module_type: self.module_type,
+ lifetime: 10.,
+ flags: 1,
+ },
+ ))
}
- pub fn to_protocol(&self, entities: &EntityHandler, data: &RigidBodySet) -> starkingdoms_protocol::module::AttachedModule {
- let body = data.get(self.handle).unwrap();
+ pub fn to_protocol(
+ &self,
+ entities: &EntityHandler,
+ data: &RigidBodySet,
+ ) -> Option<starkingdoms_protocol::module::AttachedModule> {
+ let body = data.get(self.handle)?;
let children = self.children.to_vec();
let mut prot_children = Vec::new();
for i in 1..children.len() {
@@ 365,22 327,22 @@ impl AttachedModule {
});
}
}
- starkingdoms_protocol::module::AttachedModule {
+ Some(starkingdoms_protocol::module::AttachedModule {
module_type: self.module_type.into(),
rotation: body.rotation().angle(),
x: body.translation().x * SCALE,
y: body.translation().y * SCALE,
- id: entities.get_id_from_attached(self.clone()).unwrap(),
+ id: entities.get_id_from_attached(self)?,
children: prot_children,
special_fields: Default::default(),
- }
+ })
}
- pub fn search_modules(&self, entities: &EntityHandler) -> Vec<AttachedModule> {
+ pub fn search_modules(&self, entities: &EntityHandler) -> Vec<Self> {
let mut modules = vec![self.clone()];
for attachment in self.children.iter().flatten() {
- if let Entity::AttachedModule(child_module) =
- entities.entities.get(&attachment.child).unwrap()
+ if let Some(Entity::AttachedModule(child_module)) =
+ entities.entities.get(&attachment.child)
{
modules.append(&mut child_module.search_modules(entities));
}
@@ 388,17 350,21 @@ impl AttachedModule {
modules
}
- pub fn find_parent(&self, module: AttachedModule, entities: &EntityHandler) -> Option<(u8, EntityId)> {
+ pub fn find_parent(
+ &self,
+ module: Self,
+ entities: &EntityHandler,
+ ) -> Option<(u8, EntityId)> {
for (slot, attachment) in self.children.iter().enumerate() {
if let Some(attachment) = attachment {
if let Entity::AttachedModule(child_module) =
- entities.entities.get(&attachment.child).unwrap()
+ entities.entities.get(&attachment.child)?
{
if *child_module == module {
- return Some((slot as u8, entities.get_id_from_attached(self.clone()).unwrap()));
+ return Some((slot as u8, entities.get_id_from_attached(self)?));
}
let parent = child_module.find_parent(module.clone(), entities);
- if let Some(_) = parent {
+ if parent.is_some() {
return parent;
}
}
@@ 408,7 374,7 @@ impl AttachedModule {
}
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Attachment {
pub child: EntityId,
pub connection: ImpulseJointHandle,
M server/src/orbit/constants.rs => server/src/orbit/constants.rs +8 -8
@@ 1,6 1,6 @@
-pub const GAME_SCALE_DISTANCE: f64 = 0.0001567865; // 1000 / EARTH_RADIUS_RL
-pub const GAME_SCALE_MASS: f64 = 0.0000000000000000000006697923643670463; // 4000 / EARTH_MASS_RL
-pub const GAME_SCALE_TIME: f64 = 0.00051440329218107; // 1200 / MOON_ORBIT_TIME_RL
+pub const GAME_SCALE_DISTANCE: f64 = 0.000_156_786_5; // 1000 / EARTH_RADIUS_RL
+pub const GAME_SCALE_MASS: f64 = 0.000_000_000_000_000_000_000_669_792_364_367_046_3; // 4000 / EARTH_MASS_RL
+pub const GAME_SCALE_TIME: f64 = 0.000_514_403_292_181_07; // 1200 / MOON_ORBIT_TIME_RL
pub const GAME_ORBITS_ENABLED: bool = false;
pub const EARTH_RADIUS_BIAS: f64 = 1.0;
@@ 8,7 8,7 @@ pub const EARTH_MASS_BIAS: f64 = 1.0;
pub const EARTH_RADIUS_RL: f64 = 6_378_100.0;
pub const EARTH_RADIUS: f64 = EARTH_RADIUS_RL * GAME_SCALE_DISTANCE * EARTH_RADIUS_BIAS;
-pub const EARTH_MASS_RL: f64 = 5972000000000000000000000.0;
+pub const EARTH_MASS_RL: f64 = 5_972_000_000_000_000_000_000_000.0;
pub const EARTH_MASS: f64 = EARTH_MASS_RL * GAME_SCALE_MASS * EARTH_MASS_BIAS;
pub const MOON_RADIUS_BIAS: f64 = 1.0;
@@ 19,9 19,9 @@ pub const MOON_ORBIT_TIME_BIAS: f64 = 1.0;
pub const MOON_RADIUS_RL: f64 = 1_737_400.0;
pub const MOON_RADIUS: f64 = MOON_RADIUS_RL * GAME_SCALE_DISTANCE * MOON_RADIUS_BIAS;
-pub const MOON_MASS_RL: f64 = 73476730900000000000000.0;
+pub const MOON_MASS_RL: f64 = 73_476_730_900_000_000_000_000.0;
pub const MOON_MASS: f64 = MOON_MASS_RL * GAME_SCALE_MASS * MOON_MASS_BIAS;
-pub const MOON_PERIAPSIS: f64 = 363228900.0 * GAME_SCALE_DISTANCE * MOON_PERIAPSIS_BIAS;
-pub const MOON_APOAPSIS: f64 = 405400000.0 * GAME_SCALE_DISTANCE * MOON_APOAPSIS_BIAS;
-pub const MOON_ORBIT_TIME_RL: f64 = 2332800.0;
+pub const MOON_PERIAPSIS: f64 = 363_228_900.0 * GAME_SCALE_DISTANCE * MOON_PERIAPSIS_BIAS;
+pub const MOON_APOAPSIS: f64 = 405_400_000.0 * GAME_SCALE_DISTANCE * MOON_APOAPSIS_BIAS;
+pub const MOON_ORBIT_TIME_RL: f64 = 2_332_800.0;
pub const MOON_ORBIT_TIME: f64 = MOON_ORBIT_TIME_RL * GAME_SCALE_TIME * MOON_ORBIT_TIME_BIAS;
M server/src/orbit/kepler.rs => server/src/orbit/kepler.rs +1 -1
@@ 3,5 3,5 @@
/// E is the Eccentric Anomaly (angle to where the body is on the ellipse)
/// e is the eccentricity of the orbit (0 = perfect circle, and up to 1 is increasingly elliptical)
pub fn kepler_equation(eccentric_anomaly: f64, mean_anomaly: f64, eccentricity: f64) -> f64 {
- mean_anomaly - eccentric_anomaly + eccentricity * eccentric_anomaly.sin()
+ eccentricity.mul_add(eccentric_anomaly.sin(), mean_anomaly - eccentric_anomaly)
}
M server/src/orbit/newtonian.rs => server/src/orbit/newtonian.rs +1 -1
@@ 1,7 1,7 @@
use crate::orbit::kepler::kepler_equation;
pub const NEWTONIAN_STEP_SIZE: f64 = 0.0001;
-pub const NEWTONIAN_ACCEPTABLE_ERROR: f64 = 0.00000001;
+pub const NEWTONIAN_ACCEPTABLE_ERROR: f64 = 0.000_000_01;
pub fn solve_kepler_with_newtonian(
mean_anomaly: f64,
M server/src/orbit/orbit.rs => server/src/orbit/orbit.rs +12 -5
@@ 16,8 16,9 @@ pub fn calculate_vector_of_orbit(
mass: f64,
step: f64,
) -> Vector2<f64> {
- let semi_major_length = (apoapsis + periapsis) / 2.0;
- let _linear_eccentricity = semi_major_length - periapsis; // distance between center and focus
+ // this doesnt actually do anything
+ //let semi_major_length = (apoapsis + periapsis) / 2.0;
+ //let linear_eccentricity = semi_major_length - periapsis; // distance between center and focus
let target = calculate_world_position_of_orbit(
calculate_point_on_orbit(periapsis, apoapsis, t),
@@ 45,14 46,20 @@ pub fn calculate_point_on_orbit(periapsis: f64, apoapsis: f64, t: f64) -> Vector
let semi_major_length = (apoapsis + periapsis) / 2.0;
let linear_eccentricity = semi_major_length - periapsis; // distance between center and focus
let eccentricity = linear_eccentricity / semi_major_length; // 0: circle. 1: parabola. in between: ellipse
- let semi_minor_length =
- (semi_major_length * semi_major_length - linear_eccentricity * linear_eccentricity).sqrt();
+ let semi_minor_length = semi_major_length
+ .mul_add(
+ semi_major_length,
+ -linear_eccentricity * linear_eccentricity,
+ )
+ .sqrt();
let mean_anomaly = t * std::f64::consts::PI * 2.0;
let eccentric_anomaly = solve_kepler_with_newtonian(mean_anomaly, eccentricity, 100);
let ellipse_center_x = -linear_eccentricity;
- let point_x = eccentric_anomaly.cos() * semi_major_length + ellipse_center_x;
+ let point_x = eccentric_anomaly
+ .cos()
+ .mul_add(semi_major_length, ellipse_center_x);
let point_y = eccentric_anomaly.sin() * semi_minor_length;
vector![point_x, point_y]
M server/src/planet.rs => server/src/planet.rs +5 -7
@@ 1,4 1,3 @@
-
use nalgebra::{vector, Vector2};
use rapier2d_f64::prelude::{
ColliderBuilder, ColliderSet, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
@@ 26,9 25,7 @@ pub struct Planet {
impl Planet {
pub fn gravity(&self, position: (f64, f64), mass: f64) -> (f64, f64) {
- let distance = ((position.0 - self.position.0).powi(2)
- + (position.1 - self.position.1).powi(2))
- .sqrt();
+ let distance = (position.0 - self.position.0).hypot(position.1 - self.position.1);
let force = GRAVITY * ((self.mass * mass) / (distance * distance));
let mut direction =
Vector2::new(self.position.0 - position.0, self.position.1 - position.1);
@@ 88,7 85,7 @@ impl Planets {
entities: &mut Entities,
) -> Vec<EntityId> {
let mut planet_ids: Vec<EntityId> = Vec::new();
- let (earth_id, entity) = Planets::make_planet(
+ let (earth_id, entity) = Self::make_planet(
"earth",
PlanetType::Earth,
EARTH_MASS,
@@ 102,7 99,8 @@ impl Planets {
planet_ids.push(earth_id);
let moon_start_point;
- if let Entity::Planet(earth) = entities.get(&earth_id).unwrap() {
+ #[allow(clippy::expect_used)]
+ if let Entity::Planet(earth) = entities.get(&earth_id).expect("earth does not exist") {
moon_start_point = calculate_world_position_of_orbit(
calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, 0.0),
vector![earth.position.0, earth.position.1],
@@ 111,7 109,7 @@ impl Planets {
moon_start_point = vector![0., 0.];
}
- let (moon_id, moon) = Planets::make_planet(
+ let (moon_id, moon) = Self::make_planet(
"moon",
PlanetType::Moon,
MOON_MASS,
M server/src/timer.rs => server/src/timer.rs +68 -56
@@ 12,24 12,24 @@ use crate::{
};
use async_std::sync::RwLock;
use async_std::task::sleep;
-use log::{warn};
+use log::warn;
use nalgebra::{point, vector};
use rand::Rng;
-use rapier2d_f64::prelude::{
- ColliderBuilder, MassProperties, PhysicsPipeline, RigidBodyBuilder,
-};
+use rapier2d_f64::prelude::{ColliderBuilder, MassProperties, PhysicsPipeline, RigidBodyBuilder};
use starkingdoms_protocol::{module::ModuleType, planet::PlanetType, player::Player};
use std::{f64::consts::PI, sync::Arc, time::Duration};
+use std::error::Error;
pub const LATERAL_FORCE: f64 = 0.0002;
pub const MODULE_SPAWN: f64 = 3.0;
pub const MODULE_MAX: u32 = 10;
+//noinspection ALL
pub async fn timer_main(
mgr: ClientManager,
physics_data_orig: Arc<RwLock<PhysicsData>>,
entities: Arc<RwLock<EntityHandler>>,
-) {
+) -> Result<(), Box<dyn Error>> {
let mut pipeline = PhysicsPipeline::new();
let mut time = 0.0;
@@ 68,11 68,11 @@ pub async fn timer_main(
let planets = entities.write().await;
// update earth (nothing changes, yet)
- let earth = planets.get_planet(PlanetType::Earth).unwrap();
+ let earth = planets.get_planet(PlanetType::Earth).ok_or("earth does not exist")?;
let new_earth_position = vector![earth.position.0, earth.position.1];
// update moon
- let moon: &mut Planet = &mut planets.get_planet(PlanetType::Moon).unwrap();
+ let moon: &mut Planet = &mut planets.get_planet(PlanetType::Moon).ok_or("moon does not exist")?;
let new_moon_position = calculate_world_position_of_orbit(
calculate_point_on_orbit(MOON_PERIAPSIS, MOON_APOAPSIS, time / MOON_ORBIT_TIME),
new_earth_position,
@@ 80,7 80,7 @@ pub async fn timer_main(
let moon_body = physics_data
.rigid_body_set
.get_mut(moon.body_handle)
- .unwrap();
+ .ok_or("moon does not exist")?;
moon_body.set_next_kinematic_position(new_moon_position.into());
moon.position = (
moon_body.translation()[0] / SCALE,
@@ 137,9 137,9 @@ pub async fn timer_main(
.insert(get_entity_id(), Entity::Module(module));
}
let mut entities = entities.write().await;
- for module in entities.get_modules().iter_mut() {
+ for module in &mut entities.get_modules() {
let module_handle = module.handle;
- let module_body = physics_data.rigid_body_set.get_mut(module_handle).unwrap();
+ let module_body = physics_data.rigid_body_set.get_mut(module_handle).ok_or("module does not exist")?;
module_body.reset_forces(true);
module_body.reset_torques(true);
let grav_force = entities.gravity(
@@ 147,8 147,8 @@ pub async fn timer_main(
module_body.mass(),
);
module_body.apply_impulse(vector![grav_force.0, grav_force.1], true);
- let id = entities.get_from_module(module).unwrap();
- if let Entity::Module(p_module) = entities.entities.get_mut(&id).unwrap() {
+ let id = entities.get_from_module(module).ok_or("module entity does not exist")?;
+ if let Entity::Module(p_module) = entities.entities.get_mut(&id).ok_or("module does not exist")? {
p_module.lifetime += 5. / 1000.;
}
if module.lifetime > 80. {
@@ 173,9 173,9 @@ pub async fn timer_main(
entities.entities.remove(&id);
}
}
- for module in entities.get_all_attached().iter_mut() {
+ for module in &mut entities.get_all_attached() {
let module_handle = module.handle;
- let module_body = physics_data.rigid_body_set.get_mut(module_handle).unwrap();
+ let module_body = physics_data.rigid_body_set.get_mut(module_handle).ok_or("module does not exist")?;
module_body.reset_forces(true);
module_body.reset_torques(true);
let grav_force = entities.gravity(
@@ 187,9 187,9 @@ pub async fn timer_main(
}
{
- for (player_id, player) in entities.read().await.get_players().iter() {
+ for (player_id, player) in &entities.read().await.get_players() {
let player_handle = player.handle;
- let player_body = physics_data.rigid_body_set.get_mut(player_handle).unwrap();
+ let player_body = physics_data.rigid_body_set.get_mut(player_handle).ok_or("player body does not exist")?;
player_body.reset_forces(true);
player_body.reset_torques(true);
let planets = entities.read().await;
@@ 245,20 245,20 @@ pub async fn timer_main(
right_bottom_thruster / scale * rotation.cos()
];
let top_left_point = point![
- -25. / scale * rotation.cos() + 25. / scale * rotation.sin(),
- -25. / scale * rotation.sin() - 25. / scale * rotation.cos()
+ (-25. / scale).mul_add(rotation.cos(), 25. / scale * rotation.sin()),
+ (-25. / scale).mul_add(rotation.sin(), -25. / scale * rotation.cos())
] + player_body.translation();
let top_right_point = point![
- 25. / scale * rotation.cos() + 25. / scale * rotation.sin(),
- 25. / scale * rotation.sin() - 25. / scale * rotation.cos()
+ (25. / scale).mul_add(rotation.cos(), 25. / scale * rotation.sin()),
+ (25. / scale).mul_add(rotation.sin(), -25. / scale * rotation.cos())
] + player_body.translation();
let bottom_left_point = point![
- -25. / scale * rotation.cos() - 25. / scale * rotation.sin(),
- -25. / scale * rotation.sin() + 25. / scale * rotation.cos()
+ (-25. / scale).mul_add(rotation.cos(), -25. / scale * rotation.sin()),
+ (-25. / scale).mul_add(rotation.sin(), 25. / scale * rotation.cos())
] + player_body.translation();
let bottom_right_point = point![
- 25. / scale * rotation.cos() - 25. / scale * rotation.sin(),
- 25. / scale * rotation.sin() + 25. / scale * rotation.cos()
+ (25. / scale).mul_add(rotation.cos(), -25. / scale * rotation.sin()),
+ (25. / scale).mul_add(rotation.sin(), 25. / scale * rotation.cos())
] + player_body.translation();
player_body.add_force_at_point(left_top_thruster, top_left_point, true);
@@ 271,10 271,9 @@ pub async fn timer_main(
let username;
{
let usernames = mgr.usernames.read().await;
- username = usernames.get(player_id).unwrap().clone();
+ username = usernames.get(player_id).ok_or("username does not exist")?.clone();
}
- // TODO: Figure out how to adjust codegen to use f64
protocol_players.push(Player {
rotation,
x: (translation.x * SCALE),
@@ 290,7 289,7 @@ pub async fn timer_main(
let mut mgr_w = mgr.handlers.write().await;
let mgr_r = mgr_w.clone();
- for (addr, client_thread) in mgr_r.iter() {
+ for (addr, client_thread) in &mgr_r {
match client_thread.tx.send(ClientHandlerMessage::Tick).await {
Ok(_) => {
match client_thread
@@ 308,44 307,53 @@ pub async fn timer_main(
let modules = entities.read().await.get_modules_id();
let entities = entities.read().await;
let this_player = entities.get_player_id(*addr);
- let mut attached_modules: Vec<starkingdoms_protocol::module::AttachedModule> = Vec::new();
+ let mut attached_modules: Vec<starkingdoms_protocol::module::AttachedModule> =
+ Vec::new();
let unattached_modules = entities.get_all_attached();
- let mut unattached_modules: Vec<starkingdoms_protocol::module::Module> = unattached_modules
- .iter()
- .filter(|m| {
- match this_player {
+ let mut unattached_modules: Vec<starkingdoms_protocol::module::Module> =
+ unattached_modules
+ .iter()
+ .filter(|m| match this_player {
Some(id) => {
if m.player_id != id {
true
} else {
- attached_modules.push(m.to_protocol(&entities, &physics_data.rigid_body_set));
+ #[allow(clippy::expect_used)] {
+ attached_modules.push(
+ m.to_protocol(&entities, &physics_data.rigid_body_set).expect("module does not exist"),
+ );
+ }
false
}
}
- None => {
- true
+ None => true,
+ })
+ .map(|m| {
+ let id;
+ let module;
+ #[allow(clippy::expect_used)] { (id, module) = m.to_module_id(&entities).expect("unable to get module id"); }
+ //info!("{:?}", module);
+ let body;
+ #[allow(clippy::expect_used)] { body = physics_data.rigid_body_set.get(module.handle).expect("module body does not exist"); }
+
+ starkingdoms_protocol::module::Module {
+ module_type: module.module_type.into(),
+ rotation: body.rotation().angle(),
+ x: body.translation().x * SCALE,
+ y: body.translation().y * SCALE,
+ id,
+ flags: module.flags,
+ special_fields: Default::default(),
}
- }
- })
- .map(|m| {
- let (id, module) = m.to_module_id(&entities);
- //info!("{:?}", module);
- let body = physics_data.rigid_body_set.get(module.handle).unwrap();
- starkingdoms_protocol::module::Module {
- module_type: module.module_type.into(),
- rotation: body.rotation().angle(),
- x: body.translation().x * SCALE,
- y: body.translation().y * SCALE,
- id,
- flags: module.flags,
- special_fields: Default::default(),
- }
- })
- .collect();
+ })
+ .collect();
let mut protocol_modules: Vec<starkingdoms_protocol::module::Module> = modules
.iter()
.map(|(id, module)| {
- let body = physics_data.rigid_body_set.get(module.handle).unwrap();
+ let body;
+
+ #[allow(clippy::expect_used)] { body = physics_data.rigid_body_set.get(module.handle).expect("module body does not exist"); }
+
starkingdoms_protocol::module::Module {
module_type: module.module_type.into(),
rotation: body.rotation().angle(),
@@ 371,9 379,13 @@ pub async fn timer_main(
}
};
- match client_thread.tx.send(ClientHandlerMessage::ModuleTreeUpdate {
- modules: attached_modules
- }).await {
+ match client_thread
+ .tx
+ .send(ClientHandlerMessage::ModuleTreeUpdate {
+ modules: attached_modules,
+ })
+ .await
+ {
Ok(_) => (),
Err(e) => {
warn!("unable to send module tree update packet: {}", e);
M spacetime_rs/src/commands/docker.rs => spacetime_rs/src/commands/docker.rs +6 -3
@@ 2,11 2,11 @@ use crate::commands::api::build_api_prod;
use crate::commands::client::build_client_prod;
use crate::commands::server::build_server_prod;
use crate::ninja::exec;
+use sedregex::find_and_replace;
use std::error::Error;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
-use sedregex::find_and_replace;
fn _build(img: &str, channel: &str, root: &PathBuf) -> Result<(), Box<dyn Error>> {
let mut patched = "".to_string();
@@ 18,7 18,7 @@ fn _build(img: &str, channel: &str, root: &PathBuf) -> Result<(), Box<dyn Error>
} else if img == "web" {
let (a, b) = match channel {
"stable" => ("starkingdoms", "tk"),
- _ => (channel, "starkingdoms.io")
+ _ => (channel, "starkingdoms.io"),
};
let index_html_path = root.clone().join("client/").join("index.html");
@@ 30,7 30,10 @@ fn _build(img: &str, channel: &str, root: &PathBuf) -> Result<(), Box<dyn Error>
fs::write(&index_html_path, index_html_patched.as_bytes())?;
- fs::write(root.clone().join("client/").join("index.html.orig"), index_html_src.clone())?;
+ fs::write(
+ root.clone().join("client/").join("index.html.orig"),
+ index_html_src.clone(),
+ )?;
patched = index_html_src.clone();
M spacetime_rs/src/configure/asset.rs => spacetime_rs/src/configure/asset.rs +5 -1
@@ 27,7 27,11 @@ pub fn configure_assets(writer: &mut NinjaWriter<File>, root: &Path) -> Result<(
);
let default_asset_size = 512;
- let asset_overrides = HashMap::from([("earth.svg", 2048), ("moon.svg", 2048), ("starfield.svg", 2048)]);
+ let asset_overrides = HashMap::from([
+ ("earth.svg", 2048),
+ ("moon.svg", 2048),
+ ("starfield.svg", 2048),
+ ]);
// generate an inkscape rule for all required asset sizes
let mut written_rules_for = vec![];
M web/play.html => web/play.html +1 -1
@@ 2,7 2,7 @@
<html lang="en-US">
<head>
<title>StarKingdoms.TK</title>
- <link rel="stylesheet" href="/static/css/play.css"></link>
+ <link rel="stylesheet" href="/static/css/play.css"/>
<meta charset="utf-8">
</head>
M web/static/css/index.css => web/static/css/index.css +0 -3
@@ 11,6 11,3 @@
width: 100%;
}
-.w-90 {
- width: 90%;
-}>
\ No newline at end of file
M web/static/css/play.css => web/static/css/play.css +0 -5
@@ 1,8 1,3 @@
-.texturebox {
- display: inline;
- margin: 5px;
-}
-
#canvas {
position: absolute;
top: 0;