mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Fix capture progress bar not showing up after point is contested; fix #57
This commit is contained in:
@@ -79,6 +79,7 @@ impl PlayerTracker {
|
|||||||
|
|
||||||
struct PointInfo {
|
struct PointInfo {
|
||||||
team: std::sync::atomic::AtomicI8,
|
team: std::sync::atomic::AtomicI8,
|
||||||
|
attackers: std::sync::atomic::AtomicI8,
|
||||||
on_point: tokio::sync::RwLock<std::collections::HashMap<u8, std::sync::atomic::AtomicU8>>,
|
on_point: tokio::sync::RwLock<std::collections::HashMap<u8, std::sync::atomic::AtomicU8>>,
|
||||||
capture: atomic_float::AtomicF32,
|
capture: atomic_float::AtomicF32,
|
||||||
percent_per_second: f32,
|
percent_per_second: f32,
|
||||||
@@ -88,6 +89,7 @@ impl PointInfo {
|
|||||||
fn new(percent_per_second: f32) -> Self {
|
fn new(percent_per_second: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
team: std::sync::atomic::AtomicI8::new(-1),
|
team: std::sync::atomic::AtomicI8::new(-1),
|
||||||
|
attackers: std::sync::atomic::AtomicI8::new(-1),
|
||||||
on_point: tokio::sync::RwLock::new([
|
on_point: tokio::sync::RwLock::new([
|
||||||
(0, std::sync::atomic::AtomicU8::new(0)),
|
(0, std::sync::atomic::AtomicU8::new(0)),
|
||||||
(1, std::sync::atomic::AtomicU8::new(0)),
|
(1, std::sync::atomic::AtomicU8::new(0)),
|
||||||
@@ -208,18 +210,21 @@ impl PointTracker {
|
|||||||
let player_team_u8 = player_team as u8;
|
let player_team_u8 = player_team as u8;
|
||||||
if let Some(point) = self.points.get(point_i as usize) {
|
if let Some(point) = self.points.get(point_i as usize) {
|
||||||
let point_team = point.team.load(std::sync::atomic::Ordering::SeqCst);
|
let point_team = point.team.load(std::sync::atomic::Ordering::SeqCst);
|
||||||
|
let attacking_team = point.attackers.load(std::sync::atomic::Ordering::SeqCst);
|
||||||
if !point.on_point.read().await.contains_key(&player_team_u8) {
|
if !point.on_point.read().await.contains_key(&player_team_u8) {
|
||||||
point.on_point.write().await.insert(player_team_u8, std::sync::atomic::AtomicU8::new(0));
|
point.on_point.write().await.insert(player_team_u8, std::sync::atomic::AtomicU8::new(0));
|
||||||
}
|
}
|
||||||
|
// update counter
|
||||||
|
let old_count = point.on_point.read().await[&player_team_u8].fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||||
if point_team == player_team {
|
if point_team == player_team {
|
||||||
let old_friendlies = point.on_point.read().await[&player_team_u8].fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
let old_friendlies = old_count;
|
||||||
let current_enemies = point.enemies_on_point(player_team_u8).await;
|
let current_enemies = point.enemies_on_point(player_team_u8).await;
|
||||||
if current_enemies != 0 && old_friendlies == 0 {
|
if current_enemies != 0 && old_friendlies == 0 {
|
||||||
generic.broadcast(
|
generic.broadcast(
|
||||||
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
&rlnl::events::ingame::CapturePointNotification {
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
notification: rlnl::types::CapturePointNotificationType::CaptureLocked,
|
notification: rlnl::types::CapturePointNotificationType::CaptureStoppedByDefenders,
|
||||||
id: point_i,
|
id: point_i,
|
||||||
defending_team: point_team,
|
defending_team: point_team,
|
||||||
attacking_team: player_team,
|
attacking_team: player_team,
|
||||||
@@ -227,10 +232,11 @@ impl PointTracker {
|
|||||||
true,
|
true,
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
} else {
|
} else if attacking_team == -1 {
|
||||||
let old_enemies = point.on_point.read().await[&player_team_u8].fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
let old_enemies = old_count;
|
||||||
let current_contesters = point.enemies_on_point(player_team_u8).await;
|
|
||||||
if old_enemies == 0 {
|
if old_enemies == 0 {
|
||||||
|
let current_friendlies = point.owners_on_point().await;
|
||||||
|
point.attackers.store(player_team, std::sync::atomic::Ordering::SeqCst);
|
||||||
generic.broadcast(
|
generic.broadcast(
|
||||||
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
@@ -242,12 +248,12 @@ impl PointTracker {
|
|||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
).await;
|
).await;
|
||||||
if current_contesters != 0 {
|
if current_friendlies != 0 {
|
||||||
generic.broadcast(
|
generic.broadcast(
|
||||||
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
&rlnl::events::ingame::CapturePointNotification {
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
notification: rlnl::types::CapturePointNotificationType::CaptureLocked,
|
notification: rlnl::types::CapturePointNotificationType::CaptureStoppedByDefenders,
|
||||||
id: point_i,
|
id: point_i,
|
||||||
defending_team: point_team,
|
defending_team: point_team,
|
||||||
attacking_team: player_team,
|
attacking_team: player_team,
|
||||||
@@ -256,6 +262,21 @@ impl PointTracker {
|
|||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let old_enemies = old_count;
|
||||||
|
if old_enemies == 0 {
|
||||||
|
generic.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
|
notification: rlnl::types::CapturePointNotificationType::CaptureLocked,
|
||||||
|
id: point_i,
|
||||||
|
defending_team: point_team,
|
||||||
|
attacking_team,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,62 +288,96 @@ impl PointTracker {
|
|||||||
let player_team_u8 = player_team as u8;
|
let player_team_u8 = player_team as u8;
|
||||||
if let Some(point) = self.points.get(point_i as usize) {
|
if let Some(point) = self.points.get(point_i as usize) {
|
||||||
let point_team = point.team.load(std::sync::atomic::Ordering::SeqCst);
|
let point_team = point.team.load(std::sync::atomic::Ordering::SeqCst);
|
||||||
|
let attacking_team = point.attackers.load(std::sync::atomic::Ordering::SeqCst);
|
||||||
if !point.on_point.read().await.contains_key(&player_team_u8) {
|
if !point.on_point.read().await.contains_key(&player_team_u8) {
|
||||||
point.on_point.write().await.insert(player_team_u8, std::sync::atomic::AtomicU8::new(0));
|
point.on_point.write().await.insert(player_team_u8, std::sync::atomic::AtomicU8::new(0));
|
||||||
}
|
}
|
||||||
|
// update counter
|
||||||
|
let old_count = point.on_point.read().await[&player_team_u8].fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
if old_count == 0 {
|
||||||
|
// something is out of sync, let's just ignore it and try to undo any underflow
|
||||||
|
log::warn!("Team {} players on point {} counting error", player_team, point_i);
|
||||||
|
point.on_point.read().await[&player_team_u8].store(0, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if point_team == player_team {
|
if point_team == player_team {
|
||||||
let old_friendlies = point.on_point.read().await[&player_team_u8].fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
|
let old_friendlies = old_count;
|
||||||
let current_enemies = point.enemies_on_point(player_team_u8).await;
|
let current_enemies = point.enemies_on_point(player_team_u8).await;
|
||||||
if old_friendlies == 0 {
|
if old_friendlies == 1 && current_enemies != 0 {
|
||||||
// something is out of sync, let's just ignore it and try to undo any underflow
|
|
||||||
log::warn!("Team {} players on point {} counting error", player_team, point_i);
|
|
||||||
point.on_point.read().await[&player_team_u8].store(0, std::sync::atomic::Ordering::SeqCst);
|
|
||||||
} else if old_friendlies == 1 && current_enemies != 0 {
|
|
||||||
generic.broadcast(
|
generic.broadcast(
|
||||||
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
&rlnl::events::ingame::CapturePointNotification {
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
notification: rlnl::types::CapturePointNotificationType::CaptureUnlocked,
|
notification: rlnl::types::CapturePointNotificationType::CaptureStarted,
|
||||||
id: point_i,
|
id: point_i,
|
||||||
defending_team: point_team,
|
defending_team: point_team,
|
||||||
attacking_team: player_team,
|
attacking_team,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let old_enemies = point.on_point.read().await[&player_team_u8].fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
|
let old_enemies = old_count;
|
||||||
|
//let other_enemies = point.enemies_on_point(player_team_u8).await;
|
||||||
//let current_friendlies = point.friendlies.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
//let current_friendlies = point.friendlies.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||||
if old_enemies == 0 {
|
if old_enemies == 1 {
|
||||||
// something is out of sync, let's just ignore it and try to undo any underflow
|
|
||||||
log::warn!("Team {} players on point {} counting error", player_team, point_i);
|
|
||||||
point.on_point.read().await[&player_team_u8].store(0, std::sync::atomic::Ordering::SeqCst);
|
|
||||||
} else if old_enemies == 1 {
|
|
||||||
//log::info!("Enemy has left the capture point");
|
//log::info!("Enemy has left the capture point");
|
||||||
generic.broadcast(
|
// check if there's another team attacking the point
|
||||||
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
if let Some(new_attackers) = point.stealers_team().await {
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
let new_attackers = new_attackers as i8;
|
||||||
&rlnl::events::ingame::CapturePointNotification {
|
// there is another attacking team; continue capture with them
|
||||||
notification: rlnl::types::CapturePointNotificationType::CaptureStoppedNoAttackers,
|
//let new_enemies = point.on_point.read().await[&new_attackers].load(std::sync::atomic::Ordering::SeqCst);
|
||||||
id: point_i,
|
if attacking_team == new_attackers {
|
||||||
defending_team: point_team,
|
log::info!("Player {} stopped capturing point {}, resuming team {} capturing", _player_id, point_i, attacking_team);
|
||||||
attacking_team: player_team,
|
} else {
|
||||||
},
|
log::info!("Player {} stopped capturing point {}, switching to team {} capturing", _player_id, point_i, new_attackers);
|
||||||
true,
|
point.attackers.store(new_attackers, std::sync::atomic::Ordering::SeqCst);
|
||||||
).await;
|
}
|
||||||
let progress_now = point.capture.load(std::sync::atomic::Ordering::SeqCst).floor();
|
generic.broadcast(
|
||||||
point.capture.store(progress_now, std::sync::atomic::Ordering::SeqCst);
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
let data = rlnl::events::ingame::TeamBaseState {
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
base_team_or_mining_point_index: point_i,
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
current_progress: rlnl::types::ByteFloat::from(progress_now),
|
notification: rlnl::types::CapturePointNotificationType::CaptureStarted,
|
||||||
max_progress: rlnl::types::ByteFloat::from(max_progress),
|
id: point_i,
|
||||||
};
|
defending_team: point_team,
|
||||||
generic.broadcast(
|
attacking_team: new_attackers,
|
||||||
rlnl::event_code::NetworkEvent::CapturePointProgress,
|
},
|
||||||
literustlib::packet::Property::ReliableOrdered,
|
true,
|
||||||
&data,
|
).await;
|
||||||
true
|
} else if attacking_team == player_team {
|
||||||
).await;
|
// NOTE: this assumes there are only two teams, so if the attacking team leaves
|
||||||
|
// there will only be one team at most left on the point (which will become the new capturing team)
|
||||||
|
// stealers_team() returns None for 2 teams or 0 teams, so both cases would take this branch
|
||||||
|
log::info!("Player {} stopped capturing point {}, no other attacking team", _player_id, point_i);
|
||||||
|
// no more attackers; capture has stopped
|
||||||
|
point.attackers.store(-1, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
generic.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::CapturePointNotification,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&rlnl::events::ingame::CapturePointNotification {
|
||||||
|
notification: rlnl::types::CapturePointNotificationType::CaptureStoppedNoAttackers,
|
||||||
|
id: point_i,
|
||||||
|
defending_team: point_team,
|
||||||
|
attacking_team: player_team,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
let progress_now = point.capture.load(std::sync::atomic::Ordering::SeqCst).floor();
|
||||||
|
point.capture.store(progress_now, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
let data = rlnl::events::ingame::TeamBaseState {
|
||||||
|
base_team_or_mining_point_index: point_i,
|
||||||
|
current_progress: rlnl::types::ByteFloat::from(progress_now),
|
||||||
|
max_progress: rlnl::types::ByteFloat::from(max_progress),
|
||||||
|
};
|
||||||
|
generic.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::CapturePointProgress,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&data,
|
||||||
|
true
|
||||||
|
).await;
|
||||||
|
} else {
|
||||||
|
log::info!("Player {} left point {}, not attacking nor defending!??", _player_id, point_i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,6 +418,7 @@ impl PointTracker {
|
|||||||
log::info!("Point {} was captured by team {} in game {}", i, new_team, generic.game_guid());
|
log::info!("Point {} was captured by team {} in game {}", i, new_team, generic.game_guid());
|
||||||
cap_point.capture.store(0.0, std::sync::atomic::Ordering::SeqCst);
|
cap_point.capture.store(0.0, std::sync::atomic::Ordering::SeqCst);
|
||||||
cap_point.team.store(new_team, std::sync::atomic::Ordering::SeqCst);
|
cap_point.team.store(new_team, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
cap_point.attackers.store(-1, std::sync::atomic::Ordering::SeqCst);
|
||||||
self.last_capture_team.store(stealing_team, std::sync::atomic::Ordering::Relaxed);
|
self.last_capture_team.store(stealing_team, std::sync::atomic::Ordering::Relaxed);
|
||||||
self.last_capture_time.store(chrono::Utc::now().timestamp(), std::sync::atomic::Ordering::Relaxed);
|
self.last_capture_time.store(chrono::Utc::now().timestamp(), std::sync::atomic::Ordering::Relaxed);
|
||||||
if owned_points.get(&(new_team as u8)).copied().unwrap_or(0) == 0 {
|
if owned_points.get(&(new_team as u8)).copied().unwrap_or(0) == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user