1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//! Safe wrapper for the [Discord Game SDK]
//!
//! This crate provides Rust support to the following Discord features:
//!
//! - Activities (Rich Presence)
//! - Users, Avatars and Relationships
//! - Lobbies, Matchmaking and Voice communication
//! - Faux-P2P Networking
//! - Cloud Synchronized (or not) Storage
//! - Store transactions
//! - Achievements
//! - ...
//!
//!
//! # Status
//!
//! This library is currently in early stages but is stabilizing.
//! I'm not aware of any good ways to test this crate, there are currently no tests.
//!
//!
//! # Safety
//!
//! This crate relies on the SDK to provide correct data and behavior:
//! - Non-null pointers to valid memory
//! - UTF-8, NUL-terminated strings
//! - Valid enum values
//! - No mutation of memory it should have no ownership of
//! - No use of pointers after `destroy` is called
//!
//!
//! # "Legal" note
//!
//! This wrapper was informally allowed for publication and distribution by Discord Staff.
//! I cannot redistribute the SDK files until it is made open-source or is licensed for
//! redistribution. You will have to follow some instructions when first setting up your project.
//! Apologies for the inconvenience.
//!
//! If you're a part of Discord and wish to discuss this, please
//! email `ldesgoui@gmail.com` or contact `twiikuu#0047`. I mean no harm.
//!
//!
//! [Discord Game SDK]: https://discordapp.com/developers/docs/game-sdk/sdk-starter-guide

#![doc(html_root_url = "https://docs.rs/discord_game_sdk")]

#[macro_use]
mod macros;

mod achievement;
mod action;
mod activity;
mod activity_kind;
mod callbacks;
mod cast;
mod comparison;
mod create_flags;
mod discord;
mod distance;
mod entitlement;
mod entitlement_kind;
mod error;
mod fetch_kind;
mod file_stat;
mod image;
mod image_handle;
mod image_kind;
mod input_mode;
mod input_mode_kind;
mod lobby;
mod lobby_kind;
mod lobby_member_transaction;
mod lobby_transaction;
pub(crate) mod macro_helper;
mod oauth2_token;
pub(crate) mod panic_messages;
mod premium_kind;
mod presence;
mod relationship;
mod relationship_kind;
mod reliability;
mod request_reply;
mod search_query;
mod sku;
mod sku_kind;
mod status;
mod to_result;
mod user;
mod user_flags;
pub(crate) mod utils;

mod methods {
    mod core;

    mod achievements;
    mod activities;
    mod applications;
    mod images;
    mod lobbies;
    mod networking;
    mod overlay;
    mod relationships;
    mod storage;
    mod store;
    mod users;
    mod voice;
}

/// # Event Types
///
/// This crate makes use of [`crossbeam_channel`] to pass events.
///
/// All event and callback handlers do a minimal amount of work possible across FFI; they send
/// copied or cloned data. Here is why:
/// - Panics in FFI must be intercepted and unwinding must be disabled
/// - Passing a mutable reference to [`Discord`] would result in either mutable aliasing or
///   deadlocks (if using Arc<Mutex<_>>)
///
/// If an event or callback handler runs into a panic across FFI, the panic will be
/// intercepted and the process will be aborted.
///
///
/// ### IMPORTANT NOTE:
/// If you do not make use of all receivers, you must call [`Discord::empty_event_receivers`]
/// or [`event::Receivers::empty_channels`] to prevent the event buffers from growing
/// too big. A safe place to do that would be just before [`Discord::run_callbacks`].
///
///
/// ### IMPORTANT NOTE:
/// Unless you plan to run [`Discord::run_callbacks`] in another thread, waiting for events
/// will block forever. This means that `try_` methods should be used and `select!` must
/// contain a `default` clause.
///
///
/// ### IMPORTANT NOTE:
/// [`crossbeam_channel::Receiver`]s (and [`event::Receivers`]) may be cloned but the events
/// won't be duplicated. An event may only be received once across the whole application.
/// Dispatching events to multiple different places is on you.
///
///
/// ## Examples
///
/// ```no_run
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
///
/// let mut discord = discord_game_sdk::Discord::new(999999999999999999)?;
/// let recvs = discord.event_receivers();
///
/// loop {
///     discord.empty_event_receivers();
///     discord.run_callbacks();
///
///     for _ in recvs.current_user_update.try_iter() {
///         println!("User updated!"),
///     }
/// }
/// # Ok(()) }
/// ```
///
/// [`Discord::empty_event_receivers`]: ../struct.Discord.html#method.empty_event_receivers
/// [`Discord::run_callbacks`]: ../struct.Discord.html#method.run_callbacks
/// [`Discord`]: ../struct.Discord.html
/// [`crossbeam_channel::Receiver`]: https://docs.rs/crossbeam-channel/latest/crossbeam_channel/struct.Receiver.html
/// [`crossbeam_channel::Sender`]: https://docs.rs/crossbeam-channel/latest/crossbeam_channel/struct.Sender.html
/// [`crossbeam_channel`]: https://docs.rs/crossbeam-channel
/// [`event::Receivers::empty_channel`]: struct.Receivers.html#method.empty_channels
/// [`event::Receivers`]: struct.Receivers.html
pub mod event {
    pub mod achievements;
    pub mod activities;
    mod channels;
    pub mod lobbies;
    pub mod networking;
    pub mod overlay;
    pub mod relationships;
    pub mod store;
    pub mod users;
    pub mod voice;

    pub use self::channels::Receivers;
    pub(crate) use self::channels::*;
}

pub(crate) mod across_ffi {
    pub(crate) mod achievements;
    pub(crate) mod activities;
    pub(crate) mod callbacks;
    pub(crate) mod lobbies;
    pub(crate) mod networking;
    pub(crate) mod overlay;
    pub(crate) mod relationships;
    pub(crate) mod store;
    pub(crate) mod users;
    pub(crate) mod voice;
}

pub(crate) use discord_game_sdk_sys as sys;

pub use self::{
    achievement::Achievement,
    action::Action,
    activity::Activity,
    activity_kind::ActivityKind,
    cast::Cast,
    comparison::Comparison,
    create_flags::CreateFlags,
    discord::Discord,
    distance::Distance,
    entitlement::Entitlement,
    entitlement_kind::EntitlementKind,
    error::{Error, Result},
    fetch_kind::FetchKind,
    file_stat::FileStat,
    image::Image,
    image_handle::ImageHandle,
    image_kind::ImageKind,
    input_mode::InputMode,
    input_mode_kind::InputModeKind,
    lobby::Lobby,
    lobby_kind::LobbyKind,
    lobby_member_transaction::LobbyMemberTransaction,
    lobby_transaction::LobbyTransaction,
    oauth2_token::OAuth2Token,
    premium_kind::PremiumKind,
    presence::Presence,
    relationship::Relationship,
    relationship_kind::RelationshipKind,
    reliability::Reliability,
    request_reply::RequestReply,
    search_query::SearchQuery,
    sku::Sku,
    sku_kind::SkuKind,
    status::Status,
    user::User,
    user_flags::UserFlags,
};