Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events rework #487

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ valence_advancement = { workspace = true, optional = true }
valence_anvil = { workspace = true, optional = true }
valence_boss_bar = { workspace = true, optional = true }
valence_server.workspace = true
valence_event.workspace = true
valence_inventory = { workspace = true, optional = true }
valence_network = { workspace = true, optional = true }
valence_player_list = { workspace = true, optional = true }
Expand Down Expand Up @@ -167,6 +168,7 @@ valence_advancement.path = "crates/valence_advancement"
valence_anvil.path = "crates/valence_anvil"
valence_build_utils.path = "crates/valence_build_utils"
valence_server.path = "crates/valence_server"
valence_event.path = "crates/valence_event"
valence_packet_macros.path = "crates/valence_packet_macros"
valence_server_core.path = "crates/valence_server_core"
valence_entity.path = "crates/valence_entity"
Expand Down
15 changes: 15 additions & 0 deletions crates/valence_event/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "valence_event"
version.workspace = true
edition.workspace = true

[dependencies]
valence_server_core.workspace = true
valence_protocol.workspace = true
valence_server.workspace = true
bevy_ecs.workspace = true
bevy_app.workspace = true
bitfield-struct.workspace = true
tracing.workspace = true


3 changes: 3 additions & 0 deletions crates/valence_event/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# valence_event

This crate provides a cancellable event system for Bevy, and implements all valence event types.
60 changes: 60 additions & 0 deletions crates/valence_event/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use bevy_app::{App, First, Plugin, PluginGroup, PluginGroupBuilder};
use bevy_ecs::prelude::Event;
use bevy_ecs::schedule::{IntoSystemSetConfigs, SystemSet};
use valence_server::EventLoopPreUpdate;

use self::inventory::InventoryEventPlugin;
use crate::state_event::{EventsWithState, State, States};

pub mod inventory;

#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
pub enum EventDispacherSets {
MainEvents,
Checks,
UserEvents,
}

pub struct EventDispacherPlugin;

impl Plugin for EventDispacherPlugin {
fn build(&self, app: &mut App) {
app.configure_sets(
EventLoopPreUpdate,
(
EventDispacherSets::MainEvents,
EventDispacherSets::Checks,
EventDispacherSets::UserEvents,
)
.chain(),
)

.init_resource::<States>();

}
}

pub struct EventPlugins;

impl PluginGroup for EventPlugins {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>().add(InventoryEventPlugin)
}
}

trait AddEventWithStateExt {
fn add_event_with_state<E: Event>(&mut self) -> &mut Self;
}

impl AddEventWithStateExt for App {
fn add_event_with_state<E: Event>(&mut self) -> &mut Self {
if !self.world.contains_resource::<EventsWithState<E>>() {
self.init_resource::<EventsWithState<E>>()
.add_systems(First, EventsWithState::<E>::update_system);
}
// if !self.world.contains_resource::<States>() {
// self.init_resource::<States>();
// }
self
}
}
79 changes: 79 additions & 0 deletions crates/valence_event/src/events/inventory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use bevy_ecs::prelude::{Entity, Event, EventReader};
use bevy_ecs::schedule::IntoSystemConfigs;
use valence_protocol::packets::play::click_slot_c2s::{ClickMode, SlotChange};
use valence_protocol::packets::play::ClickSlotC2s;
use valence_protocol::ItemStack;
use valence_server::event_loop::PacketEvent;

use self::click::{handle_inventory_click, InventoryClickEvent};
use super::*;
use crate::state_event::EventWithStateWriter;

pub mod click;

pub struct InventoryEventPlugin;

impl Plugin for InventoryEventPlugin {
fn build(&self, app: &mut App) {
app.add_event_with_state::<ClickSlotEvent>()
.add_event_with_state::<InventoryClickEvent>()
.add_systems(
EventLoopPreUpdate,
handle_click_slot.in_set(EventDispacherSets::MainEvents),
)
.add_systems(
EventLoopPreUpdate,
handle_inventory_click.in_set(EventDispacherSets::UserEvents),
);
}
}

#[derive(Clone, Debug)]
struct Canceled(bool);

impl State for Canceled {
fn get(&self) -> bool {
self.0
}

fn set(&mut self, value: bool) {
self.0 = value;
}
}

#[derive(Clone, Debug, Event)]
pub struct ClickSlotEvent {
pub client: Entity,
pub window_id: u8,
pub state_id: i32,
pub slot_idx: i16,
pub button: i8,
pub mode: ClickMode,
pub slot_changes: Vec<SlotChange>,
pub carried_item: Option<ItemStack>,
}

fn handle_click_slot(
mut packet_events: EventReader<PacketEvent>,
mut click_slot_events: EventWithStateWriter<ClickSlotEvent>,
) {
for packet in packet_events.iter() {
let Some(pkt) = packet.decode::<ClickSlotC2s>() else {
continue;
};

click_slot_events.send(
ClickSlotEvent {
client: packet.client,
window_id: pkt.window_id,
state_id: pkt.state_id.0,
slot_idx: pkt.slot_idx,
button: pkt.button,
mode: pkt.mode,
slot_changes: pkt.slot_changes,
carried_item: pkt.carried_item,
},
Canceled(false),
);
}
}
64 changes: 64 additions & 0 deletions crates/valence_event/src/events/inventory/click.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::state_event::{EventWithStateReader, EventReader};

use super::*;

#[derive(Debug, Event, Clone)]
pub struct InventoryClickEvent {
pub client: Entity,
pub window_id: u8,
pub state_id: i32,
pub slot_idx: i16,
pub click_type: ClickType,
pub clicked_item: Option<SlotChange>,
pub cursor_item: Option<ItemStack>,
}

#[derive(Debug, Clone)]
pub enum ClickType {
Left,
Right,
ShiftLeft,
ShiftRight,
DoubleLeft,
DoubleRight,
}

pub(super) fn handle_inventory_click(
mut click_slot_events: EventReader<ClickSlotEvent>,
mut inventory_click_events: EventWithStateWriter<InventoryClickEvent>,
) {
for (event, state_id, _) in click_slot_events.iter_with_ids() {
let click_type = match event.mode {
ClickMode::Click => match event.button {
0 => ClickType::Left,
1 => ClickType::Right,
_ => panic!("Invalid button for click mode"),
},
ClickMode::ShiftClick => match event.button {
0 => ClickType::ShiftLeft,
1 => ClickType::ShiftRight,
_ => panic!("Invalid button for shift click mode"),
},
ClickMode::DoubleClick => match event.button {
0 => ClickType::DoubleLeft,
1 => ClickType::DoubleRight,
_ => panic!("Invalid button for double click mode"),
},
_ => {
continue;
}
};

let inventory_click_event = InventoryClickEvent {
client: event.client,
window_id: event.window_id,
state_id: event.state_id,
slot_idx: event.slot_idx,
click_type,
clicked_item: event.slot_changes.get(0).cloned(),
cursor_item: event.carried_item.clone(),
};

inventory_click_events.send_with_state(inventory_click_event, state_id)
}
}
2 changes: 2 additions & 0 deletions crates/valence_event/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod events;
pub mod state_event;
Loading