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

Events rework #487

wants to merge 3 commits into from

Conversation

Bafbi
Copy link
Contributor

@Bafbi Bafbi commented Aug 21, 2023

Objective

link issue : #399

The event system of bevy_ecs is great but does not permit, to attach any state to an event.
This is probably because it's not very useful if you have control over the server and the client, but us, we have only real control over the server.
This is very important, for the server to be able to now if the packet/action of a client need to be reversed for the creation of gui's and so many other mechanics.

Solution

This is currently mostly a proof of concept

  • We have now a new Resource named States that hold state associated with an StateId
  • When sending a new event with a state, we will generate a new StateId to map this event to the state
  • We can send child event that will be associate with already existing state
  • We use the EventWithStateMutReader to iterate with a &mut of the associated state of an event
  • We use the EventWithStateReader to iterate with a & of the associated state of an event
  • We use the EventReader if we don't need the state at all (useful to send the child event)

I wanted that multiple type of events can have a share state cause I figure that some event will derive from one singular packet, so anyone on any of this events will be able to cancel it.

Playground

Code
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),
        );
    }
}


/// Resource that holds all states for all events.
#[derive(Resource)]
pub struct States {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bevy already has a type called States, a trait used for general game states.
I would recommend renaming this to EventStates, which is more obvious anyways.

@Bafbi Bafbi mentioned this pull request Sep 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants