mirror of
https://github.com/eliasstepanik/voxel-simulation.git
synced 2026-01-10 21:38:29 +00:00
Basic Synced Object Test
This commit is contained in:
parent
8f86a7997f
commit
86aa2c77be
@ -18,4 +18,5 @@ bevy_window = "0.15.0"
|
||||
egui_dock = "0.14.0"
|
||||
spacetimedb-sdk = "1.0"
|
||||
hex = "0.4"
|
||||
random_word = { version = "0.5.0", features = ["en"] }
|
||||
random_word = { version = "0.5.0", features = ["en"] }
|
||||
rand = "0.8.5"
|
||||
@ -28,7 +28,7 @@ impl Plugin for AppPlugin {
|
||||
app.add_plugins(crate::plugins::camera::camera_plugin::CameraPlugin);
|
||||
app.add_plugins(crate::plugins::ui::ui_plugin::UiPlugin);
|
||||
app.add_plugins(crate::plugins::environment::environment_plugin::EnvironmentPlugin);
|
||||
app.add_systems(Startup, setup_database);
|
||||
app.add_plugins(crate::plugins::network::network_plugin::NetworkPlugin);
|
||||
|
||||
|
||||
app.add_systems(Update, (debug_gizmos, toggle_ui_system));
|
||||
|
||||
@ -4,8 +4,9 @@ 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;
|
||||
use crate::module_bindings::{set_name, spawn_entity, DbVector3};
|
||||
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||
|
||||
#[derive(Component)]
|
||||
@ -47,6 +48,15 @@ pub fn setup(mut commands: Commands) {
|
||||
));
|
||||
}
|
||||
|
||||
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>,
|
||||
@ -98,9 +108,17 @@ pub fn camera_controller_system(
|
||||
|
||||
let word = random_word::get(Lang::En);
|
||||
|
||||
if keyboard_input.just_pressed(KeyCode::KeyQ) {
|
||||
if keyboard_input.just_pressed(KeyCode::Numpad1) {
|
||||
ctx.0.reducers.set_name(word.to_string()).unwrap();
|
||||
}
|
||||
if keyboard_input.just_pressed(KeyCode::Numpad2) {
|
||||
let rand_position = random_vec3(-10.0,10.0);
|
||||
ctx.0.reducers.spawn_entity(DbVector3{
|
||||
x: rand_position.x,
|
||||
y: rand_position.y,
|
||||
z: rand_position.z,
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 3) Handle Keyboard Movement (WASD, Space, Shift)
|
||||
|
||||
@ -7,7 +7,6 @@ pub struct EnvironmentPlugin;
|
||||
impl Plugin for EnvironmentPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, init);
|
||||
app.add_systems(FixedUpdate, fixed_update);
|
||||
app.add_systems(Update, fixed_update);
|
||||
app.add_systems(Update, sync_entities_system);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,93 @@
|
||||
|
||||
use bevy::prelude::*;
|
||||
use spacetimedb_sdk::Table;
|
||||
use crate::module_bindings::{entity_table, DbVector3, EntityTableAccess};
|
||||
use crate::plugins::network::systems::database::DbConnectionResource;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct EntityDto {
|
||||
|
||||
|
||||
pub fn init(mut commands: Commands) {
|
||||
pub entity_id: u32,
|
||||
pub position: DbVector3,
|
||||
}
|
||||
|
||||
pub fn fixed_update(time: Res<Time>,) {
|
||||
pub fn init(mut commands: Commands,
|
||||
ctx: Res<DbConnectionResource>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
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 ()),
|
||||
Transform::from_xyz(
|
||||
entity.position.x,
|
||||
entity.position.y,
|
||||
entity.position.z,
|
||||
),
|
||||
EntityDto{
|
||||
entity_id: entity.entity_id,
|
||||
position: entity.position,
|
||||
}
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn sync_entities_system(
|
||||
mut commands: Commands,
|
||||
db_resource: Res<DbConnectionResource>,
|
||||
mut query: Query<(Entity, &mut Transform, &mut EntityDto)>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
let ctx = &db_resource.0.db;
|
||||
|
||||
// For each entity record in DB, see if it exists in ECS:
|
||||
for db_entity in ctx.entity().iter() {
|
||||
// Try to find a matching entity in ECS by comparing `entity_id`
|
||||
if let Some((entity, mut transform, mut dto)) = query
|
||||
.iter_mut()
|
||||
.find(|(_, _, dto)| dto.entity_id == db_entity.entity_id)
|
||||
{
|
||||
// It already exists. Perhaps update ECS data to match DB:
|
||||
dto.position = db_entity.position;
|
||||
transform.translation = Vec3::new(
|
||||
dto.position.x,
|
||||
dto.position.y,
|
||||
dto.position.z,
|
||||
);
|
||||
// ...do any other sync logic
|
||||
} else {
|
||||
|
||||
|
||||
let debug_material = materials.add(StandardMaterial { ..default() });
|
||||
// Not found in ECS, so spawn a new entity
|
||||
commands.spawn((
|
||||
EntityDto {
|
||||
entity_id: db_entity.entity_id,
|
||||
position: db_entity.position.clone(),
|
||||
},
|
||||
// Create an initial transform using DB data
|
||||
Transform::from_xyz(
|
||||
db_entity.position.x,
|
||||
db_entity.position.y,
|
||||
db_entity.position.z,
|
||||
),
|
||||
GlobalTransform::default(),
|
||||
Mesh3d(meshes.add(Cuboid::default()),),
|
||||
MeshMaterial3d(debug_material.clone ()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(time: Res<Time>,) {
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
pub(crate) mod systems;
|
||||
mod network_plugin;
|
||||
pub mod network_plugin;
|
||||
@ -8,6 +8,6 @@ use crate::plugins::network::systems::database::setup_database;
|
||||
pub struct NetworkPlugin;
|
||||
impl Plugin for NetworkPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Startup, setup_database);
|
||||
app.add_systems(PreStartup, setup_database);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
use bevy::prelude::{Commands, Resource};
|
||||
use bevy::ecs::system::SystemState;
|
||||
use bevy::prelude::{Commands, Resource, World};
|
||||
use bevy::utils::info;
|
||||
use spacetimedb_sdk::{credentials, DbContext, Error, Event, Identity, Status, Table, TableWithPrimaryKey};
|
||||
use crate::module_bindings::*;
|
||||
@ -23,6 +23,8 @@ pub fn setup_database(mut commands: Commands) {
|
||||
subscribe_to_tables(&ctx);
|
||||
ctx.run_threaded();
|
||||
commands.insert_resource(DbConnectionResource(ctx));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -57,5 +59,5 @@ fn subscribe_to_tables(ctx: &DbConnection) {
|
||||
ctx.subscription_builder()
|
||||
.on_applied(on_sub_applied)
|
||||
.on_error(on_sub_error)
|
||||
.subscribe(["SELECT * FROM player"]);
|
||||
.subscribe(["SELECT * FROM player", "SELECT * FROM entity"]);
|
||||
}
|
||||
@ -10,4 +10,4 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
spacetimedb = "1.0.1"
|
||||
log = "0.4"
|
||||
log = "0.4"
|
||||
@ -44,4 +44,13 @@ pub fn identity_disconnected(ctx: &ReducerContext) {
|
||||
// as it doesn't make sense for a client to disconnect without connecting first.
|
||||
log::warn!("Disconnect event for unknown Player with identity {:?}", ctx.sender);
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer(init)]
|
||||
pub fn init(ctx: &ReducerContext) -> Result<(), String> {
|
||||
log::info!("Initializing...");
|
||||
ctx.db.config().try_insert(Config {
|
||||
id: 0,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
27
server/src/types/entity.rs
Normal file
27
server/src/types/entity.rs
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
use spacetimedb::{Identity, ReducerContext, Table};
|
||||
use crate::types::vec3::{DbVector3};
|
||||
|
||||
#[spacetimedb::table(name = entity, public)]
|
||||
#[derive(Debug, Clone, )]
|
||||
pub struct Entity {
|
||||
#[auto_inc]
|
||||
#[primary_key]
|
||||
pub entity_id: u32,
|
||||
|
||||
|
||||
pub position: DbVector3,
|
||||
|
||||
}
|
||||
|
||||
#[spacetimedb::reducer]
|
||||
pub fn spawn_entity(ctx: &ReducerContext, position: DbVector3) -> Result<(), String> {
|
||||
|
||||
ctx.db.entity().try_insert(Entity {
|
||||
entity_id: 0,
|
||||
position,
|
||||
}).expect("TODO: panic message");
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod vec3;
|
||||
pub mod player;
|
||||
pub mod player;
|
||||
mod entity;
|
||||
@ -29,3 +29,4 @@ fn validate_name(name: String) -> Result<String, String> {
|
||||
Ok(name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,16 +5,4 @@ pub struct DbVector3 {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
#[spacetimedb::table(name = entity, public)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Entity {
|
||||
// The `auto_inc` attribute indicates to SpacetimeDB that
|
||||
// this value should be determined by SpacetimeDB on insert.
|
||||
#[auto_inc]
|
||||
#[primary_key]
|
||||
pub entity_id: u32,
|
||||
pub position: DbVector3,
|
||||
pub mass: u32,
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user