// StarKingdoms.IO, a browser game about drifting through space // Copyright (C) 2023 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 . #![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::net::IpAddr; use crate::mathutil::rot2d; use bevy::math::{vec2, vec3}; use bevy::{ app::{PluginGroupBuilder, ScheduleRunnerPlugin}, ecs::event::ManualEventReader, prelude::*, time::TimePlugin, }; use bevy_rapier2d::prelude::*; use bevy_tungstenite_stk::{StkTungsteniteServerConfig, StkTungsteniteServerPlugin, WsEvent}; use component::Input; use component::*; use hmac::{Hmac, Mac}; use jwt::VerifyWithKey; use packet::*; 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::str::FromStr; use std::time::Duration; pub mod component; pub mod macros; pub mod mathutil; pub mod packet; const CLIENT_SCALE: f32 = 50.; 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; const HEARTY_THRUSTER_FORCE: f32 = 0.3; const LANDING_THRUSTER_FORCE: f32 = 5.; const HEARTY_MASS: f32 = 1.; const CARGO_MASS: f32 = 0.5; const HUB_MASS: f32 = 1.; const LANDING_THRUSTER_MASS: f32 = 0.9; // maybe make this only cargo modules later const FREE_MODULE_CAP: usize = 30; struct StkPluginGroup; #[cfg(debug_assertions)] impl PluginGroup for StkPluginGroup { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() .add(TaskPoolPlugin::default()) .add(TypeRegistrationPlugin) .add(FrameCountPlugin) .add(TimePlugin) .add(ScheduleRunnerPlugin::run_loop(Duration::from_millis(1))) .add(bevy::log::LogPlugin { level: bevy::log::Level::DEBUG, filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(), }) } } #[cfg(not(debug_assertions))] impl PluginGroup for StkPluginGroup { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() .add(TaskPoolPlugin::default()) .add(TypeRegistrationPlugin) .add(FrameCountPlugin) .add(TimePlugin) .add(ScheduleRunnerPlugin::run_loop(Duration::from_millis(1))) } } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct UserToken { pub id: i64, pub username: String, pub permission_level: i32, pub expires: std::time::SystemTime, } pub const REQUIRED_PERM_LEVEL: i32 = 10; fn main() { // read the key in let key = std::fs::read_to_string("/etc/starkingdoms/app_key").unwrap(); App::new() .insert_resource(AppKeys { app_key: key.into_bytes(), }) .insert_resource(StkTungsteniteServerConfig { addr: IpAddr::from_str("0.0.0.0").unwrap(), port: 3000, }) .add_plugins(StkPluginGroup) .insert_resource(RapierConfiguration { gravity: Vect { x: 0.0, y: 0.0 }, ..Default::default() }) .init_resource::() .add_plugins(RapierPhysicsPlugin::::pixels_per_meter(1.0)) .add_plugins(StkTungsteniteServerPlugin) .add_systems(Startup, setup_integration_parameters) .add_systems(Startup, spawn_planets) .add_systems(FixedUpdate, module_spawn) .add_systems(Update, on_message) .add_systems(Update, on_close) .add_systems(FixedUpdate, on_position_change) .add_systems( FixedUpdate, (break_modules, gravity_update, player_input_update).chain(), ) .add_systems(FixedUpdate, save_eligibility) .add_systems(FixedUpdate, convert_modules) //.insert_resource(Time::::from_seconds(1.0/1.0)) .run(); info!("Goodbye!"); } fn setup_integration_parameters(mut context: ResMut) { context.integration_parameters.dt = 1.0 / 60.0; context.integration_parameters.joint_erp = 0.2; context.integration_parameters.erp = 0.5; context.integration_parameters.max_stabilization_iterations = 16; } fn spawn_planets(mut commands: Commands) { info!("Spawning planets"); let earth_pos = Transform::from_xyz(0.0, 0.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Earth, transform: TransformBundle::from(earth_pos), }) .insert(Collider::ball(EARTH_SIZE)) .insert(AdditionalMassProperties::Mass(EARTH_MASS)) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(EARTH_SIZE + 0.3)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); let moon_pos = Transform::from_xyz(50.0, 0.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Moon, transform: TransformBundle::from(moon_pos), }) .insert(Collider::ball(MOON_SIZE)) .insert(AdditionalMassProperties::Mass(MOON_MASS)) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(MOON_SIZE + 0.1)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); let mars_pos = Transform::from_xyz(50.0, 20.0, 0.0); commands .spawn(PlanetBundle { planet_type: PlanetType::Mars, transform: TransformBundle::from(mars_pos), }) .insert(Collider::ball(MARS_SIZE)) .insert(AdditionalMassProperties::Mass(MARS_MASS)) .insert(ReadMassProperties::default()) .with_children(|children| { children .spawn(Collider::ball(MARS_SIZE + 0.1)) .insert(ActiveEvents::COLLISION_EVENTS) .insert(Sensor); }) .insert(RigidBody::Fixed); } fn module_spawn( mut commands: Commands, time: Res