bevy-expedition-demo/src/layout/systems.rs
2ndbeam 79fe190b6b feat: Level loading from TOML asset
- Fixed detect_interactions system
- Added test for deserializing asset with plugin
2026-03-28 01:46:27 +03:00

92 lines
3 KiB
Rust

use bevy::{
ecs::query::QueryFilter,
prelude::*,
};
use bevy_rapier2d::prelude::*;
use crate::{
player::Player,
};
use super::*;
fn get_interactive_id<F: QueryFilter>(
tested_id: Entity,
interactive_query: Query<(), F>,
parent_query: Query<&ChildOf, With<Collider>>,
) -> Option<Entity> {
if interactive_query.get(tested_id).is_ok() {
return Some(tested_id);
}
let Ok(parent_id) = parent_query.get(tested_id) else {
return None;
};
match interactive_query.get(parent_id.0) {
Ok(_) => Some(parent_id.0),
Err(_) => None,
}
}
fn interact_collisions_inner<F: QueryFilter>(
first: Entity,
second: Entity,
interactive_query: Query<(), F>,
player_query: Query<(), With<Player>>,
parent_query: Query<&ChildOf, With<Collider>>,
) -> Option<Entity> {
let Some(interactive_id) = get_interactive_id(first, interactive_query, parent_query) else {
return None;
};
if player_query.get(second).is_err() {
return None;
}
Some(interactive_id)
}
pub fn detect_interact_collisions(
mut commands: Commands,
mut collision_events: MessageReader<CollisionEvent>,
player_query: Query<(), With<Player>>,
interactive_query1: Query<(), (With<InteractiveObject>, Without<MayInteract>)>,
interactive_query2: Query<(), (With<InteractiveObject>, With<MayInteract>)>,
parent_query: Query<&ChildOf, With<Collider>>,
) {
for collision_event in collision_events.read() {
match collision_event {
CollisionEvent::Started(first, second, _) => {
if let Some(interactive_id) = interact_collisions_inner(*first, *second, interactive_query1, player_query, parent_query) {
commands.entity(interactive_id).insert(MayInteract);
}
if let Some(interactive_id) = interact_collisions_inner(*second, *first, interactive_query1, player_query, parent_query) {
commands.entity(interactive_id).insert(MayInteract);
}
},
CollisionEvent::Stopped(first, second, _) => {
if let Some(interactive_id) = interact_collisions_inner(*first, *second, interactive_query2, player_query, parent_query) {
commands.entity(interactive_id).remove::<MayInteract>();
}
if let Some(interactive_id) = interact_collisions_inner(*second, *first, interactive_query2, player_query, parent_query) {
commands.entity(interactive_id).remove::<MayInteract>();
}
},
}
}
}
pub fn lock_door(
mut commands: Commands,
query: Query<&ChildOf, Added<lock::Padlock>>,
) {
for parent in query {
commands.entity(parent.0).insert(Locked);
}
}
pub fn setup_world(
mut commands: Commands,
asset_server: Res<AssetServer>,
) {
let level_handle = asset_server.load("levels/level.toml");
commands.insert_resource(LevelAssetHandle(level_handle));
}