steel_core/world/tick_scheduler/
world.rs1use super::super::*;
2
3impl World {
4 pub fn schedule_block_tick(
11 &self,
12 pos: BlockPos,
13 block: BlockRef,
14 delay: i32,
15 priority: super::TickPriority,
16 ) {
17 let trigger_tick = self.game_time().wrapping_add(i64::from(delay));
18 let order = self.scheduled_ticks.next_sub_tick_order();
19 let chunk_pos = Self::chunk_pos_for_block(pos);
20 self.chunk_map.with_full_chunk(chunk_pos, |chunk| {
21 chunk.schedule_block_tick(pos, block, trigger_tick, priority, order);
22 });
23 }
24
25 pub fn schedule_block_tick_default(&self, pos: BlockPos, block: BlockRef, delay: i32) {
27 self.schedule_block_tick(pos, block, delay, super::TickPriority::Normal);
28 }
29
30 pub fn schedule_fluid_tick(
36 &self,
37 pos: BlockPos,
38 fluid: FluidRef,
39 delay: i32,
40 priority: super::TickPriority,
41 ) {
42 let trigger_tick = self.game_time().wrapping_add(i64::from(delay));
43 let order = self.scheduled_ticks.next_sub_tick_order();
44 let chunk_pos = Self::chunk_pos_for_block(pos);
45 self.chunk_map.with_full_chunk(chunk_pos, |chunk| {
46 chunk.schedule_fluid_tick(pos, fluid, trigger_tick, priority, order);
47 });
48 }
49
50 pub fn schedule_fluid_tick_default(&self, pos: BlockPos, fluid: FluidRef, delay: i32) {
52 self.schedule_fluid_tick(pos, fluid, delay, super::TickPriority::Normal);
53 }
54
55 pub fn has_scheduled_block_tick(&self, pos: BlockPos, block: BlockRef) -> bool {
62 let chunk_pos = Self::chunk_pos_for_block(pos);
63 self.chunk_map
64 .with_full_chunk(chunk_pos, |chunk| {
65 match chunk.has_scheduled_block_tick(pos, block) {
66 Ok(has_tick) => has_tick,
67 Err(error) => {
68 panic!("Full chunk scheduled-tick ownership invariant failed: {error:?}")
69 }
70 }
71 })
72 .unwrap_or(false)
73 }
74
75 pub fn has_scheduled_fluid_tick(&self, pos: BlockPos, fluid: FluidRef) -> bool {
82 let chunk_pos = Self::chunk_pos_for_block(pos);
83 self.chunk_map
84 .with_full_chunk(chunk_pos, |chunk| {
85 match chunk.has_scheduled_fluid_tick(pos, fluid) {
86 Ok(has_tick) => has_tick,
87 Err(error) => {
88 panic!("Full chunk scheduled-tick ownership invariant failed: {error:?}")
89 }
90 }
91 })
92 .unwrap_or(false)
93 }
94
95 pub(crate) fn register_full_chunk_ticks(
96 &self,
97 chunk: FullChunkRef<'_>,
98 ) -> Result<(), super::TickSchedulerError> {
99 self.scheduled_ticks.register_chunk(chunk)
100 }
101
102 pub(crate) fn unregister_full_chunk_ticks(&self, pos: ChunkPos) {
103 self.scheduled_ticks.unregister_chunk(pos);
104 }
105
106 #[cfg(test)]
107 pub(crate) fn has_registered_full_chunk_ticks(&self, pos: ChunkPos) -> bool {
108 self.scheduled_ticks.has_registered_chunk(pos)
109 }
110
111 #[cfg(test)]
112 pub(crate) fn has_indexed_scheduled_tick_head(&self, pos: ChunkPos) -> bool {
113 self.scheduled_ticks.has_indexed_head(pos)
114 }
115
116 pub(crate) fn schedule_block_tick_for_chunk(
117 &self,
118 chunk: FullChunkRef<'_>,
119 pos: BlockPos,
120 block: BlockRef,
121 trigger_tick: i64,
122 priority: super::TickPriority,
123 sub_tick_order: i64,
124 ) -> Result<bool, super::TickSchedulerError> {
125 self.scheduled_ticks.schedule_block(
126 chunk,
127 block,
128 pos,
129 trigger_tick,
130 priority,
131 sub_tick_order,
132 )
133 }
134
135 pub(crate) fn schedule_fluid_tick_for_chunk(
136 &self,
137 chunk: FullChunkRef<'_>,
138 pos: BlockPos,
139 fluid: FluidRef,
140 trigger_tick: i64,
141 priority: super::TickPriority,
142 sub_tick_order: i64,
143 ) -> Result<bool, super::TickSchedulerError> {
144 self.scheduled_ticks.schedule_fluid(
145 chunk,
146 fluid,
147 pos,
148 trigger_tick,
149 priority,
150 sub_tick_order,
151 )
152 }
153
154 pub(crate) fn unpack_scheduled_ticks(
155 &self,
156 pos: ChunkPos,
157 ) -> Result<(), super::TickSchedulerError> {
158 self.scheduled_ticks.unpack_chunk(pos, self.game_time())
159 }
160
161 pub(crate) fn reconcile_active_scheduled_tick_chunks<I>(
162 &self,
163 active_chunks: I,
164 ) -> Result<(), super::TickSchedulerError>
165 where
166 I: Iterator<Item = ChunkPos> + Clone,
167 {
168 self.scheduled_ticks.reconcile_active_chunks(active_chunks)
169 }
170
171 pub(crate) fn begin_scheduled_tick_phase(
172 &self,
173 current_tick: i64,
174 max_ticks: usize,
175 ) -> super::ScheduledTickBatch<BlockRef> {
176 self.scheduled_ticks.begin_tick(current_tick, max_ticks)
177 }
178
179 pub(crate) fn collect_scheduled_fluid_tick_batch(
180 &self,
181 current_tick: i64,
182 max_ticks: usize,
183 ) -> super::ScheduledTickBatch<FluidRef> {
184 self.scheduled_ticks
185 .collect_fluid_ticks(current_tick, max_ticks)
186 }
187
188 pub fn will_tick_block_this_tick(&self, pos: BlockPos, block: BlockRef) -> bool {
194 let batch = self
195 .scheduled_block_ticks_this_tick
196 .lock()
197 .as_ref()
198 .map(Arc::clone);
199 batch.is_some_and(|batch| batch.contains(pos, block))
200 }
201
202 pub fn will_tick_fluid_this_tick(&self, pos: BlockPos, fluid: FluidRef) -> bool {
204 let batch = self
205 .scheduled_fluid_ticks_this_tick
206 .lock()
207 .as_ref()
208 .map(Arc::clone);
209 batch.is_some_and(|batch| batch.contains(pos, fluid))
210 }
211
212 pub(crate) fn begin_scheduled_block_tick_batch(
213 &self,
214 ticks: Vec<super::BlockTick>,
215 ) -> Arc<super::ScheduledTickRunBatch<BlockRef>> {
216 let batch = Arc::new(super::ScheduledTickRunBatch::new(ticks));
217 let mut current = self.scheduled_block_ticks_this_tick.lock();
218 assert!(
219 current.is_none(),
220 "scheduled block-tick batch was already active"
221 );
222 *current = Some(Arc::clone(&batch));
223 batch
224 }
225
226 pub(crate) fn end_scheduled_block_tick_batch(
227 &self,
228 batch: &Arc<super::ScheduledTickRunBatch<BlockRef>>,
229 ) {
230 let removed = {
231 let mut current = self.scheduled_block_ticks_this_tick.lock();
232 assert!(
233 current
234 .as_ref()
235 .is_some_and(|current| Arc::ptr_eq(current, batch)),
236 "scheduled block-tick batch identity changed during execution"
237 );
238 current.take()
239 };
240 drop(removed);
241 }
242
243 pub(crate) fn begin_scheduled_fluid_tick_batch(
244 &self,
245 ticks: Vec<super::FluidTick>,
246 ) -> Arc<super::ScheduledTickRunBatch<FluidRef>> {
247 let batch = Arc::new(super::ScheduledTickRunBatch::new(ticks));
248 let mut current = self.scheduled_fluid_ticks_this_tick.lock();
249 assert!(
250 current.is_none(),
251 "scheduled fluid-tick batch was already active"
252 );
253 *current = Some(Arc::clone(&batch));
254 batch
255 }
256
257 pub(crate) fn end_scheduled_fluid_tick_batch(
258 &self,
259 batch: &Arc<super::ScheduledTickRunBatch<FluidRef>>,
260 ) {
261 let removed = {
262 let mut current = self.scheduled_fluid_ticks_this_tick.lock();
263 assert!(
264 current
265 .as_ref()
266 .is_some_and(|current| Arc::ptr_eq(current, batch)),
267 "scheduled fluid-tick batch identity changed during execution"
268 );
269 current.take()
270 };
271 drop(removed);
272 }
273}