~starkingdoms/starkingdoms

d2b8956323d8e82903824637cdcfb2f978dd94e9 — core 15 days ago 92b84cc
chore: please thy lord clippy
M crates/unified/assets/config/world.wc.toml => crates/unified/assets/config/world.wc.toml +1 -0
@@ 1,5 1,6 @@
[world]
gravity = 0.005
gravity_iterations = 8
spawn_parts_at = "Earth"
spawn_parts_interval_secs = 1


M crates/unified/src/build_meta.rs => crates/unified/src/build_meta.rs +2 -0
@@ 1,5 1,7 @@
// Use of a mod or pub mod is not actually necessary.
pub mod built_info {
    #![allow(clippy::allow_attributes_without_reason, reason = "generated code")]
    #![allow(clippy::pedantic, reason = "generated code")]
    // The file has been placed there by the build script.
    include!(concat!(env!("OUT_DIR"), "/built.rs"));
}

M crates/unified/src/cli.rs => crates/unified/src/cli.rs +5 -5
@@ 45,7 45,9 @@ pub fn parse_args() -> StkArgs {
        std::process::exit(1);
    };

    let args = match subcommand.as_str() {
    

    match subcommand.as_str() {
        #[cfg(feature = "client")]
        "client" => {
            StkArgs::Client {


@@ 71,9 73,7 @@ pub fn parse_args() -> StkArgs {
            eprintln!("-h, --help for help");
            std::process::exit(1);
        }
    };

    args
    }
}

fn print_help() {


@@ 124,5 124,5 @@ SERVER:

fn print_version() {
    println!("{}", version_and_features_line());
    println!("built on {} by {} on {} for {}", BUILT_TIME_UTC, RUSTC_VERSION, HOST, TARGET);
    println!("built on {BUILT_TIME_UTC} by {RUSTC_VERSION} on {HOST} for {TARGET}");
}
\ No newline at end of file

M crates/unified/src/client/input/mod.rs => crates/unified/src/client/input/mod.rs +2 -2
@@ 4,8 4,8 @@ use bevy::app::{App, Update};
use bevy::window::PrimaryWindow;
use leafwing_input_manager::Actionlike;
use leafwing_input_manager::input_map::InputMap;
use leafwing_input_manager::prelude::{ActionState, ButtonlikeChord};
use crate::ecs::{MainCamera, Me};
use leafwing_input_manager::prelude::ActionState;
use crate::ecs::MainCamera;
use crate::prelude::*;

#[derive(Actionlike, PartialEq, Eq, Hash, Clone, Copy, Debug, Reflect)]

M crates/unified/src/client/key_input.rs => crates/unified/src/client/key_input.rs +1 -1
@@ 2,7 2,7 @@ use bevy::dev_tools::picking_debug::DebugPickingMode;
use crate::prelude::*;
use bevy::{
    app::{App, Update},
    ecs::{message::MessageWriter, system::Res},
    ecs::system::Res,
    input::{ButtonInput, keyboard::KeyCode},
};
use std::ops::Deref;

M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +2 -20
@@ 7,14 7,13 @@ use crate::client::ui::ui_plugin;
use crate::client::zoom::zoom_plugin;
use crate::client::starguide::init::starguide_init_plugin;
use crate::client::starguide::input::starguide_input_plugin;
use crate::ecs::{Hi, Part, Player, StarguideGizmos};
use crate::ecs::{Hi, StarguideGizmos};
use aeronet_websocket::client::WebSocketClient;
use bevy::dev_tools::picking_debug::DebugPickingMode;
use crate::prelude::*;
use planet::incoming_planets::incoming_planets_plugin;
use crate::client::ship::attachment::client_attachment_plugin;
use crate::ecs::{Me, GameplayState, STARGUIDE_LAYER};
use crate::world_config::world_config_plugin;
use crate::ecs::{Me, GameplayState};

pub mod colors;
pub mod key_input;


@@ 79,29 78,12 @@ impl Plugin for ClientPlugin {
fn find_me(
    mut commands: Commands,
    mut reader: MessageReader<Hi>,
    asset_server: Res<AssetServer>,
) {

    for msg in reader.read() {
        info!("^^^^^^^^^^^ IGNORE THESE WARNINGS ^^^^^^^^^^^^^^");
        info!("they are normal! and are from the world state being replicated as it is sent over the network");
        info!(?msg, "finding me: got hello from server");
        commands.entity(msg.you_are).insert(Me);

        /*let mut heart_sprite =
            Sprite::from_image(asset_server.load("sprites/hearty_heart.png"));
        heart_sprite.custom_size = Some(Vec2::new(
            part.strong_config.physics.width,
            part.strong_config.physics.height,
        ));
        heart_sprite.color = Color::srgb(20.0, 0.0, 0.0);

        commands.spawn((
            ChildOf(entity),
            heart_sprite,
            Transform::from_xyz(0.0, 0.0, 10.0),
        ));
        */
    }
}


M crates/unified/src/client/parts.rs => crates/unified/src/client/parts.rs +4 -5
@@ 110,8 110,7 @@ struct DragGhost;
struct Ghost {
    pub rot: Quat,
    pub last_target_pos: Vec3,
    pub vel: Vec3,
    pub part: Entity
    pub vel: Vec3
}

const ROTATION_SMOOTH: f32 = 0.1;


@@ 145,7 144,6 @@ fn on_part_click(
        rot: sprite.1.rotation,
        last_target_pos: sprite.1.translation,
        vel: Vec3::ZERO,
        part: ev.event_target(),
    }, *sprite.1, s));

    drag.0 = Some(ev.event().event_target());


@@ 205,6 203,7 @@ fn smoothing_a(x: Vec3, x_dot: Vec3, r: Vec3, v: Vec3) -> Vec3 {
//                = x/K2 + K3/K2*x' - r(t)/K2 - K1/K2*v(t)
// [ r' ] = [ 0    1     ] * [ r(t) ] + [ 0 ]
// [ v' ] = [ 1/K2 K1/K2 ] * [ v(t) ] + [ 1 ] * x/K2 + K3/K2*x'
#[allow(clippy::similar_names, reason = "Ghostly. This function is horrible.")]
fn rk4_k_values(x: Vec3, x_dot:Vec3, r: Vec3, v: Vec3, dt: f32)
    -> (Vec3, Vec3, Vec3, Vec3, Vec3, Vec3, Vec3, Vec3) {
    let a = smoothing_a(x, x_dot, r, v);


@@ 403,8 402,8 @@ fn update_drag_ghosts(
        /time.delta_secs();


    let a = (best_target.translation - ghost.translation
        + K3*target_vel - K1*ghost_info.vel)/K2;
    //let a = (best_target.translation - ghost.translation
    //    + K3*target_vel - K1*ghost_info.vel)/K2;
    let (r_k1, v_k1, r_k2, v_k2, r_k3, v_k3, r_k4, v_k4) = rk4_k_values(best_target.translation, target_vel, ghost.translation, ghost_info.vel, time.delta_secs());

    ghost.translation += (r_k1 + 2.0*r_k2 + 2.0*r_k3 + r_k4)/6.0*time.delta_secs();

M crates/unified/src/client/rendering/mod.rs => crates/unified/src/client/rendering/mod.rs +1 -2
@@ 2,7 2,7 @@ use bevy::anti_alias::fxaa::Fxaa;
use bevy::app::{App, Startup};
use bevy::core_pipeline::tonemapping::DebandDither;
use bevy::post_process::bloom::Bloom;
use crate::ecs::{GameplayState, MAIN_LAYER, MAIN_STAR_LAYERS, MainCamera, Me, STARGUIDE_LAYER, StarguideCamera, StarguideGizmos};
use crate::ecs::{GameplayState, MAIN_LAYER, MainCamera, Me, STARGUIDE_LAYER, StarguideGizmos};
use crate::prelude::*;

pub fn render_plugin(app: &mut App) {


@@ 31,7 31,6 @@ pub fn setup_graphics(mut config_store: ResMut<GizmoConfigStore>, mut commands: 

fn follow_camera(
    mut camera: Query<&mut Transform, (With<MainCamera>, Without<Me>)>,
    mut starguide_camera: Query<&mut Transform, (With<StarguideCamera>, Without<MainCamera>, Without<Me>)>,
    player: Query<&Transform, With<Me>>,
) {
    let mut camera = camera.single_mut().unwrap();

M crates/unified/src/client/ship/mod.rs => crates/unified/src/client/ship/mod.rs +2 -1
@@ 1,2 1,3 @@
pub mod attachment;
pub mod thrusters;
\ No newline at end of file
pub mod thrusters;
mod thrust_solver;
\ No newline at end of file

A crates/unified/src/client/ship/thrust_solver.rs => crates/unified/src/client/ship/thrust_solver.rs +0 -0
M crates/unified/src/client/ship/thrusters.rs => crates/unified/src/client/ship/thrusters.rs +14 -14
@@ 4,11 4,11 @@ use bevy::app::App;
use bevy::color::palettes::basic::{RED, WHITE};
use bevy::color::palettes::css::LIMEGREEN;
use bevy::math::Vec3Swizzles;
use good_lp::{default_solver, variable, Expression, ProblemVariables, Solution, SolutionStatus, SolverModel, Variable};
use good_lp::{default_solver, variable, Expression, ProblemVariables, Solution, SolutionStatus, SolverModel};
use leafwing_input_manager::prelude::ActionState;
use crate::attachment::Parts;
use crate::client::input::ClientAction;
use crate::ecs::thruster::{PartThrusters, Thruster, ThrusterOfPart};
use crate::ecs::thruster::{PartThrusters, Thruster};
use crate::prelude::*;
use crate::client::input::util::ActionStateExt;
use crate::ecs::Me;


@@ 34,7 34,7 @@ fn draw_thruster_debug(
    thrust_solution: Res<ThrustSolution>,
    mut gizmos: Gizmos,
) {
    if !thruster_debug_res.0 { return };
    if !thruster_debug_res.0 { return }
    for thruster in thrusters {
        // Draw white if it's just a thruster, bright green if it's in the current thrust solution
        let mut color = if thrust_solution.thrusters_on.contains(&thruster.1) {


@@ 212,9 212,10 @@ fn solve_thrust(
            };

            // Then, push all this data for the next section to deal with.
            all_thrusters.push((thruster_id,
                                thruster_vector.extend(0.0),
                                Vec3::new(0.0, 0.0, renormalized_thruster_torque)
            all_thrusters.push((
                thruster_id,
                thruster_vector.extend(0.0),
                Vec3::new(0.0, 0.0, renormalized_thruster_torque)
            ));
        }
    }


@@ 239,7 240,7 @@ fn solve_thrust(
    "Coefficients" are i_0 ... i_n, and can be precomputed, and x_0 ... x_n is the "decision variables"
     */

    if all_thrusters.len() == 0 {
    if all_thrusters.is_empty() {
        trace!("there are no thrusters; zeroing thrust solution");
        trace!("solved thrust in {}ms", start.elapsed().as_millis());
        solution.converged = true;


@@ 288,11 289,11 @@ fn solve_thrust(
            // We need to return these handles later to get the values back
            (
                (
                    u.0 as f64,
                    f64::from(u.0),
                    thrust_variables.add(variable().min(0.0).max(1.0).initial(u.0))
                ),
                (
                    u.1 as f64,
                    f64::from(u.1),
                    torque_variables.add(variable().min(0.0).max(1.0).initial(u.1))
                ),
            )


@@ 322,10 323,10 @@ fn solve_thrust(
    match thrust_solution.status() {
        SolutionStatus::Optimal => {}, // yay!
        SolutionStatus::TimeLimit => {
            warn!("thrust solver failed to converge, hit time limit")
            warn!("thrust solver failed to converge, hit time limit");
        }
        SolutionStatus::GapLimit => {
            warn!("thrust solver failed to converge, hit gap limit")
            warn!("thrust solver failed to converge, hit gap limit");
        }
    }



@@ 345,10 346,10 @@ fn solve_thrust(
    match torque_solution.status() {
        SolutionStatus::Optimal => {}, // yay!
        SolutionStatus::TimeLimit => {
            warn!("torque solver failed to converge, hit time limit")
            warn!("torque solver failed to converge, hit time limit");
        }
        SolutionStatus::GapLimit => {
            warn!("torque solver failed to converge, hit gap limit")
            warn!("torque solver failed to converge, hit gap limit");
        }
    }



@@ 379,5 380,4 @@ fn solve_thrust(
    debug!(?elapsed, ?target_unit_vector, ?target_torque_vector, "solved for thrust and torque");
    *solution = new_soln; // save it to the Resource for use on the client...
    events.write(solution.clone()); // ...then send it to the server!
    return;
}

M crates/unified/src/client/starfield.rs => crates/unified/src/client/starfield.rs +1 -1
@@ 18,7 18,7 @@ use bevy::{

use crate::{
    ecs::Me,
    ecs::{MainCamera, MAIN_LAYER, STARGUIDE_LAYER, StarfieldBack, StarfieldFront, StarfieldMid},
    ecs::{MainCamera, MAIN_LAYER, StarfieldBack, StarfieldFront, StarfieldMid},
};

pub const BACK_STARFIELD_SIZE: f32 = 256.0;

M crates/unified/src/client/starguide/init.rs => crates/unified/src/client/starguide/init.rs +2 -33
@@ 1,11 1,8 @@
use bevy::anti_alias::fxaa::Fxaa;
use bevy::asset::RenderAssetUsages;
use bevy::core_pipeline::tonemapping::DebandDither;
use bevy::post_process::bloom::Bloom;
use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat};
use bevy::window::PrimaryWindow;
use crate::prelude::*;
use crate::ecs::{Me, ORBIT_LAYER, OrbitCamera, Part, STARGUIDE_LAYER, StarguideCamera, StarguideMe, StarguideOrbit, StarguideOrbitImage};
use crate::ecs::{Me, Part, STARGUIDE_LAYER, StarguideCamera, StarguideMe, StarguideOrbit};

pub fn starguide_init_plugin(app: &mut App) {
    app


@@ 15,23 12,11 @@ pub fn starguide_init_plugin(app: &mut App) {
}

pub fn init_starguide(
    mut images: ResMut<Assets<Image>>,
    window: Single<&Window, With<PrimaryWindow>>,
    mut commands: Commands,
) {
    /*commands.spawn((Camera2d::default(), Camera {
    commands.spawn((Camera2d, Camera {
        is_active: false,
        clear_color: ClearColorConfig::Custom(Color::linear_rgba(0.0, 0.0, 0.0, 1.0)),
        order: 0,
        ..default()
    }))
    .insert(ORBIT_LAYER)
    .insert(OrbitCamera);*/

    commands.spawn((Camera2d::default(), Camera {
        is_active: false,
        //clear_color: ClearColorConfig::None,
        clear_color: ClearColorConfig::Custom(Color::linear_rgba(0.0, 0.0, 0.0, 1.0)),
        ..default()
    }))
    .insert(Bloom::default())


@@ 39,21 24,6 @@ pub fn init_starguide(
    .insert(Fxaa::default())
    .insert(STARGUIDE_LAYER)
    .insert(StarguideCamera);

    /*let image = Image::new_fill(
        Extent3d {
            width: window.width() as u32,
            height: window.height() as u32,
            depth_or_array_layers: 1,
        }, TextureDimension::D2,
        &(Color::BLACK.to_srgba().to_u8_array()),
        TextureFormat::Rgba8UnormSrgb,
        RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
    );
    let handle = images.add(image);
    commands.spawn((Sprite::from_image(handle.clone()), STARGUIDE_LAYER, StarguideOrbit))
        .insert(Transform::from_xyz(0.0, 0.0, -10.0));
    commands.insert_resource(StarguideOrbitImage(handle));*/
}

pub fn player_init(


@@ 72,7 42,6 @@ pub fn player_init(

fn player_position_update(
    me: Single<&Transform, (Changed<Transform>, With<Me>)>,
    //mut orbit: Single<&mut Transform, (With<StarguideOrbit>, Without<Me>)>,
    mut starguide_me: Single<&mut Transform, (With<StarguideMe>, Without<StarguideOrbit>, Without<Me>)>,
) {
    starguide_me.translation = me.translation;

M crates/unified/src/client/starguide/input.rs => crates/unified/src/client/starguide/input.rs +1 -1
@@ 1,6 1,6 @@
use crate::prelude::*;
use crate::client::input::CursorWorldCoordinates;
use crate::ecs::{StarguideCamera, StarguideOrbit};
use crate::ecs::StarguideCamera;

pub fn starguide_input_plugin(app: &mut App) {
    app

M crates/unified/src/client/starguide/orbit.rs => crates/unified/src/client/starguide/orbit.rs +10 -47
@@ 1,43 1,33 @@
use std::{f32::{self, consts::PI}, ops::Range};
use std::f32::consts::PI;

use bevy::window::WindowResized;

use crate::{config::planet::Planet, ecs::{Me, StarguideCamera, StarguideGizmos, StarguideOrbit, StarguideOrbitImage}, prelude::*, world_config::WorldConfigResource};
use bevy::render::render_resource::Extent3d;
use crate::{config::planet::Planet, ecs::{Me, StarguideCamera, StarguideGizmos}, prelude::*, world_config::WorldConfigResource};

pub fn starguide_orbit_plugin(app: &mut App) {
    app
        .add_systems(Update, (update_orbits));
        .add_systems(Update, update_orbits);
}

fn update_orbits(
    //orbit_image: Res<StarguideOrbitImage>,
    //mut images: ResMut<Assets<Image>>,
    camera: Single<(&Camera, &GlobalTransform, &Projection), With<StarguideCamera>>,
    me: Single<(&Transform, &LinearVelocity), (With<Me>, Without<StarguideCamera>)>,
    //orbit: Single<&Transform, (With<StarguideOrbit>, Without<Me>, Without<StarguideCamera>)>,
    mut gizmos: Gizmos<StarguideGizmos>,
    world_config: Res<WorldConfigResource>,
    planets: Query<(&Mass, &Planet, &Transform)>,
) {
    /*let Some(image) = images.get_mut(&orbit_image.0) else {
        error!("Orbit prediction image not found");
        return
    };*/
    let Some(world_config) = &world_config.config else {
        return;
    };
    let Projection::Orthographic(ref projection) = camera.2.clone() else { return };
    //image.clear(&(Color::BLACK.to_srgba().to_u8_array()));
    let Projection::Orthographic(_) = camera.2.clone() else { return };

    let mut p_mass = None;
    let mut p_transform = None;
    let (sun_mass, _, sun_transform) = planets.iter().filter(|planet| planet.1.name == "Sun").next().unwrap();
    let (sun_mass, _, sun_transform) = planets.iter().find(|planet| planet.1.name == "Sun").unwrap();
    let mut closest = f32::INFINITY;
    for (mass, planet, transform) in planets {
        if planet.name == "Sun" { continue }

        let (other_mass, p, other_transform) = planets.iter().filter(|f_planet| f_planet.1.name == planet.orbit.clone().unwrap().orbiting).next().unwrap();
        let (other_mass, _, other_transform) = planets.iter().find(|f_planet| f_planet.1.name == planet.orbit.clone().unwrap().orbiting).unwrap();
        let a = other_transform.translation - transform.translation;
        let hill_sphere = a.length()*(mass.0/(3.0*(other_mass.0+mass.0))).powf(1.0/3.0);



@@ 79,41 69,14 @@ fn update_orbits(

        // convert r to image coords
        let pos = Vec2::new(r*theta.cos(), r*theta.sin()) + p_transform.translation.truncate();
        /*let pos = pos + p_transform.translation.truncate() - orbit.translation.truncate();
        let pos = Vec2::new(pos.x, -pos.y);
        let pos = pos / projection.scale;
        let pos = pos + image.size_f32()/2.0;*/

        //if !(pos.x as u32 >= image.size().x || pos.y as u32 >= image.size().y) && i != 0 {
        if last_pos.is_some() {
            gizmos.line_2d(last_pos.unwrap(), pos, Color::linear_rgb(1.0, 0.0, 0.0));
        if let Some(last_pos) = last_pos {
            gizmos.line_2d(last_pos, pos, Color::linear_rgb(1.0, 0.0, 0.0));
        }
        if first_pos.is_none() { first_pos = Some(pos) }
        last_pos = Some(pos);
    }
    if first_pos.is_some() && last_pos.is_some() {
        gizmos.line_2d(first_pos.unwrap(), last_pos.unwrap(), Color::linear_rgb(1.0, 0.0, 0.0));
    if let Some(first_pos) = first_pos && let Some(last_pos) = last_pos {
        gizmos.line_2d(first_pos, last_pos, Color::linear_rgb(1.0, 0.0, 0.0));
    }
}

/*fn window_resize(
    orbit_image: Res<StarguideOrbitImage>,
    mut images: ResMut<Assets<Image>>,
    mut resize_ev: MessageReader<WindowResized>,
    camera: Single<&Camera, With<StarguideCamera>>,
) {
    let Some(image) = images.get_mut(&orbit_image.0) else {
        error!("Orbit prediction image not found");
        return
    };
    for _ in resize_ev.read() {
        let Some(Vec2 {x: width, y: height}) = camera.logical_viewport_size() else {
            continue
        };
        image.resize(Extent3d {
            width: width as u32,
            height: height as u32,
            depth_or_array_layers: 1,
        });
    }
}*/

M crates/unified/src/client/zoom.rs => crates/unified/src/client/zoom.rs +1 -1
@@ 4,7 4,7 @@ use bevy::{
};

use crate::{
    client::{starfield::{BACK_STARFIELD_SIZE, FRONT_STARFIELD_SIZE, MID_STARFIELD_SIZE, StarfieldSize}, starguide}, ecs::{MainCamera, Me, OrbitCamera, StarfieldBack, StarfieldFront, StarfieldMid, StarguideOrbit}
    client::starfield::{BACK_STARFIELD_SIZE, FRONT_STARFIELD_SIZE, MID_STARFIELD_SIZE, StarfieldSize}, ecs::{MainCamera, Me, OrbitCamera, StarfieldBack, StarfieldFront, StarfieldMid}
};
use crate::ecs::{StarguideCamera, GameplayState};


M crates/unified/src/config/world.rs => crates/unified/src/config/world.rs +1 -0
@@ 12,6 12,7 @@ pub struct GlobalWorldConfig {
#[derive(Deserialize, Asset, TypePath, Clone)]
pub struct WorldConfig {
    pub gravity: f32,
    pub gravity_iterations: usize,
    pub spawn_parts_at: String,
    pub spawn_parts_interval_secs: f32,
}

M crates/unified/src/ecs.rs => crates/unified/src/ecs.rs +0 -1
@@ 8,7 8,6 @@ use crate::prelude::*;
use bevy_replicon::prelude::Replicated;
use serde::{Deserialize, Serialize};
use avian2d::prelude::*;
use crate::thrust::ThrustSolution;
use std::sync::LazyLock;

#[derive(States, Debug, Clone, PartialEq, Eq, Hash)]

M crates/unified/src/main.rs => crates/unified/src/main.rs +1 -1
@@ 57,7 57,7 @@ use crate::client_plugins::ClientPluginGroup;
use crate::server_plugins::ServerPluginGroup;


#[allow(unused_mut)]
#[allow(unused_mut, reason = "Conditional compilation hell")]
fn run(cli: StkArgs) -> AppExit {
    let mut app = App::new();


M crates/unified/src/server/gravity.rs => crates/unified/src/server/gravity.rs +3 -5
@@ 9,7 9,6 @@ pub fn newtonian_gravity_plugin(app: &mut App) {
    app.add_systems(Update, update_gravity.in_set(WorldUpdateSet));
}


fn update_gravity(
    mut part_query: Query<(&Transform, &LinearVelocity, &Mass, &mut ConstantForce), With<Part>>,
    planet_query: Query<(&Transform, &Mass), With<Planet>>,


@@ 32,19 31,18 @@ fn update_gravity(

            let distance = planet_translation.distance(part_translation);

            const GRAV_ITERS: u32 = 8;
            let mut x = 0.0;
            let mut total_f = 0.0;
            let mut v = part_velocity.0;
            let dt = time.delta_secs() / GRAV_ITERS as f32;
            for i in 0..GRAV_ITERS {
            let dt = time.delta_secs() / world_config.world.gravity_iterations as f32;
            for i in 0..world_config.world.gravity_iterations {
                let f =
                    world_config.world.gravity * ((part_mass * planet_mass) / distance.squared()-x);
                let dx = dt*(v.project_onto((planet_translation-part_translation).truncate())).length()
                    - 1.0/2.0*(f/part_mass)*dt*dt;
                x += dx;
                v += f/part_mass*dt;
                if i == 0 || i == GRAV_ITERS-1 {
                if i == 0 || i == world_config.world.gravity_iterations-1 {
                    total_f += f;
                } else {
                    total_f += 2.0*f;

M crates/unified/src/server/mod.rs => crates/unified/src/server/mod.rs +0 -1
@@ 11,7 11,6 @@ use crate::server::part::part_management_plugin;
use crate::server::planets::planets_plugin;
use crate::server::player::player_management_plugin;
use crate::server::system_sets::{PlayerInputSet, WorldUpdateSet};
use crate::world_config::world_config_plugin;
use aeronet::io::Session;
use aeronet::io::connection::{DisconnectReason, Disconnected, LocalAddr};
use aeronet::io::server::Server;

M crates/unified/src/server/player.rs => crates/unified/src/server/player.rs +2 -2
@@ 259,8 259,8 @@ fn dragging(

        debug!(?event, "got drag request event");

        let mut teleport_to_translation = Vec2::new(0.0, 0.0);
        let mut teleport_to_rotation = Quat::from_rotation_z(0.0);
        let teleport_to_translation;
        let teleport_to_rotation;
        let mut new_linvel = None;
        let mut new_angvel = None;


M crates/unified/src/server/player/thrust.rs => crates/unified/src/server/player/thrust.rs +1 -1
@@ 5,7 5,7 @@

use crate::attachment::Parts;
use crate::ecs::Part;
use crate::ecs::thruster::{PartThrusters, Thruster, ThrusterOfPart};
use crate::ecs::thruster::{Thruster, ThrusterOfPart};
use crate::prelude::*;
use crate::server::ConnectedNetworkEntity;
use crate::thrust::ThrustSolution;

M crates/unified/src/server_plugins.rs => crates/unified/src/server_plugins.rs +0 -1
@@ 1,6 1,5 @@
use aeronet_replicon::server::AeronetRepliconServerPlugin;
use aeronet_websocket::server::WebSocketServerPlugin;
use avian2d::prelude::PhysicsInterpolationPlugin;
use bevy::app::{PluginGroup, PluginGroupBuilder};
use std::net::SocketAddr;
use avian2d::PhysicsPlugins;