Skip to content
Merged
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
10 changes: 5 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ let package = Package(
// Targets can depend on other targets in this package and products from dependencies.
.binaryTarget(
name: "RustXcframework",
//for local development:
//path: "RustXcframework.xcframework"),
url:
"https://github.com/rustunit/bevy_ios_iap/releases/download/rs-0.7.0/RustXcframework.xcframework.zip",
checksum: "ea7396a6950199a7a25d5d8f35d220c1e3b9052e9bb9c207785c1bd8addb85e9"),
// for local development:
path: "RustXcframework.xcframework"),
// url:
// "https://github.com/rustunit/bevy_ios_iap/releases/download/rs-0.7.0/RustXcframework.xcframework.zip",
// checksum: "ea7396a6950199a7a25d5d8f35d220c1e3b9052e9bb9c207785c1bd8addb85e9"),
.target(
name: "bevy_ios_iap",
dependencies: ["RustXcframework"]),
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ or

```toml
# always pin to the same exact version you also of the Swift package
bevy_ios_iap = { version = "=0.2.1" }
bevy_ios_iap = { version = "=0.8" }
```

### 3. Setup Plugin
Expand All @@ -87,7 +87,7 @@ fn bevy_system(mut iap: BevyIosIap) {

// request product details, product IDs have to be explicitly provided
iap.products(vec!["com.rustunit.zoolitaire.levelunlock".into()])
.on_response(|trigger: Trigger<Products>| match &trigger.event().0 {
.on_response(|trigger: On<Products>| match &trigger.event().0 {
IosIapProductsResponse::Done(products) => {
info!("products loaded: {}", products.len());

Expand All @@ -100,7 +100,7 @@ fn bevy_system(mut iap: BevyIosIap) {

// trigger a product purchase for a specific product ID
iap.purchase("com.rustunit.zoolitaire.levelunlock".into())
.on_response(|trigger: Trigger<Purchase>|{
.on_response(|trigger: On<Purchase>|{
match &trigger.event().0 {
IosIapPurchaseResponse::Success(t) => {
info!("just purchased: '{}' {}", t.product_id, t.id);
Expand All @@ -113,7 +113,7 @@ fn bevy_system(mut iap: BevyIosIap) {

// request to restore active subscriptions and non-consumables
iap.current_entitlements()
.on_response(|trigger: Trigger<CurrentEntitlements>|{
.on_response(|trigger: On<CurrentEntitlements>|{
info!("current entitlements: {}", trigger.event());
});
}
Expand Down Expand Up @@ -158,7 +158,8 @@ fn process_iap_events(

|bevy|crate|
|---|---|
|0.16|0.6,main|
|0.17|0.8,main|
|0.16|0.6,0.7|
|0.15|0.5|
|0.14|0.3,0.4|
|0.13|0.2|
Expand Down
12 changes: 6 additions & 6 deletions bevy_ios_iap/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bevy_ios_iap"
version = "0.7.0"
version = "0.8.0"
edition = "2024"
build = "build.rs"
readme = "../README.md"
Expand All @@ -15,11 +15,11 @@ description = "Bevy Plugin and Swift Package to provide access to iOS native Sto
crate-type = ["staticlib", "rlib"]

[dependencies]
bevy_app = { version = "0.16", default-features = false }
bevy_ecs = { version = "0.16", default-features = false }
bevy_ecs_macros = { version = "0.16", default-features = false }
bevy_log = { version = "0.16", default-features = false }
bevy_crossbeam_event = "0.8"
bevy_app = { version = "0.17", default-features = false }
bevy_ecs = { version = "0.17", default-features = false }
bevy_ecs_macros = { version = "0.17", default-features = false }
bevy_log = { version = "0.17", default-features = false }
bevy_channel_message = "0.1.1"
swift-bridge = "0.1"

[build-dependencies]
Expand Down
10 changes: 5 additions & 5 deletions bevy_ios_iap/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::sync::OnceLock;

use bevy_crossbeam_event::CrossbeamEventSender;
use bevy_channel_message::ChannelMessageSender;

#[allow(unused_imports)]
pub use ffi::*;
Expand Down Expand Up @@ -243,16 +243,16 @@ mod ffi {
}
}

static SENDER_EVENTS: OnceLock<Option<CrossbeamEventSender<IosIapEvents>>> = OnceLock::new();
static SENDER_RESPONSE: OnceLock<Option<CrossbeamEventSender<IosIapResponse>>> = OnceLock::new();
static SENDER_EVENTS: OnceLock<Option<ChannelMessageSender<IosIapEvents>>> = OnceLock::new();
static SENDER_RESPONSE: OnceLock<Option<ChannelMessageSender<IosIapResponse>>> = OnceLock::new();

#[allow(dead_code)]
pub fn set_sender_events(sender: CrossbeamEventSender<IosIapEvents>) {
pub fn set_sender_events(sender: ChannelMessageSender<IosIapEvents>) {
while SENDER_EVENTS.set(Some(sender.clone())).is_err() {}
}

#[allow(dead_code)]
pub fn set_sender_response(sender: CrossbeamEventSender<IosIapResponse>) {
pub fn set_sender_response(sender: ChannelMessageSender<IosIapResponse>) {
while SENDER_RESPONSE.set(Some(sender.clone())).is_err() {}
}

Expand Down
18 changes: 9 additions & 9 deletions bevy_ios_iap/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
};

/// All possible responses for communication from the native iOS (Swift) side to Rust/Bevy as a reaction to a method call / request.
#[derive(Event, Clone, Debug)]
#[derive(Message, Clone, Debug)]
pub enum IosIapResponse {
/// Triggered by calls to [`get_products`][crate::get_products]
Products((i64, IosIapProductsResponse)),
Expand All @@ -24,7 +24,7 @@ pub enum IosIapResponse {

/// Events for pro-active communication from native iOS (Swift) side to Rust/Bevy that are not a direct response to a request.
#[non_exhaustive]
#[derive(Event, Clone, Debug)]
#[derive(Message, Clone, Debug)]
pub enum IosIapEvents {
/// Triggered automatically by TransactionObserver registered by [`init`][crate::init]
/// for every update on any Transaction while the app is running.
Expand All @@ -50,29 +50,29 @@ impl Plugin for IosIapPlugin {

#[cfg(not(target_os = "ios"))]
{
app.add_event::<IosIapEvents>();
app.add_event::<IosIapResponse>();
app.add_message::<IosIapEvents>();
app.add_message::<IosIapResponse>();
}

#[cfg(target_os = "ios")]
{
use bevy_crossbeam_event::{CrossbeamEventApp, CrossbeamEventSender};
use bevy_channel_message::{ChannelMessageApp, ChannelMessageSender};

app.add_crossbeam_event::<IosIapEvents>();
app.add_channel_message::<IosIapEvents>();

let sender = app
.world()
.get_resource::<CrossbeamEventSender<IosIapEvents>>()
.get_resource::<ChannelMessageSender<IosIapEvents>>()
.unwrap()
.clone();

crate::native::set_sender_events(sender);

app.add_crossbeam_event::<IosIapResponse>();
app.add_channel_message::<IosIapResponse>();

let sender = app
.world()
.get_resource::<CrossbeamEventSender<IosIapResponse>>()
.get_resource::<ChannelMessageSender<IosIapResponse>>()
.unwrap()
.clone();

Expand Down
66 changes: 48 additions & 18 deletions bevy_ios_iap/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,35 @@ use crate::{
IosIapTransactionResponse, plugin::IosIapResponse,
};

#[derive(Event, Debug)]
pub struct CurrentEntitlements(pub IosIapTransactionResponse);
#[derive(EntityEvent, Debug)]
pub struct CurrentEntitlements {
pub entity: Entity,
pub response: IosIapTransactionResponse,
}

#[derive(Event, Debug)]
pub struct Products(pub IosIapProductsResponse);
#[derive(EntityEvent, Debug)]
pub struct Products {
pub entity: Entity,
pub response: IosIapProductsResponse,
}

#[derive(Event, Debug)]
pub struct Purchase(pub IosIapPurchaseResponse);
#[derive(EntityEvent, Debug)]
pub struct Purchase {
pub entity: Entity,
pub response: IosIapPurchaseResponse,
}

#[derive(Event, Debug)]
pub struct FinishTransaction(pub IosIapTransactionFinishResponse);
#[derive(EntityEvent, Debug)]
pub struct FinishTransaction {
pub entity: Entity,
pub response: IosIapTransactionFinishResponse,
}

#[derive(Event, Debug)]
pub struct AllTransactions(pub IosIapTransactionResponse);
#[derive(EntityEvent, Debug)]
pub struct AllTransactions {
pub entity: Entity,
pub response: IosIapTransactionResponse,
}

#[derive(Resource, Default)]
struct BevyIosIapSate {
Expand Down Expand Up @@ -127,7 +142,7 @@ pub struct BevyIosIapRequestBuilder<'a, T>(EntityCommands<'a>, PhantomData<T>);

impl<'a, T> BevyIosIapRequestBuilder<'a, T>
where
T: 'static + Event,
T: 'static + Event + bevy_ecs::event::EntityEvent,
{
fn new(ec: EntityCommands<'a>) -> Self {
Self(ec, PhantomData)
Expand All @@ -151,7 +166,7 @@ pub fn plugin(app: &mut App) {
PreUpdate,
(
cleanup_finished_requests,
process_events.run_if(on_event::<IosIapResponse>),
process_events.run_if(on_message::<IosIapResponse>),
)
.chain()
.in_set(BevyIosIapSet),
Expand All @@ -171,7 +186,7 @@ fn cleanup_finished_requests(

#[allow(unused_variables, unused_mut)]
fn process_events(
mut events: EventReader<IosIapResponse>,
mut events: MessageReader<IosIapResponse>,
mut commands: Commands,
query_current_entitlements: Query<(Entity, &RequestId), With<RequestCurrentEntitlements>>,
query_products: Query<(Entity, &RequestId), With<RequestProducts>>,
Expand All @@ -182,7 +197,10 @@ fn process_events(
IosIapResponse::CurrentEntitlements((r, response)) => {
for (e, id) in &query_current_entitlements {
if id.0 == *r {
commands.trigger_targets(CurrentEntitlements(response.clone()), e);
commands.trigger(CurrentEntitlements {
entity: e,
response: response.clone(),
});
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<RequestId>();
}
Expand All @@ -193,7 +211,10 @@ fn process_events(
IosIapResponse::Products((r, response)) => {
for (e, id) in &query_products {
if id.0 == *r {
commands.trigger_targets(Products(response.clone()), e);
commands.trigger(Products {
entity: e,
response: response.clone(),
});
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<RequestId>();
}
Expand All @@ -204,7 +225,10 @@ fn process_events(
IosIapResponse::Purchase((r, response)) => {
for (e, id) in &query_purchases {
if id.0 == *r {
commands.trigger_targets(Purchase(response.clone()), e);
commands.trigger(Purchase {
entity: e,
response: response.clone(),
});
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<RequestId>();
}
Expand All @@ -215,7 +239,10 @@ fn process_events(
IosIapResponse::TransactionFinished((r, response)) => {
for (e, id) in &query_purchases {
if id.0 == *r {
commands.trigger_targets(FinishTransaction(response.clone()), e);
commands.trigger(FinishTransaction {
entity: e,
response: response.clone(),
});
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<RequestId>();
}
Expand All @@ -226,7 +253,10 @@ fn process_events(
IosIapResponse::AllTransactions((r, response)) => {
for (e, id) in &query_purchases {
if id.0 == *r {
commands.trigger_targets(AllTransactions(response.clone()), e);
commands.trigger(AllTransactions {
entity: e,
response: response.clone(),
});
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<RequestId>();
}
Expand Down
8 changes: 4 additions & 4 deletions bevy_ios_iap_egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.2.0"
edition = "2021"

[dependencies]
bevy_ios_iap = "0.7"
bevy = { version = "0.16", default-features = false }
bevy_egui = { version = "0.34", default-features = false }
egui_extras = { version = "0.31" }
bevy_ios_iap = {path="../bevy_ios_iap"}
bevy = { version = "0.17", default-features = false }
bevy_egui = { version = "0.37", default-features = false }
egui_extras = { version = "0.32" }
19 changes: 10 additions & 9 deletions bevy_ios_iap_egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ pub struct IosIapEguiPlugin {
impl Plugin for IosIapEguiPlugin {
fn build(&self, app: &mut App) {
if !app.is_plugin_added::<EguiPlugin>() {
app.add_plugins(EguiPlugin {
enable_multipass_for_primary_context: false,
});
app.add_plugins(EguiPlugin::default());
}

app.init_resource::<DebugUiResource>();
Expand All @@ -49,23 +47,26 @@ impl Plugin for IosIapEguiPlugin {
app.add_systems(Update, update);
app.add_systems(
Update,
process_iap_responses.run_if(on_event::<IosIapResponse>),
process_iap_responses.run_if(on_message::<IosIapResponse>),
);
app.add_systems(
Update,
process_iap_events.run_if(on_message::<IosIapEvents>),
);
app.add_systems(Update, process_iap_events.run_if(on_event::<IosIapEvents>));

app.add_observer(on_toggle);
}
}

fn on_toggle(trigger: Trigger<IosIapEguiOpen>, mut res: ResMut<DebugUiResource>) {
fn on_toggle(trigger: On<IosIapEguiOpen>, mut res: ResMut<DebugUiResource>) {
match trigger.event() {
IosIapEguiOpen::Toggle => res.open = !res.open,
IosIapEguiOpen::Open => res.open = true,
IosIapEguiOpen::Close => res.open = false,
}
}

fn process_iap_responses(mut events: EventReader<IosIapResponse>, mut res: ResMut<DebugIosIap>) {
fn process_iap_responses(mut events: MessageReader<IosIapResponse>, mut res: ResMut<DebugIosIap>) {
for e in events.read() {
match e {
IosIapResponse::Products((_r, IosIapProductsResponse::Done(products))) => {
Expand Down Expand Up @@ -107,7 +108,7 @@ fn process_iap_responses(mut events: EventReader<IosIapResponse>, mut res: ResMu
}
}

fn process_iap_events(mut events: EventReader<IosIapEvents>, mut res: ResMut<DebugIosIap>) {
fn process_iap_events(mut events: MessageReader<IosIapEvents>, mut res: ResMut<DebugIosIap>) {
for e in events.read() {
match e {
IosIapEvents::TransactionUpdate(t) => {
Expand All @@ -125,7 +126,7 @@ fn update(
mut res_iap: ResMut<DebugIosIap>,
) {
let mut open_state = res.open;
let Some(ctx) = contexts.try_ctx_mut() else {
let Ok(ctx) = contexts.ctx_mut() else {
return;
};

Expand Down