~starkingdoms/starkingdoms

ref: 1bcde11a581ededd03b6e60e8e97048f7556ad66 starkingdoms/crates/unified/src/server/net/update_parts.rs -rw-r--r-- 2.8 KiB
1bcde11a — core netcode: part updates (mystery performance issue, probably related to lots of malloc()) 8 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::collections::BTreeSet;
use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query};
use crate::prelude::{debug, Entity, ParamSet, Transform};
use crate::shared::ecs::{Part, Temperature};
use crate::shared::net::part::{PartUpdatePacket, PartDto};
use crate::shared::net::staged_transform::LastStagedTransform;
use crate::shared::net::{SendTargets, ToClients};

pub fn send_updated_parts(
    mut set: ParamSet<(
        // If you need to send more data, don't add it here...
        Query<(Entity, &Transform), Added<Part>>,
        Query<(Entity, &Transform, &LastStagedTransform), Changed<Transform>>,
        Query<Entity, Changed<Part>>,

        // add it here.
        Query<(&Part, &Transform, &Temperature, &mut LastStagedTransform)>,
    )>,

    mut update_packets_out: MessageWriter<ToClients<PartUpdatePacket>>,
    mut commands: Commands
) {
    let start = bevy::platform::time::Instant::now();
    let mut parts_to_send: BTreeSet<Entity> = BTreeSet::new();

    // Updating the part behavior triggers sprite loading on the client. We don't want to send it every time the Transform changes
    let mut parts_with_part_change: BTreeSet<Entity> = BTreeSet::new();

    for (new_part, transform) in set.p0().iter() {
        parts_to_send.insert(new_part); // Always send newly created parts...
        // ...and add LastStagedTransform...
        commands.entity(new_part).insert(LastStagedTransform(*transform));
        // and put a marker, we need to copy part data across
        parts_with_part_change.insert(new_part);
    }
    for (moved_part, current_transform, maybe_staged_transform) in set.p1().iter() {
        // have we had a significant transform change?
        if !maybe_staged_transform.should_update(current_transform) { continue; }
        // we have, resend
        parts_to_send.insert(moved_part);
    }
    for changed_part in set.p2().iter() {
        // if part changed, always resend
        parts_to_send.insert(changed_part);
        // and put a marker, we need to copy part data across
        parts_with_part_change.insert(changed_part);
    }

    // process all parts to send
    let mut packet = PartUpdatePacket {
        updated_parts: vec![]
    };

    for part_to_send in parts_to_send.iter() {
        let mut q = set.p3();
        let Ok(mut part_info) = q.get_mut(*part_to_send) else { continue };

        *part_info.3 = LastStagedTransform(*part_info.1);

        packet.updated_parts.push(PartDto {
            server_entity: *part_to_send,
            part: part_info.0.clone(),
            part_data_changed: parts_with_part_change.contains(part_to_send),
            transform: *part_info.1,
            temperature: *part_info.2
        });

    }

    update_packets_out.write(ToClients {
        message: packet,
        targets: SendTargets::All,
    });

}