use crate::prelude::*; use crate::server::ConnectedNetworkEntity; pub fn server_thrust_plugin(app: &mut App) { app .add_systems(Update, process_thrust_events); } pub fn process_thrust_events( mut events: MessageReader>, clients: Query<&ConnectedNetworkEntity>, q_ls_me: Query>, mut commands: Commands ) { for FromClient { client_id, message: thrust_solution, } in events.read() { let player_hearty_entity = match client_id { ClientId::Client(client_entity) => { let ConnectedNetworkEntity { game_entity: player_hearty_entity, } = clients.get(*client_entity).unwrap(); player_hearty_entity }, ClientId::Server => &q_ls_me.iter().next().unwrap() }; / commands.entity(player_hearty_entity).insert(thrust_solution); trace!("installed thrust solution {:?}", thrust_solution); /* TODO: @tm85: have fun! TODO: The ThrustSolution contains a set of thrusters that should be on. TODO: All other thrusters should be off. TODO: If a thruster should be on, apply it's force vector at it's point TODO: (RigidBodyForces::apply_force_at_point, TODO: note this is worldspace!! [GlobalTransform is your friend]) TODO: Note that this is only an event handler, and will only run TODO: when the client sends us a NEW thrust solution. TODO: You probably want to add a Component to the player entity (player_hearty_entity, TODO: it's also the hearty part entity) that stores the current ThrustSolution TODO: and applies it every tick, since avian's ExternalForces only apply for a single TODO: physics tick and must be applied every tick to be continuous. TODO: Hint: you probably want a mut commands: Commands in this system, TODO: and then insert a component with commands.entity(hearty).insert(YourNewComponent) TODO: To do this, create a new system (e.g. apply_thrust) or something, and apply thrust TODO: there, every tick (Update). Register it with the plugin above. TODO: I'll leave you to that. Have fun! ping me if you've got questions, I'll be up TODO: a while so can help you decipher the attachment system if need be. TODO: Overall, your goal is: TODO: - find all parts in the ship (hint: query for Parts on the ship (hearty)) TODO: - for each part, find all thrusters (hint: query for PartThrusters on the part) TODO: - for each thruster, if it's on (check if it's in the player's current thrust soln) TODO: - apply a force at the correct point TODO: Much of the same logic is done in the client counterpart, to calculate effective TODO: force for the solver. Take a look at client::ship::thrusters. TODO: Note that relationship components (eg Parts, PartThrusters) wont exist if there are TODO: no children - eg hearty won't have Parts if nothing is attached, a part won't have TODO: PartThrusters if it has no thrusters. TODO: Handle this with Option<&Component> in the query */ } }