@@ -90,7 +90,18 @@ impl Iterator for PeersIter {
90
90
}
91
91
}
92
92
93
- /// Get the peer cirresponding to the local device.
93
+ /// Stash is a serialized binary state of the app that you want to persist
94
+ /// between app runs and to be available in multiplayer.
95
+ ///
96
+ /// For single-player purposes, you can save data in a regular file
97
+ /// using [`dump_file`](crate::dump_file). File saved that way can be bigger
98
+ /// (and you can create lots of them) but it cannot be accessed in multiplayer.
99
+ ///
100
+ /// It's your job to serialize data into a binary stash and later parse it.
101
+ /// Stash can be saved using [`save_stash`] and later read using [`load_stash`].
102
+ type Stash = [ u8 ] ;
103
+
104
+ /// Get the peer corresponding to the local device.
94
105
#[ must_use]
95
106
pub fn get_me ( ) -> Peer {
96
107
let me = unsafe { bindings:: get_me ( ) } ;
@@ -104,11 +115,71 @@ pub fn get_peers() -> Peers {
104
115
Peers ( peers)
105
116
}
106
117
118
+ /// Save the given [`Stash`].
119
+ ///
120
+ /// When called, the stash for the given peer will be stored in RAM.
121
+ /// Calling [`load_stash`] for the same peer will return that stash.
122
+ /// On exit, the runtime will persist the stash in FS.
123
+ /// Next time the app starts, calling [`load_stash`] will restore the stash
124
+ /// saved earlier.
125
+ pub fn save_stash ( peer : Peer , stash : & Stash ) {
126
+ let ptr = stash. as_ptr ( ) ;
127
+ let peer = u32:: from ( peer. 0 ) ;
128
+ unsafe {
129
+ bindings:: save_stash ( peer, ptr as u32 , stash. len ( ) as u32 ) ;
130
+ }
131
+ }
132
+
133
+ /// Read the stash of the given peer using the passed buffer.
134
+ ///
135
+ /// It's the app's responsibility to ensure that the passed buffer is big enough
136
+ /// to fit the stash. If it doesn't fit, runtime will fill the buffer
137
+ /// and discard the rest.
138
+ ///
139
+ /// The returned stash is a slice of the passed in buffer of the actual content size
140
+ /// (up to the buffer size).
141
+ ///
142
+ /// If there is no stash (which is always true before [`save_stash`]
143
+ /// is called for the first time ever), the result is `None`.
144
+ #[ must_use]
145
+ pub fn load_stash ( peer : Peer , stash : & mut Stash ) -> Option < & mut Stash > {
146
+ let ptr = stash. as_ptr ( ) ;
147
+ let peer = u32:: from ( peer. 0 ) ;
148
+ let size = unsafe { bindings:: load_stash ( peer, ptr as u32 , stash. len ( ) as u32 ) } ;
149
+ if size == 0 {
150
+ return None ;
151
+ }
152
+ let size = size as usize ;
153
+ Some ( & mut stash[ ..size] )
154
+ }
155
+
156
+ /// Similar to [`load_stash`] but statically allocates the stash of the right size.
157
+ ///
158
+ /// Unlike [`load_stash`], the returned stash size is not adjusted
159
+ /// for the actual content size.
160
+ ///
161
+ /// Unlike other `_buf` functions, like [`load_file_buf`][crate::load_file_buf],
162
+ /// this one allocates the buffer statically, not dynamically.
163
+ /// The app must statically know the max stash size.
164
+ #[ must_use]
165
+ pub fn load_stash_buf < const N : usize > ( peer : Peer ) -> Option < [ u8 ; N ] > {
166
+ let stash = [ 0u8 ; N ] ;
167
+ let ptr = stash. as_ptr ( ) ;
168
+ let peer = u32:: from ( peer. 0 ) ;
169
+ let size = unsafe { bindings:: load_stash ( peer, ptr as u32 , stash. len ( ) as u32 ) } ;
170
+ if size == 0 {
171
+ return None ;
172
+ }
173
+ Some ( stash)
174
+ }
175
+
107
176
/// Internal bindings to the raw runtime functions.
108
177
mod bindings {
109
178
#[ link( wasm_import_module = "net" ) ]
110
179
extern {
111
180
pub ( crate ) fn get_me ( ) -> u32 ;
112
181
pub ( crate ) fn get_peers ( ) -> u32 ;
182
+ pub ( crate ) fn save_stash ( peer : u32 , ptr : u32 , len : u32 ) ;
183
+ pub ( crate ) fn load_stash ( peer : u32 , ptr : u32 , len : u32 ) -> u32 ;
113
184
}
114
185
}
0 commit comments