Skip to main content

borger/
lib.rs

1use crate::simulation::{Input, State};
2use crate::simulation_controller::GameContext;
3use borger_plugin_sdk::TickID;
4use borger_plugin_sdk::diff_ser::DiffSerializer;
5use borger_plugin_sdk::multiplayer_tradeoff::{Immediate, WaitForConsensus};
6use borger_plugin_sdk::primitive::usize32;
7
8pub(crate) mod multiplayer_tradeoff;
9pub(crate) mod scope;
10
11///Drives the simulation tick; controls pretty
12///much everything from atop its throne
13#[cfg_attr(not(any(feature = "server", feature = "client")), doc(hidden))]
14pub mod simulation_controller;
15
16///Defines bidirectional, RPC-like communication
17///channels between threads and they data they
18///can carry
19#[cfg_attr(not(any(feature = "server", feature = "client")), doc(hidden))]
20pub mod thread_comms;
21
22///Time-keeping
23pub(crate) mod tick;
24
25mod handwritten {
26	pub(crate) mod constructors;
27	pub(crate) mod diff_des;
28	pub(crate) mod diff_ser;
29	pub(crate) mod simulation;
30	pub(crate) mod snapshot_serdes;
31	pub(crate) mod untracked;
32
33	#[cfg(feature = "client")]
34	pub(crate) mod presentation_collect;
35	#[cfg(feature = "client")]
36	pub(crate) mod presentation_output;
37
38	//things that really ought to be plugins but aren't
39	pub(crate) mod plugin_exports;
40}
41
42#[allow(unused, dead_code)]
43mod generated {
44	pub(crate) mod constructors;
45	pub(crate) mod diff_des;
46	pub(crate) mod diff_ser;
47	pub(crate) mod simulation;
48	pub(crate) mod snapshot_serdes;
49	///Responsible for resetting fields with netVisibility: "Untracked"
50	///back to their default values in between ticks. This is important
51	///for maintaining deterministic behavior; otherwise, the data in
52	///each untracked field is stale/left over from any arbitrary tick,
53	///forward or backward in time. It'd be the same effect as reading
54	///from uninitialized memory
55	pub(crate) mod untracked;
56
57	#[cfg(feature = "client")]
58	pub(crate) mod presentation_collect;
59	#[cfg(feature = "client")]
60	pub(crate) mod presentation_output;
61
62	#[cfg(any(feature = "server", feature = "client"))]
63	pub(crate) mod plugin_exports;
64}
65
66///Struct definitions of state objects
67#[cfg_attr(not(any(feature = "server", feature = "client")), doc(hidden))]
68pub mod simulation {
69	pub use super::generated::simulation::*;
70	pub use super::handwritten::simulation::*;
71}
72
73///Any changes to state during the simulation tick
74///are recorded by this system as they're
75///happening. Rollback and rx systems use this
76///data to make multiplayer happen
77pub(crate) mod diff_ser {
78	pub use super::handwritten::diff_ser::*;
79
80	#[cfg(feature = "client")]
81	pub use super::generated::diff_ser::*;
82}
83
84///Parses and executes operations record by
85///diff_ser. Rollback system undoes changes to
86///predicted state in order to account for the rx
87///system receiving new information (server
88///receiving late inputs, client receiving
89///authoritative state). rx system applies state
90///changes that were received
91pub(crate) mod diff_des {
92	pub use super::handwritten::diff_des::*;
93
94	#[cfg(feature = "server")]
95	pub use super::generated::diff_des::*;
96}
97
98///Take a snapshot (ser/des) of all or part of the
99///state. Used for sending server's current state
100///to a newly connected client. Also used to predict
101///the removal of a collection element. This is a
102///complicated+expensive task because it requires
103///creating a backup of the entire struct being
104///removed in order to be able to roll back to
105///before it was deleted
106pub(crate) mod snapshot_serdes {
107	pub use super::handwritten::snapshot_serdes::*;
108}
109
110///Stripped down version of state (only fields with
111///with presentation enabled), cloned and shipped to
112///the presentation thread at the end of each client
113///sided tick
114#[cfg(feature = "client")]
115pub mod presentation_collect {
116	pub use super::generated::presentation_collect::*;
117	pub use super::handwritten::presentation_collect::*;
118}
119
120///Final output to presentation layer by interpolating
121///and diffing 2 "presentation collect" objects
122#[cfg(feature = "client")]
123pub mod presentation_output {
124	pub use super::generated::presentation_output::*;
125	pub use super::handwritten::presentation_output::*;
126}
127
128///Plugins add new types that can be used in the state.ts schema
129pub mod plugins {
130	pub use super::handwritten::plugin_exports::*;
131
132	#[cfg(any(feature = "server", feature = "client"))]
133	#[allow(unused)]
134	pub use super::generated::plugin_exports::*;
135}
136
137///Helpful types and macros when writing simulation logic
138pub mod prelude {
139	pub use crate::SimulationInitOptions;
140	pub use crate::simulation::*;
141	pub use crate::simulation_controller::GameContext;
142	pub use crate::tick::TickInfo;
143	pub use borger_plugin_sdk::TickID;
144	pub use borger_plugin_sdk::diff_ser::DiffSerializer;
145	pub use borger_plugin_sdk::multiplayer_tradeoff::{
146		AnyTradeOff, Immediate, ImmediateOrWaitForServer, WaitForConsensus, WaitForServer,
147	};
148	pub use borger_plugin_sdk::primitive::{isize32, usize32};
149	pub use borger_plugin_sdk::traits::Interpolate;
150	pub use borger_procmac::server;
151	pub use log::{debug, error, info, warn};
152
153	#[doc(inline)]
154	pub use crate::multiplayer_tradeoff; //macro
155}
156
157pub struct SimulationInitOptions {
158	///Simulation delta time/tick rate, in seconds/tick.
159	///Can be higher or lower than vsync refresh rate.
160	///Too low feels kinda floaty, too high hurts performance.
161	pub sim_dt: f32,
162
163	//pipeline
164	pub init_static_level_geom: Option<fn(/*state*/ &mut State)>,
165	pub simulation_loop: fn(/*ctx*/ &mut GameContext<Immediate>),
166
167	//input operations
168	pub input_merge: fn(/*combined*/ &Input, /*new*/ &Input) -> Input,
169	pub input_validate: fn(/*sus*/ &Input) -> Input,
170	pub input_server_predict_late: fn(
171		/*prv*/ &Input,
172		/*state*/ &State,
173		/*client_id*/ usize32,
174		/*is_timed_out*/ bool,
175	) -> Input,
176	pub input_client_predict_late:
177		fn(/*prv*/ &Input, /*state*/ &State, /*client_id*/ usize32) -> Input,
178
179	//server_events
180	pub on_server_start: fn(/*state*/ &mut State, /*diff*/ &mut DiffSerializer<WaitForConsensus>), //goes without saying tick id is 0
181	pub on_client_connect: fn(
182		/*state*/ &mut State,
183		/*client id*/ usize32,
184		/*tick id*/ TickID,
185		/*diff*/ &mut DiffSerializer<WaitForConsensus>,
186	),
187	pub on_client_disconnect: fn(
188		/*state*/ &mut State,
189		/*id*/ usize32,
190		/*tick id*/ TickID,
191		/*diff*/ &mut DiffSerializer<WaitForConsensus>,
192	),
193}