mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Boats tick in turn even when a pass removes one
boat_server_passes runs inside the loop now, and lava breaks a boat there: a for loop over the indexes skipped the boat that moved into the broken one's place. The next boat is found after this one by its id. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
2e6f8a98fb
commit
e431c279f4
1 file changed
+44
-35
@@ -726,46 +726,55 @@ impl Game<'_> {
|
||||
// EntityTickEvent.Post comes once AbstractBoat.tick is over, after the
|
||||
// passes of `boat_server_passes` (lava, ejection, bubbles, contacts),
|
||||
// and before the next boat ticks, as `ServerLevel.tickNonPassenger`.
|
||||
for i in 0..self.boats.len() {
|
||||
// A mod's hook may have removed boats.
|
||||
if i >= self.boats.len() {
|
||||
break;
|
||||
}
|
||||
let p = self.boats[i].position;
|
||||
// A pass (lava breaks a boat) or a mod's hook may remove boats: the next one is found
|
||||
// after this one by its id, so none is skipped or ticked twice.
|
||||
let mut i = 0;
|
||||
while i < self.boats.len() {
|
||||
let id = self.boats[i].id;
|
||||
if Some(id) == self.riding
|
||||
|| driven.contains(&id)
|
||||
|| !ticking(p.x.floor() as i32, p.z.floor() as i32)
|
||||
{
|
||||
// Its rider's client moves it, but the lead still ticks.
|
||||
if ticking(p.x.floor() as i32, p.z.floor() as i32) && self.remote.is_none() {
|
||||
let mut b = self.boats[i].clone();
|
||||
self.tick_boat_leash(&mut b);
|
||||
self.boats[i] = b;
|
||||
'boat: {
|
||||
let p = self.boats[i].position;
|
||||
if Some(id) == self.riding
|
||||
|| driven.contains(&id)
|
||||
|| !ticking(p.x.floor() as i32, p.z.floor() as i32)
|
||||
{
|
||||
// Its rider's client moves it, but the lead still ticks.
|
||||
if ticking(p.x.floor() as i32, p.z.floor() as i32) && self.remote.is_none() {
|
||||
let mut b = self.boats[i].clone();
|
||||
self.tick_boat_leash(&mut b);
|
||||
self.boats[i] = b;
|
||||
}
|
||||
self.boat_server_passes(id, &driven, &ticking, &round);
|
||||
break 'boat;
|
||||
}
|
||||
let kind = if round.listening() {
|
||||
self.boats[i].entity_type()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
if !self.native_tick_pre_one(&mut round, id, &kind) {
|
||||
self.boat_server_passes(id, &driven, &ticking, &round);
|
||||
break 'boat;
|
||||
}
|
||||
// The hook may have removed boats.
|
||||
let Some(i) = Some(i)
|
||||
.filter(|&i| self.boats.get(i).is_some_and(|b| b.id == id))
|
||||
.or_else(|| self.boats.iter().position(|b| b.id == id))
|
||||
else {
|
||||
break 'boat;
|
||||
};
|
||||
let b = self.boats[i].clone();
|
||||
self.boats[i] = self.tick_boat(b, false);
|
||||
self.boat_server_passes(id, &driven, &ticking, &round);
|
||||
continue;
|
||||
self.native_tick_post_one(&round, id, &kind);
|
||||
}
|
||||
let kind = if round.listening() {
|
||||
self.boats[i].entity_type()
|
||||
} else {
|
||||
String::new()
|
||||
i = match self.boats.get(i) {
|
||||
Some(b) if b.id == id => i + 1,
|
||||
_ => self
|
||||
.boats
|
||||
.iter()
|
||||
.position(|b| b.id == id)
|
||||
.map_or(i, |k| k + 1),
|
||||
};
|
||||
if !self.native_tick_pre_one(&mut round, id, &kind) {
|
||||
self.boat_server_passes(id, &driven, &ticking, &round);
|
||||
continue;
|
||||
}
|
||||
// The hook may have removed boats.
|
||||
let Some(i) = Some(i)
|
||||
.filter(|&i| self.boats.get(i).is_some_and(|b| b.id == id))
|
||||
.or_else(|| self.boats.iter().position(|b| b.id == id))
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let b = self.boats[i].clone();
|
||||
self.boats[i] = self.tick_boat(b, false);
|
||||
self.boat_server_passes(id, &driven, &ticking, &round);
|
||||
self.native_tick_post_one(&round, id, &kind);
|
||||
}
|
||||
}
|
||||
/// The rest of `AbstractBoat.tick` on the server, for every boat, the
|
||||
|
||||
Reference in new issue
Block a user