mirror of
https://github.com/eliasstepanik/voxel-simulation.git
synced 2026-01-11 05:48:29 +00:00
Fixed Rotation and scale and rotation sync.
Moved Input To its own Plugin. Moved the camera to the Environment Plugin
This commit is contained in:
parent
9442befb27
commit
befbfb8935
@ -5,6 +5,7 @@ edition = "2024"
|
|||||||
description = "Horror-Game"
|
description = "Horror-Game"
|
||||||
repository = "https://github.com/eliasstepanik/horror-game"
|
repository = "https://github.com/eliasstepanik/horror-game"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -19,4 +20,8 @@ egui_dock = "0.14.0"
|
|||||||
spacetimedb-sdk = "1.0"
|
spacetimedb-sdk = "1.0"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
random_word = { version = "0.5.0", features = ["en"] }
|
random_word = { version = "0.5.0", features = ["en"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
toml = "0.8"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
6
client/Config.toml
Normal file
6
client/Config.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[server]
|
||||||
|
host = "http://100.85.241.101:3000"
|
||||||
|
database = "network-game"
|
||||||
|
|
||||||
|
[movement]
|
||||||
|
mode = "fligt"
|
||||||
10
client/build.rs
Normal file
10
client/build.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||||
|
let target_dir = Path::new(&out_dir).ancestors().nth(3).unwrap(); // gets target/debug or release
|
||||||
|
|
||||||
|
fs::copy("config.toml", target_dir.join("config.toml"))
|
||||||
|
.expect("Failed to copy config.toml to target directory");
|
||||||
|
}
|
||||||
@ -24,12 +24,10 @@ impl Plugin for AppPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(UiState::new());
|
app.insert_resource(UiState::new());
|
||||||
app.insert_resource(InspectorVisible(true));
|
app.insert_resource(InspectorVisible(true));
|
||||||
|
|
||||||
app.add_plugins(crate::plugins::camera::camera_plugin::CameraPlugin);
|
|
||||||
app.add_plugins(crate::plugins::ui::ui_plugin::UiPlugin);
|
app.add_plugins(crate::plugins::ui::ui_plugin::UiPlugin);
|
||||||
app.add_plugins(crate::plugins::environment::environment_plugin::EnvironmentPlugin);
|
app.add_plugins(crate::plugins::environment::environment_plugin::EnvironmentPlugin);
|
||||||
app.add_plugins(crate::plugins::network::network_plugin::NetworkPlugin);
|
app.add_plugins(crate::plugins::network::network_plugin::NetworkPlugin);
|
||||||
|
app.add_plugins(crate::plugins::input::input_plugin::InputPlugin);
|
||||||
|
|
||||||
app.add_systems(Update, (debug_gizmos, toggle_ui_system));
|
app.add_systems(Update, (debug_gizmos, toggle_ui_system));
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
|
|||||||
15
client/src/config.rs
Normal file
15
client/src/config.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use bevy::prelude::Resource;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Resource)]
|
||||||
|
pub struct Config {
|
||||||
|
pub server: ServerConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct ServerConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub database: String,
|
||||||
|
|
||||||
|
}
|
||||||
12
client/src/helper/math.rs
Normal file
12
client/src/helper/math.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
pub trait RoundTo {
|
||||||
|
/// Rounds `self` to `decimals` places.
|
||||||
|
fn round_to(self, decimals: u32) -> f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoundTo for f32 {
|
||||||
|
#[inline]
|
||||||
|
fn round_to(self, decimals: u32) -> f32 {
|
||||||
|
let factor = 10f32.powi(decimals as i32);
|
||||||
|
(self * factor).round() / factor
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1,4 @@
|
|||||||
pub mod debug_gizmos;
|
pub mod debug_gizmos;
|
||||||
pub mod egui_dock;
|
pub mod egui_dock;
|
||||||
|
pub mod vector_helper;
|
||||||
|
pub mod math;
|
||||||
|
|||||||
30
client/src/helper/vector_helper.rs
Normal file
30
client/src/helper/vector_helper.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use bevy::math::Vec3;
|
||||||
|
use bevy::prelude::{Quat, Transform};
|
||||||
|
use rand::Rng;
|
||||||
|
use crate::helper::math::RoundTo;
|
||||||
|
use crate::module_bindings::DbTransform;
|
||||||
|
|
||||||
|
pub(crate) fn random_vec3(min: f32, max: f32) -> Vec3 {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
Vec3::new(
|
||||||
|
rng.gen_range(min..max),
|
||||||
|
rng.gen_range(min..max),
|
||||||
|
rng.gen_range(min..max),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DbTransform> for Transform {
|
||||||
|
fn from(db: DbTransform) -> Self {
|
||||||
|
Transform {
|
||||||
|
translation: Vec3::new(db.position.x, db.position.y, db.position.z),
|
||||||
|
rotation: //Quat::from_xyzw(0.0, 0.0, 0.0, 0.0),
|
||||||
|
Quat::from_xyzw(
|
||||||
|
db.rotation.x.round_to(3),
|
||||||
|
db.rotation.y.round_to(3),
|
||||||
|
db.rotation.z.round_to(3),
|
||||||
|
db.rotation.w.round_to(3),
|
||||||
|
),
|
||||||
|
scale: Vec3::new(db.scale.x.round_to(3), db.scale.y.round_to(3), db.scale.z.round_to(3)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,9 @@ mod app;
|
|||||||
mod helper;
|
mod helper;
|
||||||
mod plugins;
|
mod plugins;
|
||||||
mod module_bindings;
|
mod module_bindings;
|
||||||
|
mod config;
|
||||||
|
|
||||||
|
use std::fs;
|
||||||
use crate::app::AppPlugin;
|
use crate::app::AppPlugin;
|
||||||
use bevy::gizmos::{AppGizmoBuilder, GizmoPlugin};
|
use bevy::gizmos::{AppGizmoBuilder, GizmoPlugin};
|
||||||
use bevy::log::info;
|
use bevy::log::info;
|
||||||
@ -13,6 +15,8 @@ use bevy::DefaultPlugins;
|
|||||||
use bevy_egui::EguiPlugin;
|
use bevy_egui::EguiPlugin;
|
||||||
use bevy_inspector_egui::DefaultInspectorConfigPlugin;
|
use bevy_inspector_egui::DefaultInspectorConfigPlugin;
|
||||||
use bevy_window::{PresentMode, Window, WindowPlugin};
|
use bevy_window::{PresentMode, Window, WindowPlugin};
|
||||||
|
use toml;
|
||||||
|
use crate::config::Config;
|
||||||
|
|
||||||
const TITLE: &str = "horror-game";
|
const TITLE: &str = "horror-game";
|
||||||
const RESOLUTION: (f32, f32) = (1920f32, 1080f32);
|
const RESOLUTION: (f32, f32) = (1920f32, 1080f32);
|
||||||
@ -21,13 +25,27 @@ const DECORATIONS: bool = true;
|
|||||||
const TRANSPARENT: bool = true;
|
const TRANSPARENT: bool = true;
|
||||||
const PRESENT_MODE: PresentMode = PresentMode::AutoVsync;
|
const PRESENT_MODE: PresentMode = PresentMode::AutoVsync;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let config_str = fs::read_to_string("Config.toml").expect("Failed to read config file");
|
||||||
|
let config: Config = toml::from_str(&config_str).expect("Failed to parse config");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
|
app.insert_resource(config);
|
||||||
|
|
||||||
register_platform_plugins(&mut app);
|
register_platform_plugins(&mut app);
|
||||||
|
|
||||||
app.add_plugins(AppPlugin);
|
app.add_plugins(AppPlugin);
|
||||||
app.add_plugins(EguiPlugin);
|
app.add_plugins(EguiPlugin);
|
||||||
app.add_plugins(DefaultInspectorConfigPlugin);
|
app.add_plugins(DefaultInspectorConfigPlugin);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*app.add_plugins(GizmoPlugin);*/
|
/*app.add_plugins(GizmoPlugin);*/
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
use bevy::a11y::AccessibilitySystem::Update;
|
|
||||||
use bevy::app::{App, Plugin, PreUpdate, Startup};
|
|
||||||
|
|
||||||
pub struct CameraPlugin;
|
|
||||||
impl Plugin for CameraPlugin {
|
|
||||||
fn build(&self, _app: &mut App) {
|
|
||||||
_app.add_systems(
|
|
||||||
Startup,
|
|
||||||
(crate::plugins::camera::systems::camera_system::setup),
|
|
||||||
);
|
|
||||||
_app.add_systems(
|
|
||||||
PreUpdate,
|
|
||||||
(crate::plugins::camera::systems::camera_system::camera_controller_system),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
pub mod camera_plugin;
|
|
||||||
pub mod systems;
|
|
||||||
@ -1 +0,0 @@
|
|||||||
pub mod camera_system;
|
|
||||||
@ -1,6 +1,11 @@
|
|||||||
use bevy::app::{App, Plugin};
|
use bevy::app::{App, Plugin, PreStartup, PreUpdate, Startup};
|
||||||
pub struct EnvironmentPlugin;
|
pub struct EnvironmentPlugin;
|
||||||
impl Plugin for EnvironmentPlugin {
|
impl Plugin for EnvironmentPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
|
|
||||||
|
app.add_systems(
|
||||||
|
Startup,
|
||||||
|
(crate::plugins::environment::systems::camera_system::setup),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
53
client/src/plugins/environment/systems/camera_system.rs
Normal file
53
client/src/plugins/environment/systems/camera_system.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use crate::helper::egui_dock::MainCamera;
|
||||||
|
use bevy::input::mouse::{MouseMotion, MouseWheel};
|
||||||
|
use bevy::math::Vec3;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_render::camera::{Exposure, PhysicalCameraParameters, Projection};
|
||||||
|
use bevy_window::CursorGrabMode;
|
||||||
|
use rand::Rng;
|
||||||
|
use random_word::Lang;
|
||||||
|
use crate::module_bindings::{set_name, set_position, spawn_entity, DbTransform, DbVector3, DbVector4};
|
||||||
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct CameraController {
|
||||||
|
pub yaw: f32,
|
||||||
|
pub pitch: f32,
|
||||||
|
pub speed: f32,
|
||||||
|
pub sensitivity: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CameraController {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
yaw: 0.0,
|
||||||
|
pitch: 0.0,
|
||||||
|
speed: 10.0,
|
||||||
|
sensitivity: 0.1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(mut commands: Commands,) {
|
||||||
|
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
Transform::from_xyz(0.0, 0.0, 10.0), // initial f32
|
||||||
|
GlobalTransform::default(),
|
||||||
|
Camera3d::default(),
|
||||||
|
Projection::from(PerspectiveProjection {
|
||||||
|
near: 0.0001,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
MainCamera,
|
||||||
|
CameraController::default(),
|
||||||
|
Exposure::from_physical_camera(PhysicalCameraParameters {
|
||||||
|
aperture_f_stops: 1.0,
|
||||||
|
shutter_speed_s: 1.0 / 125.0,
|
||||||
|
sensitivity_iso: 100.0,
|
||||||
|
sensor_height: 0.01866,
|
||||||
|
}),
|
||||||
|
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
@ -1 +1,2 @@
|
|||||||
pub mod environment_system;
|
pub mod environment_system;
|
||||||
|
pub mod camera_system;
|
||||||
|
|||||||
20
client/src/plugins/input/input_plugin.rs
Normal file
20
client/src/plugins/input/input_plugin.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
use bevy::app::{App, Plugin, PreUpdate, Startup};
|
||||||
|
use bevy::prelude::{IntoSystemConfigs, Update};
|
||||||
|
|
||||||
|
pub struct InputPlugin;
|
||||||
|
impl Plugin for InputPlugin {
|
||||||
|
fn build(&self, _app: &mut App) {
|
||||||
|
_app.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
crate::plugins::input::systems::console::console_system,
|
||||||
|
crate::plugins::input::systems::flight::flight_systems,
|
||||||
|
crate::plugins::input::systems::ui::ui_system,
|
||||||
|
crate::plugins::input::systems::network::network_system,
|
||||||
|
crate::plugins::input::systems::movement::movement_system,
|
||||||
|
),
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
client/src/plugins/input/mod.rs
Normal file
2
client/src/plugins/input/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod systems;
|
||||||
|
pub mod input_plugin;
|
||||||
23
client/src/plugins/input/systems/console.rs
Normal file
23
client/src/plugins/input/systems/console.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use bevy::app::AppExit;
|
||||||
|
use bevy::input::ButtonInput;
|
||||||
|
use bevy::input::mouse::{MouseMotion, MouseWheel};
|
||||||
|
use bevy::prelude::{EventReader, EventWriter, KeyCode, Query, Res, ResMut, Time, Transform};
|
||||||
|
use bevy_window::Window;
|
||||||
|
use crate::plugins::environment::systems::camera_system::CameraController;
|
||||||
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
|
pub fn console_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>, /*
|
||||||
|
mouse_button_input: Res<ButtonInput<MouseButton>>,*/
|
||||||
|
mut mouse_motion_events: EventReader<MouseMotion>,
|
||||||
|
mut mouse_wheel_events: EventReader<MouseWheel>,
|
||||||
|
mut windows: Query<&mut Window>,
|
||||||
|
mut query: Query<(&mut Transform, &mut CameraController)>,
|
||||||
|
mut app_exit_events: EventWriter<AppExit>,
|
||||||
|
mut ctx: ResMut<DbConnectionResource>,
|
||||||
|
) {
|
||||||
|
let mut window = windows.single_mut();
|
||||||
|
let (mut transform, mut controller) = query.single_mut();
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,68 +1,16 @@
|
|||||||
use crate::helper::egui_dock::MainCamera;
|
use bevy::app::AppExit;
|
||||||
|
use bevy::input::ButtonInput;
|
||||||
use bevy::input::mouse::{MouseMotion, MouseWheel};
|
use bevy::input::mouse::{MouseMotion, MouseWheel};
|
||||||
use bevy::math::Vec3;
|
use bevy::math::{Quat, Vec3};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::{EventReader, EventWriter, KeyCode, Query, Res, ResMut, Time, Transform};
|
||||||
use bevy_render::camera::{Exposure, PhysicalCameraParameters, Projection};
|
use bevy_window::{CursorGrabMode, Window};
|
||||||
use bevy_window::CursorGrabMode;
|
|
||||||
use rand::Rng;
|
|
||||||
use random_word::Lang;
|
use random_word::Lang;
|
||||||
use crate::module_bindings::{set_name, set_position, spawn_entity, DbTransform, DbVector3, DbVector4};
|
use crate::module_bindings::{set_name, set_position, spawn_entity, DbTransform, DbVector3, DbVector4};
|
||||||
|
use crate::plugins::environment::systems::camera_system::CameraController;
|
||||||
use crate::plugins::network::systems::database::DbConnectionResource;
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
#[derive(Component)]
|
/// Example system to input a camera using double-precision for position.
|
||||||
pub struct CameraController {
|
pub fn flight_systems(
|
||||||
pub yaw: f32,
|
|
||||||
pub pitch: f32,
|
|
||||||
pub speed: f32,
|
|
||||||
pub sensitivity: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CameraController {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
yaw: 0.0,
|
|
||||||
pitch: 0.0,
|
|
||||||
speed: 10.0,
|
|
||||||
sensitivity: 0.1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup(mut commands: Commands,
|
|
||||||
db_resource: Res<DbConnectionResource>,) {
|
|
||||||
|
|
||||||
|
|
||||||
commands.spawn((
|
|
||||||
Transform::from_xyz(0.0, 0.0, 10.0), // initial f32
|
|
||||||
GlobalTransform::default(),
|
|
||||||
Camera3d::default(),
|
|
||||||
Projection::from(PerspectiveProjection {
|
|
||||||
near: 0.0001,
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
MainCamera,
|
|
||||||
CameraController::default(),
|
|
||||||
Exposure::from_physical_camera(PhysicalCameraParameters {
|
|
||||||
aperture_f_stops: 1.0,
|
|
||||||
shutter_speed_s: 1.0 / 125.0,
|
|
||||||
sensitivity_iso: 100.0,
|
|
||||||
sensor_height: 0.01866,
|
|
||||||
}),
|
|
||||||
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random_vec3(min: f32, max: f32) -> Vec3 {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
Vec3::new(
|
|
||||||
rng.gen_range(min..max),
|
|
||||||
rng.gen_range(min..max),
|
|
||||||
rng.gen_range(min..max),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Example system to control a camera using double-precision for position.
|
|
||||||
pub fn camera_controller_system(
|
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>, /*
|
keyboard_input: Res<ButtonInput<KeyCode>>, /*
|
||||||
mouse_button_input: Res<ButtonInput<MouseButton>>,*/
|
mouse_button_input: Res<ButtonInput<MouseButton>>,*/
|
||||||
@ -110,34 +58,6 @@ pub fn camera_controller_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let word = random_word::get(Lang::En);
|
|
||||||
|
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyQ) {
|
|
||||||
ctx.0.reducers.set_name(word.to_string()).unwrap();
|
|
||||||
}
|
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyE) {
|
|
||||||
let rand_position = random_vec3(-10.0,10.0);
|
|
||||||
let rand_rotation = random_vec3(-10.0,10.0);
|
|
||||||
let rand_scale = random_vec3(0.1,1.0);
|
|
||||||
ctx.0.reducers.spawn_entity(DbTransform{
|
|
||||||
position: DbVector3{
|
|
||||||
x: rand_position.x,
|
|
||||||
y: rand_position.y,
|
|
||||||
z: rand_position.z,
|
|
||||||
},
|
|
||||||
rotation: DbVector4 {
|
|
||||||
x: rand_rotation.x,
|
|
||||||
y: rand_rotation.y,
|
|
||||||
z: rand_position.z,
|
|
||||||
w: 0.0,
|
|
||||||
},
|
|
||||||
scale: DbVector3 {
|
|
||||||
x: rand_scale.x,
|
|
||||||
y: rand_scale.x,
|
|
||||||
z: rand_scale.x,
|
|
||||||
},
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
// 3) Handle Keyboard Movement (WASD, Space, Shift)
|
// 3) Handle Keyboard Movement (WASD, Space, Shift)
|
||||||
@ -183,30 +103,7 @@ pub fn camera_controller_system(
|
|||||||
y: transform.translation.y,
|
y: transform.translation.y,
|
||||||
z: transform.translation.z,
|
z: transform.translation.z,
|
||||||
}).expect("TODO: panic message");
|
}).expect("TODO: panic message");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
// =========================
|
|
||||||
// 4) Lock/Unlock Mouse (L)
|
|
||||||
// =========================
|
|
||||||
if keyboard_input.just_pressed(KeyCode::KeyL) {
|
|
||||||
// Toggle between locked and unlocked
|
|
||||||
if window.cursor_options.grab_mode == CursorGrabMode::None {
|
|
||||||
// Lock
|
|
||||||
window.cursor_options.visible = false;
|
|
||||||
window.cursor_options.grab_mode = CursorGrabMode::Locked;
|
|
||||||
} else {
|
|
||||||
// Unlock
|
|
||||||
window.cursor_options.visible = true;
|
|
||||||
window.cursor_options.grab_mode = CursorGrabMode::None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================
|
|
||||||
// 7) Exit on Escape
|
|
||||||
// =======================
|
|
||||||
if keyboard_input.pressed(KeyCode::Escape) {
|
|
||||||
app_exit_events.send(Default::default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
5
client/src/plugins/input/systems/mod.rs
Normal file
5
client/src/plugins/input/systems/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub mod movement;
|
||||||
|
pub mod flight;
|
||||||
|
pub mod console;
|
||||||
|
pub mod ui;
|
||||||
|
pub mod network;
|
||||||
22
client/src/plugins/input/systems/movement.rs
Normal file
22
client/src/plugins/input/systems/movement.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use bevy::app::AppExit;
|
||||||
|
use bevy::input::ButtonInput;
|
||||||
|
use bevy::input::mouse::{MouseMotion, MouseWheel};
|
||||||
|
use bevy::prelude::{EventReader, EventWriter, KeyCode, Query, Res, ResMut, Time, Transform};
|
||||||
|
use bevy_window::Window;
|
||||||
|
use crate::plugins::environment::systems::camera_system::CameraController;
|
||||||
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
|
|
||||||
|
///TODO
|
||||||
|
pub fn movement_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>, /*
|
||||||
|
mouse_button_input: Res<ButtonInput<MouseButton>>,*/
|
||||||
|
mut mouse_motion_events: EventReader<MouseMotion>,
|
||||||
|
mut mouse_wheel_events: EventReader<MouseWheel>,
|
||||||
|
mut windows: Query<&mut Window>,
|
||||||
|
mut query: Query<(&mut Transform, &mut CameraController)>,
|
||||||
|
mut app_exit_events: EventWriter<AppExit>,
|
||||||
|
mut ctx: ResMut<DbConnectionResource>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
47
client/src/plugins/input/systems/network.rs
Normal file
47
client/src/plugins/input/systems/network.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
use bevy::input::ButtonInput;
|
||||||
|
use bevy::math::{EulerRot, Quat};
|
||||||
|
use bevy::prelude::{KeyCode, Res, ResMut,};
|
||||||
|
use random_word::Lang;
|
||||||
|
use crate::module_bindings::{set_name, spawn_entity, DbTransform, DbVector3, DbVector4};
|
||||||
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
|
pub fn network_system(
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
ctx: ResMut<DbConnectionResource>,
|
||||||
|
) {
|
||||||
|
let word = random_word::get(Lang::En);
|
||||||
|
|
||||||
|
if keyboard_input.just_pressed(KeyCode::KeyQ) {
|
||||||
|
ctx.0.reducers.set_name(word.to_string()).unwrap();
|
||||||
|
}
|
||||||
|
if keyboard_input.just_pressed(KeyCode::KeyE) {
|
||||||
|
let rand_position = crate::helper::vector_helper::random_vec3(-10.0, 10.0);
|
||||||
|
let rand_rotation = crate::helper::vector_helper::random_vec3(0.0, 10.0);
|
||||||
|
let rand_rotation = Quat::from_euler(EulerRot::XYZ,rand_rotation.x,rand_rotation.y,rand_rotation.z).normalize();
|
||||||
|
let rand_scale = crate::helper::vector_helper::random_vec3(0.1, 1.0);
|
||||||
|
ctx.0.reducers.spawn_entity(DbTransform{
|
||||||
|
position: DbVector3{
|
||||||
|
x: rand_position.x,
|
||||||
|
y: rand_position.y,
|
||||||
|
z: rand_position.z,
|
||||||
|
},
|
||||||
|
rotation: DbVector4 {
|
||||||
|
x: rand_rotation.x,
|
||||||
|
y: rand_rotation.y,
|
||||||
|
z: rand_rotation.z,
|
||||||
|
w: rand_rotation.w,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
scale: DbVector3 {
|
||||||
|
x: rand_scale.x,
|
||||||
|
y: rand_scale.x,
|
||||||
|
z: rand_scale.x,
|
||||||
|
},
|
||||||
|
}).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
29
client/src/plugins/input/systems/ui.rs
Normal file
29
client/src/plugins/input/systems/ui.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use bevy::app::AppExit;
|
||||||
|
use bevy::input::ButtonInput;
|
||||||
|
use bevy::prelude::{EventWriter, KeyCode, Query, Res,};
|
||||||
|
use bevy_window::{CursorGrabMode, Window};
|
||||||
|
|
||||||
|
pub fn ui_system(
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut app_exit_events: EventWriter<AppExit>,
|
||||||
|
mut windows: Query<&mut Window>,
|
||||||
|
) {
|
||||||
|
let mut window = windows.single_mut();
|
||||||
|
|
||||||
|
if keyboard_input.just_pressed(KeyCode::KeyL) {
|
||||||
|
// Toggle between locked and unlocked
|
||||||
|
if window.cursor_options.grab_mode == CursorGrabMode::None {
|
||||||
|
// Lock
|
||||||
|
window.cursor_options.visible = false;
|
||||||
|
window.cursor_options.grab_mode = CursorGrabMode::Locked;
|
||||||
|
} else {
|
||||||
|
// Unlock
|
||||||
|
window.cursor_options.visible = true;
|
||||||
|
window.cursor_options.grab_mode = CursorGrabMode::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if keyboard_input.pressed(KeyCode::Escape) {
|
||||||
|
app_exit_events.send(Default::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
pub mod camera;
|
|
||||||
pub mod environment;
|
pub mod environment;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
|
pub mod input;
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ pub struct NetworkPlugin;
|
|||||||
impl Plugin for NetworkPlugin {
|
impl Plugin for NetworkPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(PreStartup, setup_database);
|
app.add_systems(PreStartup, setup_database);
|
||||||
app.add_systems(Startup, init);
|
app.add_systems(PostUpdate, sync_entities_system);
|
||||||
app.add_systems(Update, sync_entities_system);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
use std::ops::Deref;
|
||||||
use bevy::ecs::system::SystemState;
|
use bevy::ecs::system::SystemState;
|
||||||
use bevy::prelude::{Commands, Resource, World};
|
use bevy::prelude::{Commands, DetectChanges, Mut, Res, ResMut, Resource, World};
|
||||||
use bevy::utils::info;
|
use bevy::utils::info;
|
||||||
use spacetimedb_sdk::{credentials, DbContext, Error, Event, Identity, Status, Table, TableWithPrimaryKey};
|
use spacetimedb_sdk::{credentials, DbContext, Error, Event, Identity, Status, Table, TableWithPrimaryKey};
|
||||||
|
use crate::config::ServerConfig;
|
||||||
use crate::module_bindings::*;
|
use crate::module_bindings::*;
|
||||||
use crate::plugins::network::systems::callbacks::*;
|
use crate::plugins::network::systems::callbacks::*;
|
||||||
use crate::plugins::network::systems::connection::*;
|
use crate::plugins::network::systems::connection::*;
|
||||||
@ -16,9 +19,9 @@ const DB_NAME: &str = "network-game";
|
|||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct DbConnectionResource(pub(crate) DbConnection);
|
pub struct DbConnectionResource(pub(crate) DbConnection);
|
||||||
|
|
||||||
pub fn setup_database(mut commands: Commands) {
|
pub fn setup_database(mut commands: Commands, config: Res<crate::Config>) {
|
||||||
// Call your connection function and insert the connection as a resource.
|
// Call your connection function and insert the connection as a resource.
|
||||||
let ctx = connect_to_db();
|
let ctx = connect_to_db(config);
|
||||||
register_callbacks(&ctx);
|
register_callbacks(&ctx);
|
||||||
subscribe_to_tables(&ctx);
|
subscribe_to_tables(&ctx);
|
||||||
ctx.run_threaded();
|
ctx.run_threaded();
|
||||||
@ -30,13 +33,16 @@ pub fn setup_database(mut commands: Commands) {
|
|||||||
|
|
||||||
/// Register subscriptions for all rows of both tables
|
/// Register subscriptions for all rows of both tables
|
||||||
|
|
||||||
fn connect_to_db() -> DbConnection {
|
fn connect_to_db(config: Res<crate::Config>) -> DbConnection {
|
||||||
|
|
||||||
|
println!("It's there: {:?}", &config.server);
|
||||||
|
|
||||||
DbConnection::builder()
|
DbConnection::builder()
|
||||||
.on_connect(on_connected)
|
.on_connect(on_connected)
|
||||||
.on_connect_error(on_connect_error)
|
.on_connect_error(on_connect_error)
|
||||||
.on_disconnect( on_disconnected)
|
.on_disconnect( on_disconnected)
|
||||||
.with_module_name(DB_NAME)
|
.with_module_name(&config.server.database)
|
||||||
.with_uri(HOST)
|
.with_uri(&config.server.host)
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to connect")
|
.expect("Failed to connect")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use bevy::math::Vec3;
|
use bevy::log::debug;
|
||||||
|
use bevy::math::{NormedVectorSpace, Vec3};
|
||||||
use bevy::pbr::{MeshMaterial3d, StandardMaterial};
|
use bevy::pbr::{MeshMaterial3d, StandardMaterial};
|
||||||
use bevy::prelude::{default, Bundle, Commands, Component, Cuboid, DespawnRecursiveExt, Entity, GlobalTransform, Mesh, Quat, Query, Res, ResMut, Sphere, Transform};
|
use bevy::prelude::{default, info, Bundle, Commands, Component, Cuboid, DespawnRecursiveExt, DetectChangesMut, Entity, GlobalTransform, Mesh, PbrBundle, Quat, Query, Res, ResMut, Sphere, Transform, TransformBundle};
|
||||||
use bevy_asset::Assets;
|
use bevy_asset::Assets;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_render::mesh::Mesh3d;
|
use bevy_render::mesh::Mesh3d;
|
||||||
use spacetimedb_sdk::Table;
|
use spacetimedb_sdk::Table;
|
||||||
|
use crate::helper::math::RoundTo;
|
||||||
use crate::module_bindings::{DbTransform, DbVector3, EntityTableAccess, EntityType};
|
use crate::module_bindings::{DbTransform, DbVector3, EntityTableAccess, EntityType};
|
||||||
use crate::plugins::network::systems::database::DbConnectionResource;
|
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||||
|
|
||||||
@ -18,35 +20,18 @@ pub struct EntityDto {
|
|||||||
pub transform: DbTransform,
|
pub transform: DbTransform,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::module_bindings::Entity> for EntityDto {
|
||||||
|
fn from(e: crate::module_bindings::Entity) -> Self {
|
||||||
pub fn init(mut commands: Commands,
|
EntityDto {
|
||||||
ctx: Res<DbConnectionResource>,
|
entity_id: e.entity_id,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
transform: e.transform,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,) {
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let debug_material = materials.add(StandardMaterial { ..default() });
|
|
||||||
|
|
||||||
for entity in ctx.0.db.entity().iter() {
|
|
||||||
commands.spawn((
|
|
||||||
Mesh3d(meshes.add(Cuboid::default()),),
|
|
||||||
MeshMaterial3d(debug_material.clone ()),
|
|
||||||
db_transfrom_to_transfrom(entity.transform.clone()),
|
|
||||||
EntityDto{
|
|
||||||
entity_id: entity.entity_id,
|
|
||||||
transform: entity.transform
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// System that syncs DB entities with the Bevy ECS
|
// System that syncs DB entities with the Bevy ECS
|
||||||
pub fn sync_entities_system(
|
pub fn sync_entities_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
@ -54,7 +39,7 @@ pub fn sync_entities_system(
|
|||||||
|
|
||||||
// We need the Entity handle for potential despawning,
|
// We need the Entity handle for potential despawning,
|
||||||
// plus mutable references if we want to update Transform/EntityDto
|
// plus mutable references if we want to update Transform/EntityDto
|
||||||
mut query: Query<(Entity, &mut Transform, &mut EntityDto)>,
|
mut query: Query<(Entity, &mut Transform, &mut GlobalTransform, &mut EntityDto)>,
|
||||||
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
@ -67,16 +52,20 @@ pub fn sync_entities_system(
|
|||||||
for db_entity in db_entities.iter() {
|
for db_entity in db_entities.iter() {
|
||||||
|
|
||||||
// Try to find a matching ECS entity by entity_id
|
// Try to find a matching ECS entity by entity_id
|
||||||
if let Some((_, mut transform, mut dto)) =
|
if let Some((_, mut transform, mut global, mut dto)) =
|
||||||
query.iter_mut().find(|(_, _, dto)| dto.entity_id == db_entity.entity_id)
|
query.iter_mut().find(|(_, _, _, dto)| dto.entity_id == db_entity.entity_id)
|
||||||
{
|
{
|
||||||
// Update fields
|
// Update fields
|
||||||
dto.transform.position = db_entity.transform.position.clone();
|
|
||||||
transform.translation = Vec3::new(
|
// build the new local Transform
|
||||||
db_entity.transform.position.x,
|
let new_tf = Transform::from(db_entity.transform.clone());
|
||||||
db_entity.transform.position.y,
|
|
||||||
db_entity.transform.position.z,
|
// overwrite both components
|
||||||
);
|
*transform = new_tf;
|
||||||
|
*global = GlobalTransform::from(new_tf);
|
||||||
|
|
||||||
|
// keep your DTO in sync
|
||||||
|
dto.transform = db_entity.transform.clone();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Not found in ECS, so spawn a new entity
|
// Not found in ECS, so spawn a new entity
|
||||||
@ -92,46 +81,25 @@ pub fn sync_entities_system(
|
|||||||
EntityType::Custom => todo!(),
|
EntityType::Custom => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let new_tf = Transform::from(db_entity.transform.clone());
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
db_transfrom_to_transfrom(db_entity.transform.clone()),
|
TransformBundle::from_transform(new_tf), // inserts BOTH Transform and GlobalTransform
|
||||||
GlobalTransform::default(),
|
|
||||||
entity_type,
|
entity_type,
|
||||||
MeshMaterial3d(debug_material),
|
MeshMaterial3d(debug_material),
|
||||||
EntityDto {
|
EntityDto::from(db_entity.clone()),
|
||||||
entity_id: db_entity.entity_id,
|
|
||||||
transform: db_entity.transform.clone(),
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 3) Despawn any ECS entity that doesn't exist in the DB anymore ---
|
// --- 3) Despawn any ECS entity that doesn't exist in the DB anymore ---
|
||||||
for (entity, _, dto) in query.iter_mut() {
|
for (entity,_, _, dto) in query.iter_mut() {
|
||||||
if !db_ids.contains(&dto.entity_id) {
|
if !db_ids.contains(&dto.entity_id) {
|
||||||
// This ECS entity no longer matches anything in the DB => remove it
|
// This ECS entity no longer matches anything in the DB => remove it
|
||||||
commands.entity(entity).despawn_recursive();
|
commands.entity(entity).despawn_recursive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn db_transfrom_to_transfrom(db_transform: DbTransform) -> Transform{
|
|
||||||
Transform::from_xyz(
|
|
||||||
db_transform.position.x,
|
|
||||||
db_transform.position.y,
|
|
||||||
db_transform.position.z,
|
|
||||||
).with_rotation(
|
|
||||||
Quat::from_xyzw(
|
|
||||||
db_transform.rotation.x,
|
|
||||||
db_transform.rotation.y,
|
|
||||||
db_transform.rotation.z,
|
|
||||||
db_transform.rotation.w
|
|
||||||
)
|
|
||||||
).with_scale(
|
|
||||||
Vec3::new(
|
|
||||||
db_transform.scale.x,
|
|
||||||
db_transform.scale.y,
|
|
||||||
db_transform.scale.z,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::plugins::camera::systems::camera_system::CameraController;
|
use crate::plugins::environment::systems::camera_system::CameraController;
|
||||||
use bevy::asset::AssetServer;
|
use bevy::asset::AssetServer;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user