~starkingdoms/starkingdoms

6cc37973babd2f840d5d72056b568d5ab245363c — core 1 year, 8 months ago 25385f2
server config file
M Cargo.lock => Cargo.lock +64 -21
@@ 382,6 382,9 @@ name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
dependencies = [
 "serde",
]

[[package]]
name = "ash"


@@ 620,6 623,7 @@ dependencies = [
 "bevy_tasks",
 "bevy_utils",
 "bytemuck",
 "serde",
]

[[package]]


@@ 771,6 775,7 @@ dependencies = [
 "bevy_math",
 "bevy_reflect",
 "bevy_utils",
 "serde",
 "smol_str",
 "thiserror",
]


@@ 802,6 807,7 @@ dependencies = [
 "bevy_tasks",
 "bevy_time",
 "bevy_transform",
 "bevy_ui",
 "bevy_utils",
 "bevy_window",
 "bevy_winit",


@@ 874,6 880,7 @@ dependencies = [
 "log",
 "nalgebra",
 "rapier2d",
 "serde",
]

[[package]]


@@ 1034,6 1041,7 @@ dependencies = [
 "bevy_reflect",
 "bevy_utils",
 "crossbeam-channel",
 "serde",
 "thiserror",
]



@@ 1048,6 1056,35 @@ dependencies = [
 "bevy_hierarchy",
 "bevy_math",
 "bevy_reflect",
 "serde",
 "thiserror",
]

[[package]]
name = "bevy_ui"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3449b963573a56b484cf4f8883f1b5b8eaccaaeda8f28a70c006e3291450f77"
dependencies = [
 "bevy_a11y",
 "bevy_app",
 "bevy_asset",
 "bevy_core_pipeline",
 "bevy_derive",
 "bevy_ecs",
 "bevy_hierarchy",
 "bevy_input",
 "bevy_log",
 "bevy_math",
 "bevy_reflect",
 "bevy_render",
 "bevy_sprite",
 "bevy_transform",
 "bevy_utils",
 "bevy_window",
 "bytemuck",
 "serde",
 "taffy",
 "thiserror",
]



@@ 1095,6 1132,7 @@ dependencies = [
 "bevy_reflect",
 "bevy_utils",
 "raw-window-handle",
 "serde",
 "smol_str",
]



@@ 1137,6 1175,9 @@ name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
dependencies = [
 "serde",
]

[[package]]
name = "bitflags"


@@ 2170,6 2211,12 @@ dependencies = [
]

[[package]]
name = "grid"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c"

[[package]]
name = "guillotiere"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 2701,6 2748,7 @@ dependencies = [
 "num-complex",
 "num-rational",
 "num-traits",
 "serde",
 "simba",
 "typenum",
]


@@ 2778,6 2826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6"
dependencies = [
 "num-traits",
 "serde",
]

[[package]]


@@ 2989,6 3038,7 @@ dependencies = [
 "num-derive",
 "num-traits",
 "rustc-hash",
 "serde",
 "simba",
 "slab",
 "smallvec",


@@ 3252,6 3302,7 @@ dependencies = [
 "num-traits",
 "parry2d",
 "rustc-hash",
 "serde",
 "simba",
]



@@ 3741,7 3792,7 @@ dependencies = [
 "serde_json",
 "sha2",
 "starkingdoms-common",
 "tikv-jemallocator",
 "toml 0.8.12",
 "tracing-subscriber",
 "tungstenite",
]


@@ 3812,6 3863,18 @@ dependencies = [
]

[[package]]
name = "taffy"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3"
dependencies = [
 "arrayvec",
 "grid",
 "num-traits",
 "slotmap",
]

[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 3851,26 3914,6 @@ dependencies = [
]

[[package]]
name = "tikv-jemalloc-sys"
version = "0.5.4+5.3.0-patched"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1"
dependencies = [
 "cc",
 "libc",
]

[[package]]
name = "tikv-jemallocator"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca"
dependencies = [
 "libc",
 "tikv-jemalloc-sys",
]

[[package]]
name = "time"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"

M server/Cargo.toml => server/Cargo.toml +2 -2
@@ 8,7 8,7 @@ license = "AGPL-3"
bevy = { version = "0.13.1", default-features = false }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
bevy_rapier2d = "0.25.0"
bevy_rapier2d = { version = "0.25", features = ["serde-serialize"] }
rand = "0.8.5"
tracing-subscriber = "0.3"
starkingdoms-common = { version = "0.1", path = "../starkingdoms-common" }


@@ 16,9 16,9 @@ jwt = "0.16"
sha2 = "0.10"
hmac = "0.12"
hex = "0.4"
tikv-jemallocator = "0.5.0"
crossbeam-channel = "0.5"
tungstenite = "0.21"
toml = "0.8"

[features]
default = []

A server/config.toml => server/config.toml +30 -0
@@ 0,0 1,30 @@
[physics]
solver = "SmallstepPGS" # or "OldPGS"
dt = 0.05
min_ccd_dt = 0.000166666666667
erp = 0.8
damping_ratio = 0.25
joint_erp = 1.0
joint_damping_ratio = 0.25
allowed_linear_error = 0.001
max_penetration_correction = 0.5
prediction_distance = 0.002
num_solver_iterations = 4
num_additional_friction_iterations = 4
num_internal_pgs_iterations = 1
min_island_size = 128
max_ccd_substeps = 1

[world]
gravity = 0.0002
pixels_per_meter = 1.0

[security]
app_key = "abcd"
required_permission_level = 0

[server]
tick_time_ms = 1
world_fixed_timestep = 0.1666
bind = { ip = "0.0.0.0", port = 3000 }
max_free_parts = 50
\ No newline at end of file

A server/parts.toml => server/parts.toml +23 -0
@@ 0,0 1,23 @@
[part.Hearty]
mass = 1.0
energy_capacity = 2000
thruster_force = 0.3
thruster_energy = 1

[part.LandingThruster]
mass = 0.9
energy_capacity = 1000
thruster_force = 5
thruster_energy = 3

[part.Cargo]
mass = 0.5
energy_capacity = 0
thruster_force = 0
thruster_energy = 0

[part.Hub]
mass = 1
energy_capacity = 3000
thruster_force = 0
thruster_energy = 0

A server/planets.toml => server/planets.toml +11 -0
@@ 0,0 1,11 @@
[planets.Earth]
size = 20.0
mass = 10000.0

[planets.Moon]
size = 5.0
mass = 300.0

[planets.Mars]
size = 10.0
mass = 1250.0
\ No newline at end of file

M server/src/component.rs => server/src/component.rs +1 -1
@@ 19,7 19,7 @@ use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use starkingdoms_common::PartType as c_PartType;

#[derive(Component, Clone, Copy, Serialize, Deserialize, Debug, PartialEq)]
#[derive(Component, Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
pub enum PlanetType {
    Earth,
    Moon,

A server/src/config.rs => server/src/config.rs +91 -0
@@ 0,0 1,91 @@
// StarKingdoms.IO, a browser game about drifting through space
//     Copyright (C) 2024 ghostly_zsh, TerraMaster85, core
//
//     This program is free software: you can redistribute it and/or modify
//     it under the terms of the GNU Affero General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
//
//     This program is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU Affero General Public License for more details.
//
//     You should have received a copy of the GNU Affero General Public License
//     along with this program.  If not, see <https://www.gnu.org/licenses/>.

use std::collections::HashMap;
use std::net::IpAddr;
use bevy_rapier2d::rapier::dynamics::IntegrationParameters;
use serde::{Deserialize, Serialize};
use crate::component::{PartType, PlanetType};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StkConfig {
    pub security: SecurityConfig,
    pub server: ServerConfig,
    pub world: WorldConfig,
    pub physics: PhysicsConfig
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SecurityConfig {
    pub app_key: String,
    pub required_permission_level: u64
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ServerConfig {
    pub tick_time_ms: u64,
    pub world_fixed_timestep: f64,
    pub bind: BindConfig,
    pub max_free_parts: usize
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BindConfig {
    pub ip: IpAddr,
    pub port: u16
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WorldConfig {
    pub gravity: f32,
    pub part_half_size: f32,
    pub pixels_per_meter: f32
}


#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PhysicsConfig {
    pub parameters: IntegrationParameters,
    pub solver: PhysicsSolver
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum PhysicsSolver {
    SmallstepPGS,
    OldPGS
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PlanetsConfig {
    pub planets: HashMap<PlanetType, PlanetConfig>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PlanetConfig {
    pub size: f32,
    pub mass: f32
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PartsConfig {
    pub parts: HashMap<PartType, PartConfig>
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PartConfig {
    pub mass: f32,
    pub energy_capacity: u32,
    pub thruster_force: f32,
    pub thruster_energy: u32
}
\ No newline at end of file

M server/src/main.rs => server/src/main.rs +76 -56
@@ 16,9 16,8 @@
#![allow(clippy::type_complexity)] // bevy :(
#![allow(clippy::too_many_arguments)] // bevy :(
#![allow(clippy::only_used_in_recursion)] // todo: remove this
#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

use std::cell::OnceCell;
use std::collections::HashMap;
use std::net::IpAddr;



@@ 36,15 35,17 @@ use component::*;
use hmac::{Hmac, Mac};
use jwt::VerifyWithKey;
use packet::*;
use part::{HEARTY_THRUST_ENERGY, LANDING_THRUSTER_ENERGY};
use rand::Rng;
use serde::{Deserialize, Serialize};
use sha2::Sha256;
use starkingdoms_common::SaveModule;
use starkingdoms_common::{pack_savefile, unpack_savefile, SaveData};
use std::f32::consts::PI;
use std::fs;
use std::str::FromStr;
use std::sync::{Arc, OnceLock};
use std::time::Duration;
use crate::config::{PartsConfig, PlanetsConfig, ServerConfig, StkConfig};

pub mod component;
pub mod macros;


@@ 52,22 53,13 @@ pub mod mathutil;
pub mod packet;
pub mod part;
pub mod ws;

const CLIENT_SCALE: f32 = 50.0;

const EARTH_SIZE: f32 = 20.0;
const MOON_SIZE: f32 = EARTH_SIZE / 4.;
const MARS_SIZE: f32 = EARTH_SIZE / 2.;

const EARTH_MASS: f32 = 10000.0;
const MOON_MASS: f32 = EARTH_MASS / 30.;
const MARS_MASS: f32 = EARTH_MASS / 8.;

const GRAVITY: f32 = 0.0002;
const PART_HALF_SIZE: f32 = 25.0;
mod config;

struct StkPluginGroup;

pub static CLIENT_SCALE: f32 = 50.0;
pub static PART_HALF_SIZE: f32 = 25.0;

#[cfg(debug_assertions)]
impl PluginGroup for StkPluginGroup {
    fn build(self) -> PluginGroupBuilder {


@@ 76,7 68,7 @@ impl PluginGroup for StkPluginGroup {
            .add(TypeRegistrationPlugin)
            .add(FrameCountPlugin)
            .add(TimePlugin)
            .add(ScheduleRunnerPlugin::run_loop(Duration::from_millis(1)))
            .add(ScheduleRunnerPlugin::run_loop(Duration::from_millis(server_config().server.tick_time_ms)))
            .add(bevy::log::LogPlugin {
                level: bevy::log::Level::DEBUG,
                filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),


@@ 112,18 104,46 @@ struct KeyJson {
    app_key: String,
}

static _SERVER_CONFIG: OnceLock<StkConfig> = OnceLock::new();
#[inline]
pub fn server_config() -> StkConfig {
    _SERVER_CONFIG.get().unwrap().clone()
}
static _PARTS_CONFIG: OnceLock<PartsConfig> = OnceLock::new();
#[inline]
pub fn parts_config() -> PartsConfig {
    _PARTS_CONFIG.get().unwrap().clone()
}
static _PLANETS_CONFIG: OnceLock<PlanetsConfig> = OnceLock::new();
#[inline]
pub fn planets_config() -> PlanetsConfig {
    _PLANETS_CONFIG.get().unwrap().clone()
}

fn main() {
    // read the key in
    let key = std::fs::read_to_string("/etc/starkingdoms/keys.json").unwrap();
    let keyjson: KeyJson = serde_json::from_str(&key).unwrap();
    {
        // read the server main config
        let server_config = fs::read_to_string("/etc/starkingdoms/config.toml").unwrap();
        let parts_config = fs::read_to_string("/etc/starkingdoms/parts.toml").unwrap();
        let planets_config = fs::read_to_string("/etc/starkingdoms/planets.toml").unwrap();

        let server_config: StkConfig = toml::from_str(&server_config).unwrap();
        _SERVER_CONFIG.set(server_config).unwrap();
        let parts_config: PartsConfig = toml::from_str(&parts_config).unwrap();
        _PARTS_CONFIG.set(parts_config).unwrap();
        let planets_config: PlanetsConfig = toml::from_str(&planets_config).unwrap();
        _PLANETS_CONFIG.set(planets_config).unwrap();
    }
    
    let cfg = server_config();

    App::new()
        .insert_resource(AppKeys {
            app_key: keyjson.app_key.as_bytes().to_vec(),
            app_key: cfg.security.app_key.as_bytes().to_vec(),
        })
        .insert_resource(StkTungsteniteServerConfig {
            addr: IpAddr::from_str("0.0.0.0").unwrap(),
            port: 3000,
            addr: cfg.server.bind.ip,
            port: cfg.server.bind.port,
        })
        .add_plugins(StkPluginGroup)
        .insert_resource(RapierConfiguration {


@@ 131,7 151,7 @@ fn main() {
            ..Default::default()
        })
        .init_resource::<ModuleTimer>()
        .add_plugins(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(1.0))
        .add_plugins(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(cfg.world.pixels_per_meter))
        .add_plugins(StkTungsteniteServerPlugin)
        .add_systems(Startup, setup_integration_parameters)
        .add_systems(Startup, spawn_planets)


@@ 146,7 166,7 @@ fn main() {
        )
        .add_systems(FixedUpdate, save_eligibility)
        .add_systems(FixedUpdate, convert_modules)
        .insert_resource(Time::<Fixed>::from_seconds(1.0 / 60.0))
        .insert_resource(Time::<Fixed>::from_seconds(cfg.server.world_fixed_timestep))
        .run();

    info!("Goodbye!");


@@ 169,12 189,12 @@ fn spawn_planets(mut commands: Commands) {
            planet_type: PlanetType::Earth,
            transform: TransformBundle::from(earth_pos),
        })
        .insert(Collider::ball(EARTH_SIZE))
        .insert(AdditionalMassProperties::Mass(EARTH_MASS))
        .insert(Collider::ball(planet!(PlanetType::Earth).size))
        .insert(AdditionalMassProperties::Mass(planet!(PlanetType::Earth).mass))
        .insert(ReadMassProperties::default())
        .with_children(|children| {
            children
                .spawn(Collider::ball(EARTH_SIZE + 0.3))
                .spawn(Collider::ball(planet!(PlanetType::Earth).size + 0.3))
                .insert(ActiveEvents::COLLISION_EVENTS)
                .insert(Sensor);
        })


@@ 185,12 205,12 @@ fn spawn_planets(mut commands: Commands) {
            planet_type: PlanetType::Moon,
            transform: TransformBundle::from(moon_pos),
        })
        .insert(Collider::ball(MOON_SIZE))
        .insert(AdditionalMassProperties::Mass(MOON_MASS))
        .insert(Collider::ball(planet!(PlanetType::Moon).size))
        .insert(AdditionalMassProperties::Mass(planet!(PlanetType::Moon).mass))
        .insert(ReadMassProperties::default())
        .with_children(|children| {
            children
                .spawn(Collider::ball(MOON_SIZE + 0.1))
                .spawn(Collider::ball(planet!(PlanetType::Moon).size + 0.1))
                .insert(ActiveEvents::COLLISION_EVENTS)
                .insert(Sensor);
        })


@@ 201,12 221,12 @@ fn spawn_planets(mut commands: Commands) {
            planet_type: PlanetType::Mars,
            transform: TransformBundle::from(mars_pos),
        })
        .insert(Collider::ball(MARS_SIZE))
        .insert(AdditionalMassProperties::Mass(MARS_MASS))
        .insert(Collider::ball(planet!(PlanetType::Mars).size))
        .insert(AdditionalMassProperties::Mass(planet!(PlanetType::Mars).mass))
        .insert(ReadMassProperties::default())
        .with_children(|children| {
            children
                .spawn(Collider::ball(MARS_SIZE + 0.1))
                .spawn(Collider::ball(planet!(PlanetType::Mars).size + 0.1))
                .insert(ActiveEvents::COLLISION_EVENTS)
                .insert(Sensor);
        })


@@ 220,7 240,7 @@ fn module_spawn(
    mut packet_send: EventWriter<WsEvent>,
) {
    if module_timer.0.tick(time.delta()).just_finished()
        && part_query.iter().count() < part::FREE_MODULE_CAP
        && part_query.iter().count() < server_config().server.max_free_parts
    {
        let angle: f32 = {
            let mut rng = rand::thread_rng();


@@ 243,7 263,7 @@ fn module_spawn(
            })
            .insert(AdditionalMassProperties::MassProperties(MassProperties {
                local_center_of_mass: vec2(0.0, 0.0),
                mass: part::CARGO_MASS,
                mass: part!(PartType::Cargo).mass,
                principal_inertia: 7.5,
            }))
            .insert(ExternalForce::default())


@@ 369,8 389,8 @@ fn on_message(
                        input: component::Input::default(),
                        selected: None,
                        save_eligibility: false,
                        energy_capacity: part::HEARTY_CAPACITY,
                        energy: part::HEARTY_CAPACITY,
                        energy_capacity: part!(PartType::Hearty).energy_capacity,
                        energy: part!(PartType::Hearty).energy_capacity,
                    };
                    let mut entity_id = commands.spawn(PartBundle {
                        part_type: PartType::Hearty,


@@ 381,7 401,7 @@ fn on_message(
                        .insert(Collider::cuboid(0.5, 0.5))
                        .insert(AdditionalMassProperties::MassProperties(MassProperties {
                            local_center_of_mass: vec2(0.0, 0.0),
                            mass: part::HEARTY_MASS,
                            mass: part!(PartType::Hearty).mass,
                            principal_inertia: 7.5,
                        }))
                        .insert(ExternalImpulse {


@@ 449,9 469,9 @@ fn on_message(
                                    translation * CLIENT_SCALE
                                )),
                                radius: match *planet_type {
                                    PlanetType::Earth => EARTH_SIZE * CLIENT_SCALE,
                                    PlanetType::Moon => MOON_SIZE * CLIENT_SCALE,
                                    PlanetType::Mars => MARS_SIZE * CLIENT_SCALE,
                                    PlanetType::Earth => planet!(PlanetType::Earth).size * CLIENT_SCALE,
                                    PlanetType::Moon => planet!(PlanetType::Moon).size * CLIENT_SCALE,
                                    PlanetType::Mars => planet!(PlanetType::Mars).size * CLIENT_SCALE,
                                },
                            },
                        ));


@@ 1418,7 1438,7 @@ fn convert_modules_recursive(
                    *part_type = PartType::Hub;
                    *mass_prop = AdditionalMassProperties::MassProperties(MassProperties {
                        local_center_of_mass: Vec2::new(0.0, 0.0),
                        mass: part::HUB_MASS,
                        mass: part!(PartType::Hub).mass,
                        principal_inertia: 7.5,
                    });
                    let (mut collider, mut transform, _) =


@@ 1434,7 1454,7 @@ fn convert_modules_recursive(
                        .unwrap()
                        .insert(CanAttach(15));

                    increase_capacity_by += part::HUB_CAPACITY;
                    increase_capacity_by += part!(PartType::Hub).energy_capacity;

                    let packet = Packet::DespawnPart { id: child.index() };



@@ 1459,7 1479,7 @@ fn convert_modules_recursive(
                    *part_type = PartType::LandingThruster;
                    *mass_prop = AdditionalMassProperties::MassProperties(MassProperties {
                        local_center_of_mass: Vec2::new(0.0, 0.0),
                        mass: part::LANDING_THRUSTER_MASS,
                        mass: part!(PartType::LandingThruster).mass,
                        principal_inertia: 7.5,
                    });
                    let (mut collider, mut transform, _) =


@@ 1502,7 1522,7 @@ fn convert_modules_recursive(
                        });
                    attach.children[2] = Some(suspension.id());

                    increase_capacity_by += part::LANDING_THRUSTER_CAPACITY;
                    increase_capacity_by += part!(PartType::LandingThruster).energy_capacity;

                    let packet = Packet::DespawnPart { id: child.index() };



@@ 1817,9 1837,9 @@ fn on_position_change(
                    transform.translation * CLIENT_SCALE
                )),
                radius: match *planet_type {
                    PlanetType::Earth => EARTH_SIZE * CLIENT_SCALE,
                    PlanetType::Moon => MOON_SIZE * CLIENT_SCALE,
                    PlanetType::Mars => MARS_SIZE * CLIENT_SCALE,
                    PlanetType::Earth => planet!(PlanetType::Earth).size * CLIENT_SCALE,
                    PlanetType::Moon => planet!(PlanetType::Moon).size * CLIENT_SCALE,
                    PlanetType::Mars => planet!(PlanetType::Mars).size * CLIENT_SCALE,
                },
            },
        ));


@@ 1897,12 1917,12 @@ fn player_input_update(
        ];

        for (force_multiplier, x_offset, y_offset) in thrusters {
            if force_multiplier != 0.0 && player.energy >= HEARTY_THRUST_ENERGY {
                player.energy -= HEARTY_THRUST_ENERGY;
            if force_multiplier != 0.0 && player.energy >= part!(PartType::Hearty).thruster_energy {
                player.energy -= part!(PartType::Hearty).thruster_energy;
                let thruster_pos_uncast = vec2(x_offset, y_offset);
                let thruster_pos_cast =
                    rot2d(thruster_pos_uncast, rot) + transform.translation.xy();
                let thruster_force = force_multiplier * part::HEARTY_THRUSTER_FORCE;
                let thruster_force = force_multiplier * part!(PartType::Hearty).thruster_force;
                let thruster_vec = vec2(-thruster_force * rot.sin(), thruster_force * rot.cos());
                let thruster_force = ExternalForce::at_point(
                    thruster_vec,


@@ 1914,7 1934,7 @@ fn player_input_update(
            }
        }
        // change to support other thruster types later
        if player.energy >= LANDING_THRUSTER_ENERGY {
        if player.energy >= part!(PartType::LandingThruster).thruster_energy {
            search_thrusters(
                player.input,
                attach.clone(),


@@ 1953,8 1973,8 @@ fn search_thrusters(
        let mut force_mult = 0.;
        let mut energy_lose_by = 0;
        if *part_type == PartType::LandingThruster {
            force_mult = part::LANDING_THRUSTER_FORCE;
            energy_lose_by = LANDING_THRUSTER_ENERGY;
            force_mult = part!(PartType::LandingThruster).thruster_force;
            energy_lose_by = part!(PartType::LandingThruster).thruster_energy;
        }
        if input.up && 3. * PI / 4. < relative_angle && relative_angle < 5. * PI / 4. {
            let thruster_force = ExternalForce::at_point(


@@ 2134,7 2154,7 @@ fn gravity_update(
            let planet_mass = planet_mp.mass;
            let planet_translate = planet_transform.translation;
            let distance = planet_translate.distance(part_translate);
            let force = GRAVITY * ((part_mass * planet_mass) / (distance * distance));
            let force = server_config().world.gravity * ((part_mass * planet_mass) / (distance * distance));
            let direction = (planet_translate - part_translate).normalize() * force;
            /*let gravity_force = ExternalForce::at_point(
                direction.xy(),

M server/src/part.rs => server/src/part.rs +19 -38
@@ 1,36 1,9 @@
pub const HEARTY_THRUSTER_FORCE: f32 = 0.3;
pub const LANDING_THRUSTER_FORCE: f32 = 5.;

pub const HEARTY_MASS: f32 = 1.0;
pub const CARGO_MASS: f32 = 0.5;
pub const HUB_MASS: f32 = 1.0;
pub const LANDING_THRUSTER_MASS: f32 = 0.9;

// maybe make this only cargo modules later
pub const FREE_MODULE_CAP: usize = 30;

// energy capacity
pub const HEARTY_CAPACITY: u32 = 2000;
pub const LANDING_THRUSTER_CAPACITY: u32 = 1000;
pub const HUB_CAPACITY: u32 = 3000;

// energy/tick
pub const HEARTY_THRUST_ENERGY: u32 = 1;
pub const LANDING_THRUSTER_ENERGY: u32 = 3;

#[macro_export]
macro_rules! mass {
    ($p:expr) => {
        if $p == $crate::component::PartType::Hearty {
            $crate::part::HEARTY_MASS
        } else if $p == $crate::component::PartType::Cargo {
            $crate::part::CARGO_MASS
        } else if $p == $crate::component::PartType::Hub {
            $crate::part::HUB_MASS
        } else if $p == $crate::component::PartType::LandingThruster {
            $crate::part::LANDING_THRUSTER_MASS
        } else {
            1.
        match $crate::parts_config().parts.get(&$p) {
            Some(v) => v.mass,
            None => 1.0
        }
    };
}


@@ 38,14 11,22 @@ macro_rules! mass {
#[macro_export]
macro_rules! capacity {
    ($p:expr) => {
        if $p == $crate::component::PartType::Hearty {
            $crate::part::HEARTY_CAPACITY
        } else if $p == $crate::component::PartType::Hub {
            $crate::part::HUB_CAPACITY
        } else if $p == $crate::component::PartType::LandingThruster {
            $crate::part::LANDING_THRUSTER_CAPACITY
        } else {
            0
        match $crate::parts_config().parts.get(&$p) {
            Some(v) => v.energy_capacity,
            None => 0
        }
    };
}

#[macro_export]
macro_rules! planet {
    ($t:expr) => {
        $crate::planets_config().planets.get(&$t).unwrap()
    };
}
#[macro_export]
macro_rules! part {
    ($t:expr) => {
        $crate::parts_config().parts.get(&$t).unwrap()
    };
}
\ No newline at end of file