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
//! Safer access to a running Source SDK 2013 server from a plugin.
//!
//! # Entry point
//!
//! Everything starts from a [`Server`], which [`Server::new`] creates from the
//! engine's and game server's interface factories for the duration of one
//! callback. Its safety contract covers what every other type relies on, and
//! each interface is then a safe accessor away, such as [`Server::valve_engine`]
//! or [`Server::server_game_dll`]. Operations with additional requirements,
//! such as entity spawning or schema-dependent attribute writes, document
//! their own `unsafe` contracts.
//!
//! # Handles and aliasing
//!
//! The engine and game own their objects and mutate them through their own
//! pointers at any time, including in the middle of calls made from Rust. A
//! Rust reference into such an object would promise an immutability (`&T`) or
//! exclusivity (`&mut T`) that Rust cannot guarantee, so this crate never
//! creates one. Engine objects are reached through handles instead, which
//! store the pointer the engine returned and access the object only through
//! virtual calls and raw reads and writes, like a `Cell`:
//!
//! - Handles are `Copy`, and their methods take `self`. Sharing a handle is
//! like sharing `&Cell<T>`: exclusivity would protect nothing, since the
//! engine keeps its own pointers.
//! - Handles carry the scope lifetime of the `Server` they came from, so none
//! outlives the callback in which the engine keeps the object alive.
//! - Handles are `!Send` and `!Sync`, since the engine is single-threaded.
//! - Data read out of the engine is copied unless it stays unchanged for the
//! whole scope, such as class names or static strings.
//!
//! Uniqueness is reserved for what the plugin owns: an [`OwnedGameEvent`] is
//! freed exactly once, and a [`GameEventListener`] is registered by pinned
//! reference and is `!Unpin`, since the engine keeps its address.
//!
//! [`OwnedGameEvent`]: interfaces::game_event::OwnedGameEvent
//! [`GameEventListener`]: interfaces::game_event::GameEventListener
use PhantomData;
/// The hand-written raw bindings and low-level utilities this crate wraps,
/// for what [`sys`] does not generate.
pub use sdk_raw as raw;
pub use ;
/// The raw Source SDK bindings this crate wraps.
pub use sys;
/// Makes a type `!Send` and `!Sync`.
///
/// Engine state may only be touched from the server's main thread.
pub type NotThreadSafe = ;