Skip to content

Commit 4d756b3

Browse files
authored
Add events to quill API (#522)
* Add events to quill API * Split it into 3 host calls * format
1 parent eaffe46 commit 4d756b3

File tree

6 files changed

+119
-15
lines changed

6 files changed

+119
-15
lines changed

feather/plugin-host/src/host_calls.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod block;
1212
mod component;
1313
mod entity;
1414
mod entity_builder;
15+
mod event;
1516
mod plugin_message;
1617
mod query;
1718
mod system;
@@ -49,6 +50,7 @@ use block::*;
4950
use component::*;
5051
use entity::*;
5152
use entity_builder::*;
53+
use event::*;
5254
use plugin_message::*;
5355
use query::*;
5456
use system::*;
@@ -57,6 +59,8 @@ host_calls! {
5759
"register_system" => register_system,
5860
"entity_get_component" => entity_get_component,
5961
"entity_set_component" => entity_set_component,
62+
"entity_add_event" => entity_add_event,
63+
"add_event" => add_event,
6064
"entity_builder_new_empty" => entity_builder_new_empty,
6165
"entity_builder_new" => entity_builder_new,
6266
"entity_builder_add_component" => entity_builder_add_component,

feather/plugin-host/src/host_calls/component.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,36 @@ pub fn entity_get_component(
4343
Ok(())
4444
}
4545

46-
struct SetComponentVisitor<'a> {
47-
cx: &'a PluginContext,
48-
entity: Entity,
49-
bytes_ptr: PluginPtr<u8>,
50-
bytes_len: u32,
46+
pub(crate) struct InsertComponentVisitor<'a> {
47+
pub cx: &'a PluginContext,
48+
pub bytes_ptr: PluginPtr<u8>,
49+
pub bytes_len: u32,
50+
pub action: SetComponentAction,
51+
}
52+
53+
pub(crate) enum SetComponentAction {
54+
SetComponent(Entity),
55+
AddEntityEvent(Entity),
56+
AddEvent,
5157
}
5258

53-
impl<'a> ComponentVisitor<anyhow::Result<()>> for SetComponentVisitor<'a> {
59+
impl<'a> ComponentVisitor<anyhow::Result<()>> for InsertComponentVisitor<'a> {
5460
fn visit<T: quill_common::Component>(self) -> anyhow::Result<()> {
5561
let component = self
5662
.cx
5763
.read_component::<T>(self.bytes_ptr, self.bytes_len)?;
5864
let mut game = self.cx.game_mut();
5965

60-
let existing_component = game.ecs.get_mut::<T>(self.entity);
61-
if let Ok(mut existing_component) = existing_component {
62-
*existing_component = component;
63-
} else {
64-
drop(existing_component);
65-
let _ = game.ecs.insert(self.entity, component);
66+
match self.action {
67+
SetComponentAction::SetComponent(entity) => {
68+
let _ = game.ecs.insert(entity, component);
69+
}
70+
SetComponentAction::AddEntityEvent(entity) => {
71+
let _ = game.ecs.insert_entity_event(entity, component);
72+
}
73+
SetComponentAction::AddEvent => {
74+
game.ecs.insert_event(component);
75+
}
6676
}
6777

6878
Ok(())
@@ -79,11 +89,11 @@ pub fn entity_set_component(
7989
) -> anyhow::Result<()> {
8090
let entity = Entity::from_bits(entity);
8191
let component = HostComponent::from_u32(component).context("invalid component")?;
82-
let visitor = SetComponentVisitor {
92+
let visitor = InsertComponentVisitor {
8393
cx,
84-
entity,
8594
bytes_ptr,
8695
bytes_len,
96+
action: SetComponentAction::SetComponent(entity),
8797
};
8898
component.visit(visitor)
8999
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use crate::context::{PluginContext, PluginPtr};
2+
use crate::host_calls::component::{InsertComponentVisitor, SetComponentAction};
3+
use anyhow::Context;
4+
use feather_ecs::Entity;
5+
use feather_plugin_host_macros::host_function;
6+
use quill_common::HostComponent;
7+
8+
#[host_function]
9+
pub fn entity_add_event(
10+
cx: &PluginContext,
11+
entity: u64,
12+
event: u32,
13+
bytes_ptr: PluginPtr<u8>,
14+
bytes_len: u32,
15+
) -> anyhow::Result<()> {
16+
let entity = Entity::from_bits(entity);
17+
let event = HostComponent::from_u32(event).context("invalid component")?;
18+
let visitor = InsertComponentVisitor {
19+
cx,
20+
bytes_ptr,
21+
bytes_len,
22+
action: SetComponentAction::AddEntityEvent(entity),
23+
};
24+
event.visit(visitor)
25+
}
26+
27+
#[host_function]
28+
pub fn add_event(
29+
cx: &PluginContext,
30+
event: u32,
31+
bytes_ptr: PluginPtr<u8>,
32+
bytes_len: u32,
33+
) -> anyhow::Result<()> {
34+
let event = HostComponent::from_u32(event).context("invalid component")?;
35+
let visitor = InsertComponentVisitor {
36+
cx,
37+
bytes_ptr,
38+
bytes_len,
39+
action: SetComponentAction::AddEvent,
40+
};
41+
event.visit(visitor)
42+
}

quill/api/src/entity.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ impl Entity {
8989
}
9090
}
9191

92+
/// Inserts an event to the entity.
93+
///
94+
/// If the entity already has this event,
95+
/// the event is overwritten.
96+
pub fn insert_event<T: Component>(&self, event: T) {
97+
let host_component = T::host_component();
98+
let bytes = event.to_cow_bytes();
99+
100+
unsafe {
101+
quill_sys::entity_add_event(
102+
self.id.0,
103+
host_component,
104+
bytes.as_ptr().into(),
105+
bytes.len() as u32,
106+
);
107+
}
108+
}
109+
92110
/// Sends the given message to this entity.
93111
///
94112
/// The message sends as a "system" message.

quill/api/src/game.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use libcraft_blocks::BlockState;
44
use libcraft_core::{BlockPosition, ChunkPosition, Position, CHUNK_HEIGHT};
55
use libcraft_particles::Particle;
66
use quill_common::entity_init::EntityInit;
7+
use quill_common::Component;
78

89
use crate::{
910
query::{Query, QueryIter},
@@ -218,6 +219,16 @@ impl Game {
218219
)
219220
}
220221
}
222+
223+
/// Inserts an event to the world.
224+
pub fn insert_event<T: Component>(&self, event: T) {
225+
let host_component = T::host_component();
226+
let bytes = event.to_cow_bytes();
227+
228+
unsafe {
229+
quill_sys::add_event(host_component, bytes.as_ptr().into(), bytes.len() as u32);
230+
}
231+
}
221232
}
222233

223234
fn check_y_bound(pos: BlockPosition) -> Result<(), BlockAccessError> {

quill/sys/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ extern "C" {
7676
/// component.
7777
///
7878
/// This will overwrite any existing component of the same type.
79-
///
8079
/// Does nothing if `entity` does not exist.
8180
pub fn entity_set_component(
8281
entity: EntityId,
@@ -85,6 +84,26 @@ extern "C" {
8584
bytes_len: u32,
8685
);
8786

87+
/// Adds an event for an entity.
88+
///
89+
/// `bytes_ptr` is a pointer to the serialized
90+
/// event.
91+
///
92+
/// This will overwrite any existing event of the same type.
93+
/// Does nothing if `entity` does not exist.
94+
pub fn entity_add_event(
95+
entity: EntityId,
96+
event: HostComponent,
97+
bytes_ptr: Pointer<u8>,
98+
bytes_len: u32,
99+
);
100+
101+
/// Adds a global event.
102+
///
103+
/// `bytes_ptr` is a pointer to the serialized
104+
/// component.
105+
pub fn add_event(event: HostComponent, bytes_ptr: Pointer<u8>, bytes_len: u32);
106+
88107
/// Sends a message to an entity.
89108
///
90109
/// The given message should be in the JSON format.

0 commit comments

Comments
 (0)