Skip to content

Commit 2ec7b98

Browse files
committed
Rendering: Trigger an event when the current map has been changed instead of polling it through a RwLock
1 parent f07120d commit 2ec7b98

2 files changed

Lines changed: 52 additions & 32 deletions

File tree

src/game/map_manager.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,15 @@ pub struct MapManager {
4242
// now, it works that way.
4343
pub current_light_settings: Option<LightSettings>,
4444
pub sunlight: Sunlight,
45+
/// A watcher to notify dependent systems of map changes.
46+
/// Note: This shall replace the current polling of current_map
47+
pub map_watcher: tokio::sync::watch::Receiver<Option<String>>,
48+
map_event_sender: tokio::sync::watch::Sender<Option<String>>,
4549
}
4650

4751
impl MapManager {
4852
pub fn new(mpq_loader: Arc<MPQLoader>) -> Self {
53+
let (map_event_sender, map_watcher) = tokio::sync::watch::channel(None);
4954
Self {
5055
mpq_loader: mpq_loader.clone(),
5156
current_map: None,
@@ -61,6 +66,8 @@ impl MapManager {
6166
map_light_settings: vec![],
6267
current_light_settings: None,
6368
sunlight: Sunlight::new(3.0),
69+
map_watcher,
70+
map_event_sender,
6471
}
6572
}
6673

@@ -120,7 +127,8 @@ impl MapManager {
120127
}
121128
}
122129

123-
self.current_map = Some((map, wdt));
130+
self.current_map = Some((map.clone(), wdt));
131+
self.map_event_sender.send_replace(Some(map));
124132
warn!("Loading took {}ms", now.elapsed().as_millis());
125133
// ADT file is map_x_y.adt. I think x are rows and ys are columns.
126134
}

src/rendering/application.rs

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ pub struct RenderingApplication {
6565
grabber: Option<Grabber>,
6666
app: Weak<GameApplication>,
6767

68-
// mirroring the state of the MapManager.
69-
current_map: Option<String>,
68+
on_map_change: tokio::sync::watch::Receiver<Option<String>>,
7069
tile_graph: HashMap<(u8, u8), Arc<ADTNode>>,
7170
missing_texture_material: Option<MaterialHandle>,
7271
texture_still_loading_material: Option<MaterialHandle>,
@@ -80,6 +79,16 @@ pub struct RenderingApplication {
8079

8180
impl RenderingApplication {
8281
pub fn new(app: Weak<GameApplication>, sample_count: SampleCount) -> Self {
82+
let on_map_change = {
83+
let app_strong = app.upgrade().expect("Weak Pointer expired");
84+
let mm = app_strong
85+
.game_state
86+
.map_manager
87+
.read()
88+
.expect("Map Manager Read Lock");
89+
mm.map_watcher.clone()
90+
};
91+
8392
Self {
8493
app,
8594
scancode_status: FastHashMap::default(),
@@ -88,7 +97,7 @@ impl RenderingApplication {
8897
camera_location: Vec3A::new(0.0, 0.0, 0.0),
8998
timestamp_last_frame: Instant::now(),
9099
grabber: None,
91-
current_map: None,
100+
on_map_change,
92101
tile_graph: HashMap::new(),
93102
missing_texture_material: None,
94103
texture_still_loading_material: None,
@@ -127,32 +136,36 @@ impl RenderingApplication {
127136
self.camera_location = coordinate_systems::adt_to_blender(player_loc);
128137
}
129138

130-
let mm_lock = app.game_state.clone().map_manager.clone();
139+
let mm_lock = &app.game_state.map_manager;
140+
if self
141+
.on_map_change
142+
.has_changed()
143+
.expect("map change channel has been closed")
131144
{
132-
let mm = mm_lock.read().expect("Read Lock on Map Manager");
133-
if mm.current_map.is_some() != self.current_map.is_some() /* initial load or unload */ ||
134-
(mm.current_map.is_some() && &mm.current_map.as_ref().unwrap().0 != self.current_map.as_ref().unwrap())
135-
{
136-
trace!("Map has changed, discarding everything");
137-
self.tile_graph.clear();
138-
self.current_map = Some(mm.current_map.as_ref().unwrap().0.clone());
139-
140-
// TODO: This needs to be more sophisticated, in general it sucks that we just can't call from the packet handler into RenderApplication
141-
self.camera_location = coordinate_systems::adt_to_blender(
142-
*app.game_state
143-
.player_location
144-
.read()
145-
.expect("Read Lock on Player Location"),
146-
);
145+
trace!("Map has changed, discarding everything");
146+
147+
// We don't even care for the actual map name as we rely on the map manager's tile graph
148+
self.on_map_change.mark_unchanged();
149+
self.tile_graph.clear();
150+
151+
// TODO: This needs to be more sophisticated, in general it sucks that we just can't call from the packet handler into RenderApplication
152+
self.camera_location = coordinate_systems::adt_to_blender(
153+
*app.game_state
154+
.player_location
155+
.read()
156+
.expect("Read Lock on Player Location"),
157+
);
147158

148-
self.camera_yaw = PI
149-
- *app
150-
.game_state
151-
.player_orientation
152-
.read()
153-
.expect("Read Lock on Player Orientation");
154-
}
159+
self.camera_yaw = PI
160+
- *app
161+
.game_state
162+
.player_orientation
163+
.read()
164+
.expect("Read Lock on Player Orientation");
165+
}
155166

167+
{
168+
let mm = mm_lock.read().expect("Read Lock on Map Manager");
156169
let added_tiles = mm
157170
.tile_graph
158171
.iter()
@@ -174,14 +187,13 @@ impl RenderingApplication {
174187
self.add_tile_graph(renderer, *key, &val);
175188
self.tile_graph.insert(*key, val);
176189
}
190+
}
177191

178-
for (key, value) in &self.tile_graph {
179-
// currently, we only update doodads
180-
self.update_tile_graph(renderer, *key, value);
181-
}
192+
for (key, value) in &self.tile_graph {
193+
// currently, we only update doodads
194+
self.update_tile_graph(renderer, *key, value);
182195
}
183196

184-
// a) We need to drop mm first and b) this should happen after the camera_location has been initially set
185197
mm_lock
186198
.write()
187199
.expect("Write lock on map manager")

0 commit comments

Comments
 (0)