mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 17:21:49 -10:00
Building boxes: no per-level clone, linear per-turn snapshot
GameLevel borrows guest_boxes outside a guest turn instead of cloning them, and for_turn only searches the few borrowed ancestors, so a turn costs O(players) rather than O(players^2) for each guest every tick. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ceb886b00f
commit
c17d14c739
2 files changed
+21
-9
No files matched your search
@@ -959,8 +959,9 @@ struct GameLevel<'w> {
|
||||
player_box: Option<([f64; 3], [f64; 3])>,
|
||||
/// The LAN guests in this level who trigger blocks (not spectators).
|
||||
guest_boxes: Vec<([f64; 3], [f64; 3])>,
|
||||
/// Other players that block placement, including a detached guest turn.
|
||||
building_player_boxes: Vec<([f64; 3], [f64; 3])>,
|
||||
/// Other players that block placement during a guest turn, whose hub is
|
||||
/// borrowed out; None outside one, where `guest_boxes` are those players.
|
||||
building_player_boxes: Option<Vec<([f64; 3], [f64; 3])>>,
|
||||
player_collision: Option<PlayerCollision>,
|
||||
/// Minecart boxes (detector rails).
|
||||
cart_boxes: Vec<([f64; 3], [f64; 3])>,
|
||||
@@ -1151,7 +1152,11 @@ impl GameLevel<'_> {
|
||||
let b = self.entities;
|
||||
self.player_box
|
||||
.iter()
|
||||
.chain(&self.building_player_boxes)
|
||||
.chain(
|
||||
self.building_player_boxes
|
||||
.as_ref()
|
||||
.unwrap_or(&self.guest_boxes),
|
||||
)
|
||||
.chain(&self.cart_boxes)
|
||||
.map(boxed)
|
||||
.chain(b.mobs.iter().filter(|m| !m.removed).map(Mob::bounds))
|
||||
@@ -4638,11 +4643,10 @@ impl Game<'_> {
|
||||
})
|
||||
.collect();
|
||||
let guest_boxes = self.lan_block_trigger_boxes();
|
||||
let building_player_boxes = if self.lan_acting.is_some() {
|
||||
self.lan_building_boxes.boxes(self.dim)
|
||||
} else {
|
||||
guest_boxes.clone()
|
||||
};
|
||||
let building_player_boxes = self
|
||||
.lan_acting
|
||||
.is_some()
|
||||
.then(|| self.lan_building_boxes.boxes(self.dim));
|
||||
let dimension = match self.dim {
|
||||
Dim::Overworld => LevelDimension::Overworld,
|
||||
Dim::Nether => LevelDimension::Nether,
|
||||
|
||||
@@ -23,6 +23,9 @@ impl BuildingPlayers {
|
||||
outer: Option<BuildingPlayer>,
|
||||
current: Vec<BuildingPlayer>,
|
||||
) -> Self {
|
||||
// The borrowed ancestors are the few nested turns (usually none or
|
||||
// one): only they are searched, so a turn costs O(players), not
|
||||
// O(players²), every guest's turn of every tick.
|
||||
let mut players: Vec<_> = self
|
||||
.0
|
||||
.iter()
|
||||
@@ -41,8 +44,13 @@ impl BuildingPlayers {
|
||||
players.push(outer);
|
||||
}
|
||||
}
|
||||
let ancestors = players.len();
|
||||
players.reserve(current.len());
|
||||
for player in current {
|
||||
if player.conn != Some(actor) && !players.iter().any(|p| p.conn == player.conn) {
|
||||
// Hub conns are unique, so only the ancestors can already hold one.
|
||||
if player.conn != Some(actor)
|
||||
&& !players[..ancestors].iter().any(|p| p.conn == player.conn)
|
||||
{
|
||||
players.push(player);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user