M crates/unified/assets/config/parts/chassis.part.toml => crates/unified/assets/config/parts/chassis.part.toml +19 -3
@@ 8,7 8,23 @@ width = 50
height = 50
mass = 100
-# North
[[joints]]
-translation = [ 0.0, 50.0, 0.0 ]
-rotation = 0.0>
\ No newline at end of file
+id = "Top"
+target = { translation = [ 0.0, 50.0, 0.0 ], rotation = 0.0 }
+snap = { translation = [ 0.0, 25.0, 0.0 ], rotation = 0.0 }
+
+
+[[joints]]
+id = "Right"
+target = { translation = [ 50.0, 0.0, 0.0 ], rotation = 90.0 }
+snap = { translation = [ 25.0, 0.0, 0.0 ], rotation = 90.0 }
+
+[[joints]]
+id = "Bottom"
+target = { translation = [ 0.0, -50.0, 0.0 ], rotation = 180.0 }
+snap = { translation = [ 0.0, -25.0, 0.0 ], rotation = 180.0 }
+
+[[joints]]
+id = "Left"
+target = { translation = [ -50.0, 0.0, 0.0 ], rotation = 270.0 }
+snap = { translation = [ -25.0, 0.0, 0.0 ], rotation = 270.0 }<
\ No newline at end of file
M crates/unified/assets/config/parts/hearty.part.toml => crates/unified/assets/config/parts/hearty.part.toml +19 -3
@@ 8,7 8,23 @@ width = 50
height = 50
mass = 100
-# North
[[joints]]
-translation = [ 0.0, 50.0, 0.0 ]
-rotation = 0.0>
\ No newline at end of file
+id = "Top"
+target = { translation = [ 0.0, 50.0, 0.0 ], rotation = 0.0 }
+snap = { translation = [ 0.0, 25.0, 0.0 ], rotation = 0.0 }
+
+
+[[joints]]
+id = "Right"
+target = { translation = [ 50.0, 0.0, 0.0 ], rotation = 90.0 }
+snap = { translation = [ 25.0, 0.0, 0.0 ], rotation = 90.0 }
+
+[[joints]]
+id = "Bottom"
+target = { translation = [ 0.0, -50.0, 0.0 ], rotation = 180.0 }
+snap = { translation = [ 0.0, -25.0, 0.0 ], rotation = 180.0 }
+
+[[joints]]
+id = "Left"
+target = { translation = [ -50.0, 0.0, 0.0 ], rotation = 270.0 }
+snap = { translation = [ -25.0, 0.0, 0.0 ], rotation = 270.0 }<
\ No newline at end of file
M crates/unified/src/attachment.rs => crates/unified/src/attachment.rs +32 -3
@@ 1,3 1,6 @@
+use std::ops::Deref;
+use bevy::asset::processor::ErasedProcessor;
+use bevy::ecs::entity::MapEntities;
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
@@ 7,15 10,41 @@ pub struct Ship;
#[derive(Component, Serialize, Deserialize)]
#[relationship_target(relationship = PartInShip, linked_spawn)]
-pub struct Parts(Vec<Entity>);
+pub struct Parts(#[entities] Vec<Entity>);
#[derive(Component, Serialize, Deserialize)]
#[relationship(relationship_target = Parts)]
-pub struct PartInShip(Entity);
+pub struct PartInShip(#[entities] Entity);
+
#[derive(Component, Serialize, Deserialize)]
pub struct Joint {
+ pub id: JointId,
pub transform: Transform
}
#[derive(Component, Serialize, Deserialize)]
-pub struct Peer(Entity);>
\ No newline at end of file
+pub struct Peer(#[entities] Entity);
+
+#[derive(Component, Serialize, Deserialize)]
+#[relationship(relationship_target = Joints)]
+pub struct JointOf(#[entities] pub Entity);
+#[derive(Component, Serialize, Deserialize)]
+#[relationship_target(relationship = JointOf)]
+pub struct Joints(#[entities] Vec<Entity>);
+#[derive(Component, Serialize, Deserialize)]
+#[relationship(relationship_target = JointSnaps)]
+pub struct JointSnapOf(#[entities] pub Entity);
+#[derive(Component, Serialize, Deserialize)]
+#[relationship_target(relationship = JointSnapOf)]
+pub struct JointSnaps(#[entities] Vec<Entity>);
+
+#[derive(Serialize, Deserialize)]
+pub struct JointId(pub String);
+impl JointId {
+ pub fn from_part_and_joint_id(part: String, joint: String) -> Self {
+ Self(format!("{part}:{joint}"))
+ }
+}
+
+#[derive(Serialize, Deserialize, Component)]
+pub struct JointSnapFor(#[entities] pub Entity);<
\ No newline at end of file
M crates/unified/src/client/key_input.rs => crates/unified/src/client/key_input.rs +36 -6
@@ 3,28 3,40 @@ use bevy::{
ecs::{event::EventWriter, system::Res},
input::{ButtonInput, keyboard::KeyCode},
};
+use bevy::color::palettes::css::{FUCHSIA, GREEN};
use bevy::dev_tools::picking_debug::DebugPickingMode;
-use bevy::log::info;
-use bevy::prelude::ResMut;
+use bevy::gizmos::AppGizmoBuilder;
+use bevy::log::{debug, info};
+use bevy::math::Vec3Swizzles;
+use bevy::prelude::{ChildOf, GizmoConfigGroup, Gizmos, GlobalTransform, IntoScheduleConfigs, Query, Reflect, ResMut, Resource, Transform, With};
use bevy_rapier2d::render::DebugRenderContext;
-use crate::ecs::ThrustEvent;
+use crate::attachment::{Joint, JointSnapFor};
+use crate::ecs::{Part, ThrustEvent};
pub fn key_input_plugin(app: &mut App) {
app.add_systems(Update, directional_keys)
- .add_systems(Update, debug_render_keybind);
+ .add_systems(Update, debug_render_keybind)
+ .init_resource::<AttachmentDebugRes>()
+ .add_systems(Update, draw_attachment_debug);
}
+#[derive(Resource, Default)]
+struct AttachmentDebugRes(bool);
+
fn debug_render_keybind(
keys: Res<ButtonInput<KeyCode>>,
mut debug_render: ResMut<DebugRenderContext>,
- mut picking_debug_mode: ResMut<DebugPickingMode>
+ mut picking_debug_mode: ResMut<DebugPickingMode>,
+ mut attachment_debug: ResMut<AttachmentDebugRes>,
) {
if keys.just_pressed(KeyCode::F3) {
debug_render.enabled = !debug_render.enabled;
}
if keys.just_pressed(KeyCode::F4) {
*picking_debug_mode = DebugPickingMode::Noisy;
- info!("{:?}", picking_debug_mode);
+ }
+ if keys.just_pressed(KeyCode::F5) {
+ attachment_debug.0 = !attachment_debug.0;
}
}
@@ 57,3 69,21 @@ fn directional_keys(
thrust_event.write(ThrustEvent::Right(false));
}
}
+
+fn draw_attachment_debug(joints: Query<&GlobalTransform, With<Joint>>, snaps: Query<&GlobalTransform, With<JointSnapFor>>, mut gizmos: Gizmos, mut state: ResMut<AttachmentDebugRes>) {
+ if !state.0 { return; }
+ for joint_target in joints.iter() {
+ gizmos.cross_2d(
+ joint_target.translation().xy(),
+ 4.0,
+ FUCHSIA
+ );
+ }
+ for joint_snap in snaps.iter() {
+ gizmos.cross_2d(
+ joint_snap.translation().xy(),
+ 4.0,
+ GREEN
+ );
+ }
+}<
\ No newline at end of file
M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +0 -1
@@ 70,7 70,6 @@ fn find_me(
for (entity, player, part) in q_clients.iter() {
let this_id_clientside = entity_map.to_client().get(&player.client).unwrap();
if *this_id_clientside == entity {
- info!("hi! i've been found!");
commands.entity(entity).insert(Me);
let mut heart_sprite = Sprite::from_image(asset_server.load("sprites/heart_sprite.png"));
heart_sprite.custom_size = Some(Vec2::new(part.width, part.height));
M crates/unified/src/client/parts.rs => crates/unified/src/client/parts.rs +3 -7
@@ 18,7 18,7 @@ fn handle_incoming_parts(
asset_server: Res<AssetServer>,
) {
for (new_entity, new_part) in new_parts.iter() {
- info!(?new_entity, ?new_part, "new part");
+ trace!(?new_entity, ?new_part, "new part");
let mut sprite = Sprite::from_image(asset_server.load(&new_part.sprite));
sprite.custom_size = Some(Vec2::new(new_part.width, new_part.height));
@@ 35,7 35,7 @@ fn handle_incoming_parts(
.insert(Pickable::default())
.observe(on_part_click);
- info!(?new_part, ?new_entity, "prepared new part");
+ trace!(?new_part, ?new_entity, "prepared new part");
}
}
fn handle_updated_parts(
@@ 57,7 57,7 @@ fn handle_updated_parts(
mass: updated_part.mass,
principal_inertia: 7.5,
}));
- info!(?updated_part, ?updated_entity, "updated part");
+ trace!(?updated_part, ?updated_entity, "updated part");
}
}
@@ 72,8 72,6 @@ fn on_part_click(ev: Trigger<Pointer<Pressed>>, sprites: Query<&Sprite, Without<
drag.0 = Some(ev.target());
events.write(PartDragControlEvent::Start(ev.target()));
-
- info!(?sprite, ?ev, "start drag");
}
fn on_part_release(ev: Trigger<Pointer<Released>>, mut drag: ResMut<DragResource>, mut events: EventWriter<PartDragControlEvent>) {
if ev.button != PointerButton::Primary { return; };
@@ 83,8 81,6 @@ fn on_part_release(ev: Trigger<Pointer<Released>>, mut drag: ResMut<DragResource
}
drag.0 = None;
-
- info!(?ev, "stop drag");
}
fn send_drag(drag: ResMut<DragResource>, coords: Res<CursorWorldCoordinates>, mut events: EventWriter<PartDragEvent>) {
let Some(dragging) = drag.0 else { return; };
M crates/unified/src/client/planet/incoming_planets.rs => crates/unified/src/client/planet/incoming_planets.rs +2 -2
@@ 27,7 27,7 @@ fn handle_incoming_planets(
commands.insert(AdditionalMassProperties::Mass(new_planet.mass))
.insert(sprite);
- info!(?new_planet, "prepared new planet");
+ trace!(?new_planet, "prepared new planet");
}
}
fn handle_updated_planets(
@@ 56,6 56,6 @@ fn handle_updated_planets(
- info!(?updated_planet, "updated planet");
+ trace!(?updated_planet, "updated planet");
}
}
M crates/unified/src/config/part.rs => crates/unified/src/config/part.rs +22 -7
@@ 1,6 1,6 @@
use bevy::asset::Asset;
-use bevy::math::Vec3;
-use bevy::prelude::TypePath;
+use bevy::math::{Quat, Vec3};
+use bevy::prelude::{Component, Transform, TypePath};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq, Asset)]
@@ 9,20 9,35 @@ pub struct PartConfig {
pub physics: PartPhysicsConfig,
pub joints: Vec<JointConfig>
}
-#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq, Asset)]
+#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)]
pub struct PartPartConfig {
pub name: String,
pub sprite_connected: String,
pub sprite_disconnected: String,
}
-#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq, Asset)]
+#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)]
pub struct PartPhysicsConfig {
pub width: f32,
pub height: f32,
pub mass: f32
}
-#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq, Asset)]
+#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)]
pub struct JointConfig {
+ pub id: String,
+ pub target: JointOffset,
+ pub snap: JointOffset,
+}
+#[derive(Deserialize, Serialize, Clone, Debug, TypePath, PartialEq, Copy)]
+pub struct JointOffset {
pub translation: Vec3,
- pub rotation: f32
-}>
\ No newline at end of file
+ pub rotation: f32,
+}
+impl From<JointOffset> for Transform {
+ fn from(value: JointOffset) -> Self {
+ Transform {
+ translation: value.translation,
+ rotation: Quat::from_rotation_z(value.rotation),
+ ..Default::default()
+ }
+ }
+ }<
\ No newline at end of file
M crates/unified/src/server/gravity.rs => crates/unified/src/server/gravity.rs +0 -2
@@ 23,8 23,6 @@ fn update_gravity(
let part_mass = part_mass.mass;
let part_translation = part_transform.translation;
- debug!(?part_transform, "part transform");
-
for (planet_transform, planet_mass) in &planet_query {
let planet_mass = planet_mass.mass;
let planet_translation = planet_transform.translation;
M crates/unified/src/server/part.rs => crates/unified/src/server/part.rs +54 -13
@@ 2,7 2,8 @@ use bevy::asset::Handle;
use bevy::prelude::*;
use bevy_rapier2d::prelude::{AdditionalMassProperties, Collider};
use bevy_replicon::prelude::Replicated;
-use crate::config::part::PartConfig;
+use crate::attachment::{Joint, JointId, JointOf, JointSnapFor, JointSnaps, Joints};
+use crate::config::part::{JointOffset, PartConfig};
use crate::ecs::Part;
pub fn part_config_plugin(app: &mut App) {
@@ 21,9 22,9 @@ struct PartType(AssetId<PartConfig>);
struct LiveConfigHandle(Handle<PartConfig>);
// watch for new SpawnPart components and start loading their config files
-fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), Added<SpawnPart>>, mut commands: Commands, asset_server: Res<AssetServer>, assets: Res<Assets<PartConfig>>) {
+fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), Added<SpawnPart>>, mut commands: Commands, asset_server: Res<AssetServer>, assets: Res<Assets<PartConfig>>, parts: Query<(&Joints, &JointSnaps), With<Part>>,) {
for (new_part, request) in &new_parts {
- info!(?new_part, ?request, "answering part request");
+ trace!(?new_part, ?request, "answering part request");
let hdl: Handle<PartConfig> = asset_server.load(request.0.clone());
@@ 32,7 33,7 @@ fn handle_spawn_part_requests(new_parts: Query<(Entity, &SpawnPart), Added<Spawn
.insert(LiveConfigHandle(hdl.clone()));
if let Some(cfg) = assets.get(&hdl) {
- spawn_part(commands.reborrow(), new_part, cfg, &hdl.id(), hdl.clone());
+ spawn_part(commands.reborrow(), new_part, cfg, &hdl.id(), parts, false);
} else {
commands.entity(new_part)
.insert(LoadingPart(hdl.clone()));
@@ 44,29 45,27 @@ fn update_part_requests(
loading_parts: Query<(Entity, &LoadingPart)>,
existing_parts: Query<(Entity, &PartType)>,
mut assets: ResMut<Assets<PartConfig>>,
- mut commands: Commands
+ mut commands: Commands,
+ parts: Query<(&Joints, &JointSnaps), With<Part>>,
) {
for ev in ev_config.read() {
match ev {
AssetEvent::Added { id } => {
- info!(?id, "asset added");
+ trace!(?id, "asset added");
for (loading_part, req) in &loading_parts {
if req.0.id() == *id {
- let strong_handle = assets.get_strong_handle(*id).unwrap();
let Some(asset) = assets.get(*id) else { continue; };
- spawn_part(commands.reborrow(), loading_part, asset, id, strong_handle);
+ spawn_part(commands.reborrow(), loading_part, asset, id, parts, false);
}
}
},
AssetEvent::Modified { id } => {
- info!(?id, "updating part");
+ trace!(?id, "updating part");
for (existing_part, ptype) in &existing_parts {
if ptype.0 == *id {
- let strong_handle = assets.get_strong_handle(*id).unwrap();
let Some(asset) = assets.get(ptype.0) else { continue; };
-
- spawn_part(commands.reborrow(), existing_part, asset, id, strong_handle);
+ spawn_part(commands.reborrow(), existing_part, asset, id, parts, true);
}
}
}
@@ 75,7 74,7 @@ fn update_part_requests(
}
}
-fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &AssetId<PartConfig>, strong_handle: Handle<PartConfig>) {
+fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &AssetId<PartConfig>, parts: Query<(&Joints, &JointSnaps), With<Part>>, is_update: bool) {
commands.entity(entity)
.remove::<LoadingPart>()
.insert(Part {
@@ 88,4 87,46 @@ fn spawn_part(mut commands: Commands, entity: Entity, part: &PartConfig, id: &As
.insert(AdditionalMassProperties::Mass(part.physics.mass))
.insert(PartType(*id))
.insert(Replicated);
+
+ for joint in &part.joints {
+ if is_update {
+ // find all entities
+ for (joints, snaps) in &parts {
+ for joint_entity in joints.iter() {
+ commands.entity(joint_entity).insert((
+ ChildOf(entity),
+ Joint {
+ id: JointId::from_part_and_joint_id(part.part.name.clone(), joint.id.clone()),
+ transform: joint.target.into()
+ },
+ <JointOffset as Into<Transform>>::into(joint.target),
+ JointOf(entity),
+ Replicated,
+ ));
+ }
+ for snap_entity in snaps.iter() {
+ commands.entity(snap_entity).insert((
+ <JointOffset as Into<Transform>>::into(joint.snap),
+ ));
+ }
+ }
+ } else {
+ let e = commands.spawn((
+ ChildOf(entity),
+ Joint {
+ id: JointId::from_part_and_joint_id(part.part.name.clone(), joint.id.clone()),
+ transform: joint.target.into()
+ },
+ <JointOffset as Into<Transform>>::into(joint.target),
+ JointOf(entity),
+ Replicated,
+ )).id();
+ commands.spawn((
+ ChildOf(entity),
+ JointSnapFor(e),
+ <JointOffset as Into<Transform>>::into(joint.snap),
+ Replicated,
+ ));
+ }
+ }
}=
\ No newline at end of file
M crates/unified/src/server/part_dragging.rs => crates/unified/src/server/part_dragging.rs +2 -4
@@ 29,12 29,10 @@ fn handle_start_stop_drag(mut colliders: Query<&Collider, With<Part>>, mut event
match &event.event {
PartDragControlEvent::Start(_) => {
commands.entity(entity)
- .insert(BeingDragged)
- .insert(ColliderDisabled);
+ .insert(BeingDragged);
},
PartDragControlEvent::Stop(_) => {
- commands.entity(entity).remove::<BeingDragged>()
- .remove::<ColliderDisabled>();
+ commands.entity(entity).remove::<BeingDragged>();
}
}
}
M crates/unified/src/server/planets.rs => crates/unified/src/server/planets.rs +5 -5
@@ 42,7 42,7 @@ pub fn update_planets(
match ev {
AssetEvent::Added { id } => {
if *id == waiting_for_asset_id {
- info!("planet config loaded - creating planets");
+ debug!("planet config loaded - creating planets");
let planet_config = assets.get(*id).unwrap();
for planet in &planet_config.planets {
commands
@@ 59,13 59,13 @@ pub fn update_planets(
),
})
.insert(Replicated);
- info!(?planet, "new planet spawned");
+ trace!(?planet, "new planet spawned");
}
}
}
AssetEvent::Modified { id } => {
if *id == waiting_for_asset_id {
- info!("planet config modified - reloading planets");
+ trace!("planet config modified - reloading planets");
let planet_config = assets.get(*id).unwrap();
for planet in &planet_config.planets {
@@ 87,7 87,7 @@ pub fn update_planets(
planet.default_transform[2],
);
*e_mass = AdditionalMassProperties::Mass(planet.mass);
- info!(?planet, "planet hot-reloaded");
+ trace!(?planet, "planet hot-reloaded");
} else {
commands
.spawn(PlanetBundle {
@@ 103,7 103,7 @@ pub fn update_planets(
),
})
.insert(Replicated);
- info!(?planet, "new planet spawned");
+ trace!(?planet, "new planet spawned");
}
}
}
M crates/unified/src/server/player.rs => crates/unified/src/server/player.rs +1 -87
@@ 35,7 35,7 @@ fn handle_new_players(
return;
};
for joined_player in &q_new_clients {
- info!(?joined_player, "detected joined player!");
+ trace!(?joined_player, "detected joined player!");
// find earth
let (spawn_planet_pos, spawn_planet) = planets
.iter()
@@ 57,92 57,6 @@ fn handle_new_players(
.insert(Player {
client: joined_player
});
-
- /*
- commands
- .entity(joined_player)
- .insert(PartBundle {
- part: Part {
- sprite: "textures/hearty.png".to_string(),
- width: wc.part.default_width,
- height: wc.part.default_height,
- mass: wc.part.default_mass,
- },
- transform: new_transform,
- collider: Collider::cuboid(
- wc.part.default_width / 2.0,
- wc.part.default_height / 2.0,
- ),
- additional_mass_properties: AdditionalMassProperties::MassProperties(
- MassProperties {
- local_center_of_mass: Vec2::ZERO,
- mass: wc.part.default_mass,
- principal_inertia: 7.5,
- },
- ),
- })
- .insert(Replicated)
- .insert(ExternalForce::default())
- .insert(PlayerThrust::default())
- .insert(Player {
- client: joined_player,
- })
- .insert(children![
- // bottom left
- (
- Particles {
- effect: "particles/ship_thruster.particle.ron".to_string(),
- active: false
- },
- Transform::from_xyz(
- -wc.part.default_width / 2.0 + 5.0,
- -wc.part.default_height / 2.0,
- 0.0
- )
- .with_rotation(Quat::from_rotation_z(180.0f32.to_radians())),
- Replicated
- ),
- // bottom right
- (
- Particles {
- effect: "particles/ship_thruster.particle.ron".to_string(),
- active: false
- },
- Transform::from_xyz(
- wc.part.default_width / 2.0 - 5.0,
- -wc.part.default_height / 2.0,
- 0.0
- )
- .with_rotation(Quat::from_rotation_z(180.0f32.to_radians())),
- Replicated
- ),
- // top left
- (
- Particles {
- effect: "particles/ship_thruster.particle.ron".to_string(),
- active: false
- },
- Transform::from_xyz(
- -wc.part.default_width / 2.0 + 5.0,
- wc.part.default_height / 2.0,
- 0.0
- ),
- Replicated
- ),
- // top right
- (
- Particles {
- effect: "particles/ship_thruster.particle.ron".to_string(),
- active: false
- },
- Transform::from_xyz(
- wc.part.default_width / 2.0 - 5.0,
- wc.part.default_height / 2.0,
- 0.0
- ),
- Replicated
- ),
- ]);*/
}
}
M crates/unified/src/server_plugins.rs => crates/unified/src/server_plugins.rs +8 -1
@@ 2,7 2,7 @@ use crate::config::planet::PlanetConfigCollection;
use crate::config::world::{GlobalWorldConfig};
use aeronet_replicon::server::AeronetRepliconServerPlugin;
use aeronet_websocket::server::WebSocketServerPlugin;
-use bevy::app::{PluginGroup, PluginGroupBuilder, ScheduleRunnerPlugin, TaskPoolPlugin};
+use bevy::app::{App, PluginGroup, PluginGroupBuilder, ScheduleRunnerPlugin, Startup, TaskPoolPlugin};
use bevy::asset::AssetPlugin;
use bevy::diagnostic::FrameCountPlugin;
use bevy::time::TimePlugin;
@@ 10,6 10,9 @@ use bevy_common_assets::toml::TomlAssetPlugin;
use bevy_replicon::RepliconPlugins;
use std::net::SocketAddr;
use std::time::Duration;
+use bevy::math::Vec2;
+use bevy::prelude::Query;
+use bevy_rapier2d::plugin::{NoUserData, RapierConfiguration, RapierPhysicsPlugin};
use crate::config::part::PartConfig;
pub struct ServerPluginGroup {
@@ 29,14 32,18 @@ impl PluginGroup for ServerPluginGroup {
.add_group(RepliconPlugins)
.add(WebSocketServerPlugin)
.add(AeronetRepliconServerPlugin)
+
/* Assets */
.add(AssetPlugin::default())
.add(TomlAssetPlugin::<GlobalWorldConfig>::new(&["wc.toml"]))
.add(TomlAssetPlugin::<PlanetConfigCollection>::new(&["pc.toml"]))
.add(TomlAssetPlugin::<PartConfig>::new(&["part.toml"]))
+
.add(crate::server::ServerPlugin {
bind: self.bind,
max_clients: self.max_clients,
})
}
}
+
+
M crates/unified/src/shared_plugins.rs => crates/unified/src/shared_plugins.rs +6 -3
@@ 4,7 4,7 @@ use bevy::app::{App, PluginGroup, PluginGroupBuilder};
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
use bevy_replicon::prelude::{AppRuleExt, Channel, ClientEventAppExt};
-use crate::attachment::{Joint, PartInShip, Peer, Ship};
+use crate::attachment::{Joint, JointOf, JointSnapFor, PartInShip, Peer, Ship};
use crate::clientevent::{PartDragControlEvent, PartDragEvent};
pub struct SharedPluginGroup;
@@ 13,8 13,9 @@ impl PluginGroup for SharedPluginGroup {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
.add(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0))
- .add(register_everything)
.add(physics_setup_plugin)
+
+ .add(register_everything)
}
}
@@ 35,7 36,9 @@ pub fn register_everything(app: &mut App) {
.replicate::<Ship>()
.replicate::<PartInShip>()
.replicate::<Joint>()
- .replicate::<Peer>();
+ .replicate::<Peer>()
+ .replicate::<JointOf>()
+ .replicate::<JointSnapFor>();
}
fn physics_setup_plugin(app: &mut App) {