mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Add basic stats tracking #30
This commit is contained in:
@@ -479,7 +479,7 @@ fn default_rotation() -> GameEventSequence {
|
|||||||
|
|
||||||
fn default_multiplayer() -> super::MultiplayerConfig {
|
fn default_multiplayer() -> super::MultiplayerConfig {
|
||||||
super::MultiplayerConfig {
|
super::MultiplayerConfig {
|
||||||
players_per_game: 1,
|
players_per_game: 2,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
network: super::multiplayer::default_net_conf(),
|
network: super::multiplayer::default_net_conf(),
|
||||||
}
|
}
|
||||||
|
|||||||
31
rc_multiplayer/src/events/assist_bonus.rs
Normal file
31
rc_multiplayer/src/events/assist_bonus.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
pub struct AssistBonus {
|
||||||
|
msg_router: tokio::sync::mpsc::Sender<crate::matches::GameMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::SimpleRlnl<rlnl::events::ingame::AssistBonus, AssistBonus> {
|
||||||
|
crate::handlers::SimpleRlnl::new(AssistBonus::new(init_ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AssistBonus {
|
||||||
|
fn new(init_ctx: &crate::InitConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_router: init_ctx.matches_chann.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl crate::handlers::RlnlEventCodeHandler for AssistBonus {
|
||||||
|
type In = rlnl::events::ingame::AssistBonus;
|
||||||
|
const CODE: rlnl::event_code::NetworkEvent = rlnl::event_code::NetworkEvent::AssistBonusRequest;
|
||||||
|
|
||||||
|
async fn handle(&self, data: Self::In, _peer: &std::sync::Arc<literustlib_server::Connection<crate::PacketData>>, user: &crate::UserData, _sender: &std::sync::Arc<literustlib_server::DataSender<crate::PacketData>>) {
|
||||||
|
if let Some(user_info) = user.user().await {
|
||||||
|
super::log_channel_send_failure(self.msg_router.send(crate::matches::GameMessage::AssistBonus {
|
||||||
|
user_id: user_info.user_id(),
|
||||||
|
shootee: data.requester_player_id as u8,
|
||||||
|
shooters: data.player_ids.into_iter().map(|x| x.player).collect(),
|
||||||
|
}).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
rc_multiplayer/src/events/damage_bonus.rs
Normal file
30
rc_multiplayer/src/events/damage_bonus.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
pub struct DamageBonus {
|
||||||
|
msg_router: tokio::sync::mpsc::Sender<crate::matches::GameMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::SimpleRlnl<rlnl::events::ingame::DestroyedHealedCubesBonus, DamageBonus> {
|
||||||
|
crate::handlers::SimpleRlnl::new(DamageBonus::new(init_ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DamageBonus {
|
||||||
|
fn new(init_ctx: &crate::InitConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_router: init_ctx.matches_chann.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl crate::handlers::RlnlEventCodeHandler for DamageBonus {
|
||||||
|
type In = rlnl::events::ingame::DestroyedHealedCubesBonus;
|
||||||
|
const CODE: rlnl::event_code::NetworkEvent = rlnl::event_code::NetworkEvent::DestroyCubesBonusRequest;
|
||||||
|
|
||||||
|
async fn handle(&self, data: Self::In, _peer: &std::sync::Arc<literustlib_server::Connection<crate::PacketData>>, user: &crate::UserData, _sender: &std::sync::Arc<literustlib_server::DataSender<crate::PacketData>>) {
|
||||||
|
if let Some(user_info) = user.user().await {
|
||||||
|
super::log_channel_send_failure(self.msg_router.send(crate::matches::GameMessage::DestroyCubesBonus {
|
||||||
|
user_id: user_info.user_id(),
|
||||||
|
info: data,
|
||||||
|
}).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
rc_multiplayer/src/events/heal_bonus.rs
Normal file
30
rc_multiplayer/src/events/heal_bonus.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
pub struct HealBonus {
|
||||||
|
msg_router: tokio::sync::mpsc::Sender<crate::matches::GameMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::SimpleRlnl<rlnl::events::ingame::DestroyedHealedCubesBonus, HealBonus> {
|
||||||
|
crate::handlers::SimpleRlnl::new(HealBonus::new(init_ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HealBonus {
|
||||||
|
fn new(init_ctx: &crate::InitConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_router: init_ctx.matches_chann.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl crate::handlers::RlnlEventCodeHandler for HealBonus {
|
||||||
|
type In = rlnl::events::ingame::DestroyedHealedCubesBonus;
|
||||||
|
const CODE: rlnl::event_code::NetworkEvent = rlnl::event_code::NetworkEvent::HealCubesBonusRequest;
|
||||||
|
|
||||||
|
async fn handle(&self, data: Self::In, _peer: &std::sync::Arc<literustlib_server::Connection<crate::PacketData>>, user: &crate::UserData, _sender: &std::sync::Arc<literustlib_server::DataSender<crate::PacketData>>) {
|
||||||
|
if let Some(user_info) = user.user().await {
|
||||||
|
super::log_channel_send_failure(self.msg_router.send(crate::matches::GameMessage::DestroyCubesBonus {
|
||||||
|
user_id: user_info.user_id(),
|
||||||
|
info: data,
|
||||||
|
}).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
rc_multiplayer/src/events/kill_bonus.rs
Normal file
31
rc_multiplayer/src/events/kill_bonus.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
pub struct KillEnemyBonus {
|
||||||
|
msg_router: tokio::sync::mpsc::Sender<crate::matches::GameMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::SimpleRlnl<rlnl::events::ingame::Kill, KillEnemyBonus> {
|
||||||
|
crate::handlers::SimpleRlnl::new(KillEnemyBonus::new(init_ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KillEnemyBonus {
|
||||||
|
fn new(init_ctx: &crate::InitConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_router: init_ctx.matches_chann.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl crate::handlers::RlnlEventCodeHandler for KillEnemyBonus {
|
||||||
|
type In = rlnl::events::ingame::Kill;
|
||||||
|
const CODE: rlnl::event_code::NetworkEvent = rlnl::event_code::NetworkEvent::KillBonusRequest;
|
||||||
|
|
||||||
|
async fn handle(&self, data: Self::In, _peer: &std::sync::Arc<literustlib_server::Connection<crate::PacketData>>, user: &crate::UserData, _sender: &std::sync::Arc<literustlib_server::DataSender<crate::PacketData>>) {
|
||||||
|
if let Some(user_info) = user.user().await {
|
||||||
|
super::log_channel_send_failure(self.msg_router.send(crate::matches::GameMessage::KillBonus {
|
||||||
|
user_id: user_info.user_id(),
|
||||||
|
shootee: data.killee_player_id,
|
||||||
|
shooter: data.killer_player_id,
|
||||||
|
}).await);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,10 @@ mod client_unregister;
|
|||||||
mod flipper_start;
|
mod flipper_start;
|
||||||
mod self_destruct_elimination;
|
mod self_destruct_elimination;
|
||||||
mod map_ping;
|
mod map_ping;
|
||||||
|
mod kill_bonus;
|
||||||
|
mod assist_bonus;
|
||||||
|
mod damage_bonus;
|
||||||
|
mod heal_bonus;
|
||||||
|
|
||||||
pub async fn handler(init_ctx: &crate::InitConfig) -> crate::handler::LnlEventHandler {
|
pub async fn handler(init_ctx: &crate::InitConfig) -> crate::handler::LnlEventHandler {
|
||||||
crate::handler::LnlEventHandler::new(init_ctx.users.clone(), crate::vehicle_motion::handler(init_ctx))
|
crate::handler::LnlEventHandler::new(init_ctx.users.clone(), crate::vehicle_motion::handler(init_ctx))
|
||||||
@@ -79,10 +83,8 @@ pub async fn handler(init_ctx: &crate::InitConfig) -> crate::handler::LnlEventHa
|
|||||||
{literustlib::packet::Property::Unreliable as u8},
|
{literustlib::packet::Property::Unreliable as u8},
|
||||||
rlnl::events::ingame::DestroyCubeEffectOnly,
|
rlnl::events::ingame::DestroyCubeEffectOnly,
|
||||||
>::handler(init_ctx))
|
>::handler(init_ctx))
|
||||||
.add(crate::handlers::Stub::<
|
.add(damage_bonus::handler(init_ctx))
|
||||||
{rlnl::event_code::NetworkEvent::DestroyCubesBonusRequest as i16},
|
.add(heal_bonus::handler(init_ctx))
|
||||||
rlnl::events::ingame::DestroyedHealedCubesBonus,
|
|
||||||
>::handler(init_ctx))
|
|
||||||
.add(crate::handlers::Broadcaster::<
|
.add(crate::handlers::Broadcaster::<
|
||||||
false,
|
false,
|
||||||
{rlnl::event_code::NetworkEvent::HealSelf as i16},
|
{rlnl::event_code::NetworkEvent::HealSelf as i16},
|
||||||
@@ -90,10 +92,8 @@ pub async fn handler(init_ctx: &crate::InitConfig) -> crate::handler::LnlEventHa
|
|||||||
{literustlib::packet::Property::ReliableOrdered as u8},
|
{literustlib::packet::Property::ReliableOrdered as u8},
|
||||||
rlnl::events::HealedCubes,
|
rlnl::events::HealedCubes,
|
||||||
>::handler(init_ctx))
|
>::handler(init_ctx))
|
||||||
.add(crate::handlers::Stub::<
|
.add(kill_bonus::handler(init_ctx))
|
||||||
{rlnl::event_code::NetworkEvent::KillBonusRequest as i16},
|
.add(assist_bonus::handler(init_ctx))
|
||||||
rlnl::events::ingame::Kill, // FIXME this is not a player ID -- it's actually sending 2 bytes not 1
|
|
||||||
>::handler(init_ctx))
|
|
||||||
.add(kill_player::handler(init_ctx))
|
.add(kill_player::handler(init_ctx))
|
||||||
.add(crate::handlers::Broadcaster::<
|
.add(crate::handlers::Broadcaster::<
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ mod ingame_broadcast_dataless;
|
|||||||
pub use ingame_broadcast_dataless::DatalessBroadcaster;
|
pub use ingame_broadcast_dataless::DatalessBroadcaster;
|
||||||
|
|
||||||
mod stub;
|
mod stub;
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use stub::Stub;
|
pub use stub::Stub;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ pub struct Stub<const CODE_IN: i16, In: byteserde::des_slice::ByteDeserializeSli
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl <const CODE_IN: i16, In: byteserde::des_slice::ByteDeserializeSlice<In> + Send + Sync + 'static> Stub<CODE_IN, In> {
|
impl <const CODE_IN: i16, In: byteserde::des_slice::ByteDeserializeSlice<In> + Send + Sync + 'static> Stub<CODE_IN, In> {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::simple_typed::SimpleRlnl<In, Self> {
|
pub fn handler(init_ctx: &crate::InitConfig) -> crate::handlers::simple_typed::SimpleRlnl<In, Self> {
|
||||||
crate::handlers::simple_typed::SimpleRlnl::new(Stub::new(init_ctx))
|
crate::handlers::simple_typed::SimpleRlnl::new(Stub::new(init_ctx))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ pub(super) struct UserConnection {
|
|||||||
pub(super) state: std::sync::Arc<UserState>,
|
pub(super) state: std::sync::Arc<UserState>,
|
||||||
pub(super) machine: MachineState,
|
pub(super) machine: MachineState,
|
||||||
pub(super) descriptor: oj_rc_core::persist::user::PlayerDescriptor,
|
pub(super) descriptor: oj_rc_core::persist::user::PlayerDescriptor,
|
||||||
|
pub(super) counters: UserData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -76,6 +77,57 @@ impl Location {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) struct UserData {
|
||||||
|
pub kills: std::sync::atomic::AtomicU32,
|
||||||
|
pub deaths: std::sync::atomic::AtomicU32,
|
||||||
|
pub assists: std::sync::atomic::AtomicU32,
|
||||||
|
pub healed: std::sync::atomic::AtomicU32,
|
||||||
|
pub received_healed: std::sync::atomic::AtomicU32,
|
||||||
|
pub cubes: std::sync::atomic::AtomicU32,
|
||||||
|
pub received_cubes: std::sync::atomic::AtomicU32, // damage taken
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
kills: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
deaths: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
assists: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
healed: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
received_healed: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
cubes: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
received_cubes: std::sync::atomic::AtomicU32::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn generic_score(&self) -> u32 {
|
||||||
|
self.kills.load(std::sync::atomic::Ordering::Relaxed) * 1_000
|
||||||
|
+ self.assists.load(std::sync::atomic::Ordering::Relaxed) * 100
|
||||||
|
+ self.healed.load(std::sync::atomic::Ordering::Relaxed)
|
||||||
|
+ self.cubes.load(std::sync::atomic::Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn get_generic_packet(&self, player_id: u8, stat: rlnl::types::IngameStatId, delta: Option<u32>) -> rlnl::events::ingame::UpdateGameStats {
|
||||||
|
let (stat_amount, backup_delta) = match stat {
|
||||||
|
rlnl::types::IngameStatId::DestroyedCubes
|
||||||
|
| rlnl::types::IngameStatId::DestroyedCubesInProtection
|
||||||
|
| rlnl::types::IngameStatId::DestroyedCubesDefendingTheBase => (self.cubes.load(std::sync::atomic::Ordering::SeqCst), 1),
|
||||||
|
rlnl::types::IngameStatId::Kill => (self.kills.load(std::sync::atomic::Ordering::Relaxed), 1_000),
|
||||||
|
rlnl::types::IngameStatId::KillAssist => (self.assists.load(std::sync::atomic::Ordering::Relaxed), 100),
|
||||||
|
rlnl::types::IngameStatId::HealCubes => (self.assists.load(std::sync::atomic::Ordering::SeqCst), 1),
|
||||||
|
rlnl::types::IngameStatId::RobotDestroyed => (self.deaths.load(std::sync::atomic::Ordering::Relaxed), 0),
|
||||||
|
s => panic!("Cannot generate game stat {:?}", s)
|
||||||
|
};
|
||||||
|
rlnl::events::ingame::UpdateGameStats {
|
||||||
|
player_id,
|
||||||
|
stat_id: stat,
|
||||||
|
amount: stat_amount,
|
||||||
|
score: self.generic_score(),
|
||||||
|
delta_score: delta.unwrap_or(backup_delta),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub(super) enum ConnectionMode {
|
pub(super) enum ConnectionMode {
|
||||||
@@ -252,6 +304,7 @@ impl <L: super::CustomGameLogic> GenericGamemodeEngine<L> {
|
|||||||
state: std::sync::Arc::new(UserState::new()),
|
state: std::sync::Arc::new(UserState::new()),
|
||||||
machine: MachineState::new(),
|
machine: MachineState::new(),
|
||||||
descriptor: player_info.to_owned(),
|
descriptor: player_info.to_owned(),
|
||||||
|
counters: UserData::new(),
|
||||||
};
|
};
|
||||||
if self.custom_logic_handler.on_player_join(&self, &new_user, &self.players_info).await {
|
if self.custom_logic_handler.on_player_join(&self, &new_user, &self.players_info).await {
|
||||||
self.spawn_send_loading_events(&new_user, id, self.players_info.clone());
|
self.spawn_send_loading_events(&new_user, id, self.players_info.clone());
|
||||||
@@ -489,7 +542,19 @@ impl <L: super::CustomGameLogic> GenericGamemodeEngine<L> {
|
|||||||
true,
|
true,
|
||||||
).await;
|
).await;
|
||||||
log::info!("Player {} was destroyed by {} ({}) in game {}", remote_player, killer_player, user_id, self.game_guid());
|
log::info!("Player {} was destroyed by {} ({}) in game {}", remote_player, killer_player, user_id, self.game_guid());
|
||||||
self.custom_logic_handler.on_vehicle_destroyed(&self, killer_player, remote_player).await;
|
if self.custom_logic_handler.on_vehicle_destroyed(&self, killer_player, remote_player).await {
|
||||||
|
// the kill tracking is initiated separately by the client with kill bonus event
|
||||||
|
if let Some(killed) = self.users.read().await.get(&remote_player) {
|
||||||
|
killed.counters.deaths.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let data = killed.counters.get_generic_packet(remote_player, rlnl::types::IngameStatId::RobotDestroyed, None);
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
super::GameMessage::SelfDestruct { user_id, is_classic } => {
|
super::GameMessage::SelfDestruct { user_id, is_classic } => {
|
||||||
if let Some(player_id) = self.user_key_by_user_id(user_id).await {
|
if let Some(player_id) = self.user_key_by_user_id(user_id).await {
|
||||||
@@ -520,6 +585,16 @@ impl <L: super::CustomGameLogic> GenericGamemodeEngine<L> {
|
|||||||
conn.connection.connection.disconnect();
|
conn.connection.connection.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(killed) = self.users.read().await.get(&player_id) {
|
||||||
|
killed.counters.deaths.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let data = killed.counters.get_generic_packet(player_id, rlnl::types::IngameStatId::RobotDestroyed, None);
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +621,106 @@ impl <L: super::CustomGameLogic> GenericGamemodeEngine<L> {
|
|||||||
).await);
|
).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
super::GameMessage::KillBonus { user_id: _, shootee, shooter } => {
|
||||||
|
if let Some(to_reward) = self.users.read().await.get(&shooter) {
|
||||||
|
to_reward.counters.kills.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
crate::events::log_lnl_send_failure(to_reward.connection.rlnl().send_data(
|
||||||
|
&rlnl::events::ingame::Kill {
|
||||||
|
killee_player_id: shootee,
|
||||||
|
killer_player_id: shooter,
|
||||||
|
},
|
||||||
|
rlnl::event_code::NetworkEvent::ConfirmedKill,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&to_reward.connection.connection
|
||||||
|
).await);
|
||||||
|
let data = to_reward.counters.get_generic_packet(shooter, rlnl::types::IngameStatId::Kill, None);
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
super::GameMessage::AssistBonus { user_id: _, shootee, shooters } => {
|
||||||
|
let lock = self.users.read().await;
|
||||||
|
for shooter in shooters {
|
||||||
|
if let Some(to_reward) = lock.get(&shooter) {
|
||||||
|
to_reward.counters.assists.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
crate::events::log_lnl_send_failure(to_reward.connection.rlnl().send_data(
|
||||||
|
&rlnl::events::ingame::Kill {
|
||||||
|
killee_player_id: shootee,
|
||||||
|
killer_player_id: shooter,
|
||||||
|
},
|
||||||
|
rlnl::event_code::NetworkEvent::ConfirmedAssist,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&to_reward.connection.connection
|
||||||
|
).await);
|
||||||
|
let data = to_reward.counters.get_generic_packet(shooter, rlnl::types::IngameStatId::KillAssist, None);
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::ReliableOrdered,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
super::GameMessage::DestroyCubesBonus { user_id: _, info } => {
|
||||||
|
let lock = self.users.read().await;
|
||||||
|
for shooter in info.shooters {
|
||||||
|
if let Some(to_reward) = lock.get(&shooter.shooting_player_id) {
|
||||||
|
let mut total_cubes = 0;
|
||||||
|
for target in shooter.shooter_targets {
|
||||||
|
if let Some(to_punish) = lock.get(&target.target_player_id) {
|
||||||
|
let mut total_cubes_received = 0;
|
||||||
|
for cubes in target.cube_amounts {
|
||||||
|
// TODO use cube_id for something!?
|
||||||
|
total_cubes += cubes.cube_count;
|
||||||
|
total_cubes_received += cubes.cube_count;
|
||||||
|
}
|
||||||
|
to_punish.counters.received_cubes.fetch_add(total_cubes_received, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_reward.counters.cubes.fetch_add(total_cubes, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
let data = to_reward.counters.get_generic_packet(shooter.shooting_player_id, rlnl::types::IngameStatId::DestroyedCubes, Some(total_cubes));
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::Unreliable,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
super::GameMessage::HealCubesBonus { user_id: _, info } => {
|
||||||
|
let lock = self.users.read().await;
|
||||||
|
for shooter in info.shooters {
|
||||||
|
if let Some(to_reward) = lock.get(&shooter.shooting_player_id) {
|
||||||
|
let mut total_cubes = 0;
|
||||||
|
for target in shooter.shooter_targets {
|
||||||
|
if let Some(to_punish) = lock.get(&target.target_player_id) {
|
||||||
|
let mut total_cubes_received = 0;
|
||||||
|
for cubes in target.cube_amounts {
|
||||||
|
// TODO use cube_id for something!?
|
||||||
|
total_cubes += cubes.cube_count;
|
||||||
|
total_cubes_received += cubes.cube_count;
|
||||||
|
}
|
||||||
|
to_punish.counters.received_healed.fetch_add(total_cubes_received, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_reward.counters.healed.fetch_add(total_cubes, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
let data = to_reward.counters.get_generic_packet(shooter.shooting_player_id, rlnl::types::IngameStatId::HealCubes, Some(total_cubes));
|
||||||
|
self.broadcast(
|
||||||
|
rlnl::event_code::NetworkEvent::UpdateGameStats,
|
||||||
|
literustlib::packet::Property::Unreliable,
|
||||||
|
&data,
|
||||||
|
true,
|
||||||
|
).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
super::GameMessage::BroadcastRlnl { user_id, event, event_in, property, data } => {
|
super::GameMessage::BroadcastRlnl { user_id, event, event_in, property, data } => {
|
||||||
if self.custom_logic_handler.on_broadcast(&self, user_id, event, event_in, property, &data, false).await {
|
if self.custom_logic_handler.on_broadcast(&self, user_id, event, event_in, property, &data, false).await {
|
||||||
if let Some(data) = data {
|
if let Some(data) = data {
|
||||||
|
|||||||
@@ -49,6 +49,24 @@ pub enum GameMessage {
|
|||||||
user_id: i32,
|
user_id: i32,
|
||||||
ping: rlnl::events::ingame::MapPing,
|
ping: rlnl::events::ingame::MapPing,
|
||||||
},
|
},
|
||||||
|
KillBonus {
|
||||||
|
user_id: i32,
|
||||||
|
shootee: u8,
|
||||||
|
shooter: u8,
|
||||||
|
},
|
||||||
|
AssistBonus {
|
||||||
|
user_id: i32,
|
||||||
|
shootee: u8,
|
||||||
|
shooters: Vec<u8>,
|
||||||
|
},
|
||||||
|
DestroyCubesBonus {
|
||||||
|
user_id: i32,
|
||||||
|
info: rlnl::events::ingame::DestroyedHealedCubesBonus,
|
||||||
|
},
|
||||||
|
HealCubesBonus {
|
||||||
|
user_id: i32,
|
||||||
|
info: rlnl::events::ingame::DestroyedHealedCubesBonus,
|
||||||
|
},
|
||||||
BroadcastRlnl {
|
BroadcastRlnl {
|
||||||
user_id: i32,
|
user_id: i32,
|
||||||
event: rlnl::event_code::NetworkEvent,
|
event: rlnl::event_code::NetworkEvent,
|
||||||
@@ -87,6 +105,10 @@ impl GameMessage {
|
|||||||
Self::SelfDestruct { user_id, .. } => *user_id,
|
Self::SelfDestruct { user_id, .. } => *user_id,
|
||||||
Self::FlippingStarted { user_id, .. } => *user_id,
|
Self::FlippingStarted { user_id, .. } => *user_id,
|
||||||
Self::MapPing { user_id, .. } => *user_id,
|
Self::MapPing { user_id, .. } => *user_id,
|
||||||
|
Self::KillBonus { user_id, .. } => *user_id,
|
||||||
|
Self::AssistBonus { user_id, .. } => *user_id,
|
||||||
|
Self::DestroyCubesBonus { user_id, .. } => *user_id,
|
||||||
|
Self::HealCubesBonus { user_id, .. } => *user_id,
|
||||||
Self::BroadcastRlnl { user_id, .. } => *user_id,
|
Self::BroadcastRlnl { user_id, .. } => *user_id,
|
||||||
Self::RebroadcastRlnl { skip_user_id, .. } => *skip_user_id,
|
Self::RebroadcastRlnl { skip_user_id, .. } => *skip_user_id,
|
||||||
Self::Motion { user_id, .. } => *user_id,
|
Self::Motion { user_id, .. } => *user_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user