Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ fn init(ctx: &ReducerContext) {

#[reducer(client_connected)]
fn client_connected(ctx: &ReducerContext) {
let existing_user = ctx.db.offline_user().identity().find(ctx.sender);
let existing_user = ctx.db.offline_user().identity().find(ctx.sender());
if let Some(user) = existing_user {
ctx.db.user().insert(user);
ctx.db.offline_user().identity().delete(ctx.sender);
ctx.db.offline_user().identity().delete(ctx.sender());
return;
}
ctx.db.offline_user().insert(User {
identity: ctx.sender,
identity: ctx.sender(),
has_incremented_count: 0,
});
}

#[reducer(client_disconnected)]
fn client_disconnected(ctx: &ReducerContext) -> Result<(), String> {
let existing_user = ctx.db.user().identity().find(ctx.sender).ok_or("User not found")?;
let existing_user = ctx.db.user().identity().find(ctx.sender()).ok_or("User not found")?;
ctx.db.offline_user().insert(existing_user);
ctx.db.user().identity().delete(ctx.sender);
ctx.db.user().identity().delete(ctx.sender());
Ok(())
}

Expand All @@ -48,7 +48,7 @@ fn increment_counter(ctx: &ReducerContext) -> Result<(), String> {
counter.count += 1;
ctx.db.counter().id().update(counter);

let mut user = ctx.db.user().identity().find(ctx.sender).ok_or("User not found")?;
let mut user = ctx.db.user().identity().find(ctx.sender()).ok_or("User not found")?;
user.has_incremented_count += 1;
ctx.db.user().identity().update(user);

Expand Down
2 changes: 1 addition & 1 deletion crates/bindings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ struct PlayerAndLevel {
// At-most-one row: return Option<T>
#[view(name = my_player, public)]
fn my_player(ctx: &ViewContext) -> Option<Player> {
ctx.db.player().identity().find(ctx.sender)
ctx.db.player().identity().find(ctx.sender())
}

// Multiple rows: return Vec<T>
Expand Down
30 changes: 23 additions & 7 deletions crates/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ pub use spacetimedb_bindings_macro::table;
///
/// #[reducer]
/// fn scheduled(ctx: &ReducerContext, args: ScheduledArgs) -> Result<(), String> {
/// if ctx.sender != ctx.identity() {
/// if ctx.sender() != ctx.identity() {
/// return Err("Reducer `scheduled` may not be invoked by clients, only via scheduling.".into());
/// }
/// // Reducer body...
Expand Down Expand Up @@ -707,7 +707,7 @@ pub use spacetimedb_bindings_macro::reducer;
/// #[procedure]
/// fn return_value(ctx: &mut ProcedureContext, arg: MyArgument) -> MyReturnValue {
/// MyReturnValue {
/// a: format!("Hello, {}", ctx.sender),
/// a: format!("Hello, {}", ctx.sender()),
/// b: ctx.timestamp,
/// }
/// }
Expand Down Expand Up @@ -816,13 +816,13 @@ pub use spacetimedb_bindings_macro::procedure;
/// // A view that selects at most one row from a table
/// #[view(name = my_player, public)]
/// fn my_player(ctx: &ViewContext) -> Option<Player> {
/// ctx.db.player().identity().find(ctx.sender)
/// ctx.db.player().identity().find(ctx.sender())
/// }
///
/// // An example of column projection
/// #[view(name = my_player_id, public)]
/// fn my_player_id(ctx: &ViewContext) -> Option<PlayerId> {
/// ctx.db.player().identity().find(ctx.sender).map(|Player { id, .. }| PlayerId { id })
/// ctx.db.player().identity().find(ctx.sender()).map(|Player { id, .. }| PlayerId { id })
/// }
///
/// // An example that is analogous to a semijoin in sql
Expand Down Expand Up @@ -894,7 +894,7 @@ impl Default for AnonymousViewContext {
/// The other is [`AnonymousViewContext`].
/// Use this type if the view depends on the caller's identity.
pub struct ViewContext {
pub sender: Identity,
sender: Identity,
pub db: LocalReadOnly,
pub from: QueryBuilder,
}
Expand All @@ -907,6 +907,11 @@ impl ViewContext {
from: QueryBuilder {},
}
}

/// The `Identity` of the client that invoked the view.
pub fn sender(&self) -> Identity {
self.sender
}
}

/// The context that any reducer is provided with.
Expand All @@ -924,7 +929,7 @@ impl ViewContext {
#[non_exhaustive]
pub struct ReducerContext {
/// The `Identity` of the client that invoked the reducer.
pub sender: Identity,
sender: Identity,

/// The time at which the reducer was started.
pub timestamp: Timestamp,
Expand Down Expand Up @@ -1014,6 +1019,11 @@ impl ReducerContext {
}
}

/// The `Identity` of the client that invoked the reducer.
pub fn sender(&self) -> Identity {
self.sender
}

/// Returns the authorization information for the caller of this reducer.
pub fn sender_auth(&self) -> &AuthCtx {
&self.sender_auth
Expand Down Expand Up @@ -1124,7 +1134,7 @@ impl Deref for TxContext {
#[cfg(feature = "unstable")]
pub struct ProcedureContext {
/// The `Identity` of the client that invoked the procedure.
pub sender: Identity,
sender: Identity,

/// The time at which the procedure was started.
pub timestamp: Timestamp,
Expand Down Expand Up @@ -1162,6 +1172,12 @@ impl ProcedureContext {
counter_uuid: Cell::new(0),
}
}

/// The `Identity` of the client that invoked the procedure.
pub fn sender(&self) -> Identity {
self.sender
}

/// Read the current module's [`Identity`].
pub fn identity(&self) -> Identity {
// Hypothetically, we *could* read the module identity out of the system tables.
Expand Down
28 changes: 19 additions & 9 deletions demo/Blackholio/server-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ pub fn init(ctx: &ReducerContext) -> Result<(), String> {

#[spacetimedb::reducer(client_connected)]
pub fn connect(ctx: &ReducerContext) -> Result<(), String> {
if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) {
if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) {
ctx.db.player().insert(player.clone());
ctx.db.logged_out_player().identity().delete(&player.identity);

Expand All @@ -157,7 +157,7 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> {
}
} else {
ctx.db.player().try_insert(Player {
identity: ctx.sender,
identity: ctx.sender(),
player_id: 0,
name: String::new(),
})?;
Expand All @@ -167,10 +167,15 @@ pub fn connect(ctx: &ReducerContext) -> Result<(), String> {

#[spacetimedb::reducer(client_disconnected)]
pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> {
let player = ctx.db.player().identity().find(&ctx.sender).ok_or("Player not found")?;
let player = ctx
.db
.player()
.identity()
.find(&ctx.sender())
.ok_or("Player not found")?;
let player_id = player.player_id;
ctx.db.logged_out_player().insert(player);
ctx.db.player().identity().delete(&ctx.sender);
ctx.db.player().identity().delete(&ctx.sender());

// Move any circles from the arena into logged out tables
for circle in ctx.db.circle().player_id().filter(&player_id) {
Expand All @@ -187,7 +192,7 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> {
#[spacetimedb::reducer]
pub fn enter_game(ctx: &ReducerContext, name: String) -> Result<(), String> {
log::info!("Creating player with name {}", name);
let mut player: Player = ctx.db.player().identity().find(ctx.sender).ok_or("")?;
let mut player: Player = ctx.db.player().identity().find(ctx.sender()).ok_or("")?;
let player_id = player.player_id;
player.name = name;
ctx.db.player().identity().update(player);
Expand Down Expand Up @@ -234,7 +239,7 @@ pub fn respawn(ctx: &ReducerContext) -> Result<(), String> {
.db
.player()
.identity()
.find(&ctx.sender)
.find(&ctx.sender())
.ok_or("No such player found")?;

spawn_player_initial_circle(ctx, player.player_id)?;
Expand All @@ -248,7 +253,7 @@ pub fn suicide(ctx: &ReducerContext) -> Result<(), String> {
.db
.player()
.identity()
.find(&ctx.sender)
.find(&ctx.sender())
.ok_or("No such player found")?;

for circle in ctx.db.circle().player_id().filter(&player.player_id) {
Expand All @@ -260,7 +265,12 @@ pub fn suicide(ctx: &ReducerContext) -> Result<(), String> {

#[spacetimedb::reducer]
pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result<(), String> {
let player = ctx.db.player().identity().find(&ctx.sender).ok_or("Player not found")?;
let player = ctx
.db
.player()
.identity()
.find(&ctx.sender())
.ok_or("Player not found")?;
for mut circle in ctx.db.circle().player_id().filter(&player.player_id) {
circle.direction = direction.normalized();
circle.speed = direction.magnitude().clamp(0.0, 1.0);
Expand Down Expand Up @@ -467,7 +477,7 @@ pub fn player_split(ctx: &ReducerContext) -> Result<(), String> {
.db
.player()
.identity()
.find(&ctx.sender)
.find(&ctx.sender())
.ok_or("Sender has no player")?;
let circles: Vec<Circle> = ctx.db.circle().player_id().filter(&player.player_id).collect();
let mut circle_count = circles.len() as i32;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ A view can be written in Rust like so:
```rust
#[spacetimedb::view(name = my_player, public)]
fn my_player(ctx: &spacetimedb::ViewContext) -> Option<Player> {
ctx.db.player().identity().find(ctx.sender)
ctx.db.player().identity().find(ctx.sender())
}
```

Expand Down
12 changes: 6 additions & 6 deletions docs/docs/00100-intro/00300-tutorials/00100-chat-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ Add to `spacetimedb/src/lib.rs`:
#[reducer]
pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> {
let name = validate_name(name)?;
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender()) {
ctx.db.user().identity().update(User { name: Some(name), ..user });
Ok(())
} else {
Expand Down Expand Up @@ -439,7 +439,7 @@ pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> {
let text = validate_message(text)?;
log::info!("{}", text);
ctx.db.message().insert(Message {
sender: ctx.sender,
sender: ctx.sender(),
text,
sent: ctx.timestamp,
});
Expand Down Expand Up @@ -547,23 +547,23 @@ Add to `spacetimedb/src/lib.rs`:
```rust server
#[reducer(client_connected)]
pub fn client_connected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender()) {
ctx.db.user().identity().update(User { online: true, ..user });
} else {
ctx.db.user().insert(User {
name: None,
identity: ctx.sender,
identity: ctx.sender(),
online: true,
});
}
}

#[reducer(client_disconnected)]
pub fn identity_disconnected(ctx: &ReducerContext) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender) {
if let Some(user) = ctx.db.user().identity().find(ctx.sender()) {
ctx.db.user().identity().update(User { online: false, ..user });
} else {
log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender);
log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender());
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ public static void Debug(ReducerContext ctx)
```rust
#[spacetimedb::reducer]
pub fn debug(ctx: &ReducerContext) -> Result<(), String> {
log::debug!("This reducer was called by {}.", ctx.sender);
log::debug!("This reducer was called by {}.", ctx.sender());
Ok(())
}
```
Expand Down Expand Up @@ -463,7 +463,7 @@ Next let's connect our client to our database. Let's start by modifying our `deb
```rust
#[spacetimedb::reducer(client_connected)]
pub fn connect(ctx: &ReducerContext) -> Result<(), String> {
log::debug!("{} just connected.", ctx.sender);
log::debug!("{} just connected.", ctx.sender());
Ok(())
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,15 +391,15 @@ Next, modify your `connect` reducer and add a new `disconnect` reducer below it:
```rust
#[spacetimedb::reducer(client_connected)]
pub fn connect(ctx: &ReducerContext) -> Result<(), String> {
if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender) {
if let Some(player) = ctx.db.logged_out_player().identity().find(&ctx.sender()) {
ctx.db.player().insert(player.clone());
ctx.db
.logged_out_player()
.identity()
.delete(&player.identity);
} else {
ctx.db.player().try_insert(Player {
identity: ctx.sender,
identity: ctx.sender(),
player_id: 0,
name: String::new(),
})?;
Expand All @@ -413,11 +413,11 @@ pub fn disconnect(ctx: &ReducerContext) -> Result<(), String> {
.db
.player()
.identity()
.find(&ctx.sender)
.find(&ctx.sender())
.ok_or("Player not found")?;
let player_id = player.player_id;
ctx.db.logged_out_player().insert(player);
ctx.db.player().identity().delete(&ctx.sender);
ctx.db.player().identity().delete(&ctx.sender());

Ok(())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result
.db
.player()
.identity()
.find(&ctx.sender)
.find(&ctx.sender())
.ok_or("Player not found")?;
for mut circle in ctx.db.circle().player_id().filter(&player.player_id) {
circle.direction = direction.normalized();
Expand All @@ -218,7 +218,7 @@ pub fn update_player_input(ctx: &ReducerContext, direction: DbVector2) -> Result
}
```

This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender` value is not set by the client. Instead `ctx.sender` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called.
This is a simple reducer that takes the movement input from the client and applies them to all circles that that player controls. Note that it is not possible for a player to move another player's circles using this reducer, because the `ctx.sender()` value is not set by the client. Instead `ctx.sender()` is set by SpacetimeDB after it has authenticated that sender. You can rest assured that the caller has been authenticated as that player by the time this reducer is called.

</TabItem>
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ public static void Debug(ReducerContext ctx)
```rust
#[spacetimedb::reducer]
pub fn debug(ctx: &ReducerContext) -> Result<(), String> {
log::debug!("This reducer was called by {}.", ctx.sender);
log::debug!("This reducer was called by {}.", ctx.sender());
Ok(())
}
```
Expand Down Expand Up @@ -459,7 +459,7 @@ Next let's connect our client to our database. Let's start by modifying our `deb
```rust
#[spacetimedb::reducer(client_connected)]
pub fn connect(ctx: &ReducerContext) -> Result<(), String> {
log::debug!("{} just connected.", ctx.sender);
log::debug!("{} just connected.", ctx.sender());
Ok(())
}
```
Expand Down
Loading
Loading