Skip to content

Commit

Permalink
Lock plugin mutex later
Browse files Browse the repository at this point in the history
  • Loading branch information
Zerthox committed Jun 1, 2023
1 parent 126657c commit 145e0e9
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 51 deletions.
38 changes: 9 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@ use arcdps::{
imgui::Ui,
Agent, CombatEvent,
};
use once_cell::sync::Lazy;
use plugin::Plugin;
use std::sync::Mutex;

/// Main plugin instance.
// FIXME: a single mutex for the whole thing is potentially inefficient
static PLUGIN: Lazy<Mutex<Plugin>> = Lazy::new(|| Mutex::new(Plugin::new()));

// create exports for arcdps
arcdps::export! {
Expand All @@ -41,12 +35,12 @@ arcdps::export! {

fn init() -> Result<(), String> {
// TODO: use error
PLUGIN.lock().unwrap().load();
Plugin::lock().load();
Ok(())
}

fn release() {
PLUGIN.lock().unwrap().unload()
Plugin::lock().unload()
}

fn combat(
Expand All @@ -57,43 +51,29 @@ fn combat(
id: u64,
revision: u64,
) {
// TODO: put relevant event information in priority queue, update state in worker thread?
// or split into important (buff initial), unimportant (encounter start) and last seen time (atomic)
PLUGIN
.lock()
.unwrap()
.area_event(event, src, dest, skill_name, id, revision)
Plugin::area_event(event, src, dest, skill_name, id, revision)
}

fn imgui(ui: &Ui, not_loading_or_character_selection: bool) {
PLUGIN
.lock()
.unwrap()
.render_windows(ui, not_loading_or_character_selection)
Plugin::lock().render_windows(ui, not_loading_or_character_selection)
}

fn options_windows(ui: &Ui, window_name: Option<&str>) -> bool {
PLUGIN
.lock()
.unwrap()
.render_window_options(ui, window_name)
Plugin::render_window_options(ui, window_name)
}

fn options_end(ui: &Ui) {
PLUGIN.lock().unwrap().render_settings(ui)
Plugin::lock().render_settings(ui)
}

fn wnd_filter(key: usize, key_down: bool, prev_key_down: bool) -> bool {
PLUGIN
.lock()
.unwrap()
.key_event(key, key_down, prev_key_down)
Plugin::key_event(key, key_down, prev_key_down)
}

fn extras_init(addon_info: ExtrasAddonInfo, account_name: Option<&str>) {
PLUGIN.lock().unwrap().extras_init(addon_info, account_name)
Plugin::lock().extras_init(addon_info, account_name)
}

fn extras_squad_update(users: UserInfoIter) {
PLUGIN.lock().unwrap().extras_squad_update(users)
Plugin::lock().extras_squad_update(users)
}
41 changes: 26 additions & 15 deletions src/plugin/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,55 +13,62 @@ use log::{debug, info, log_enabled, Level};
impl Plugin {
/// Handles a combat event from area stats.
pub fn area_event(
&mut self,
event: Option<CombatEvent>,
src: Option<Agent>,
dst: Option<Agent>,
skill_name: Option<&str>,
event_id: u64,
_revision: u64,
) {
// TODO: put relevant event information in priority queue, update state in worker thread?
// or split into important (buff initial), unimportant (encounter start) and last seen time (atomic)

// ignore events without source
if let Some(src) = src {
// check for combat event
if let Some(event) = event {
match event.is_statechange {
StateChange::LogStart => {
let mut guard = Self::lock();
let plugin = guard.as_mut();
let target_id = event.src_agent;
if log_enabled!(Level::Debug) {
let delta = calc_delta(&event);
debug!("Log for id {} started with {:?} delta", target_id, delta);
}

// change buffs to none, initial buffs should be reported right after
for entry in self.tracker.players.iter_mut() {
for entry in plugin.tracker.players.iter_mut() {
entry.data.unset_to_none(
event.time,
self.reminder.all_custom().iter().map(|remind| remind.id),
plugin.reminder.all_custom().iter().map(|remind| remind.id),
);
}

// refresh if food or util sorting
self.tracker.refresh_sort_if(Sorting::Food);
self.tracker.refresh_sort_if(Sorting::Util);
plugin.tracker.refresh_sort_if(Sorting::Food);
plugin.tracker.refresh_sort_if(Sorting::Util);

self.reminder.start_encounter(target_id, event.time);
plugin.reminder.start_encounter(target_id, event.time);
}

StateChange::LogNPCUpdate => {
let mut plugin = Self::lock();
let target_id = event.src_agent;
debug!(
"Log changed from {:?} to id {}",
self.reminder.current_encounter(),
plugin.reminder.current_encounter(),
target_id
);
self.reminder.change_encounter(target_id, event.time);
plugin.reminder.change_encounter(target_id, event.time);
}

StateChange::LogEnd => {
let mut guard = Self::lock();
let plugin = guard.as_mut();
let target_id = event.src_agent;
debug!("Log for id {} ended", target_id);
self.reminder.end_encounter(&self.tracker.players);
plugin.reminder.end_encounter(&plugin.tracker.players);
}

StateChange::None | StateChange::ApiDelayed | StateChange::BuffInitial => {
Expand All @@ -70,7 +77,7 @@ impl Plugin {
BuffRemove::None => {
if event.buff != 0 && event.buff_dmg == 0 {
if let Some(dst) = dst {
self.buff_apply(
Self::lock().buff_apply(
dst.id,
event.skill_id,
skill_name,
Expand All @@ -82,7 +89,7 @@ impl Plugin {
}

// remove on all or single manual
BuffRemove::All | BuffRemove::Manual => self.buff_remove(
BuffRemove::All | BuffRemove::Manual => Self::lock().buff_remove(
src.id,
event.skill_id,
skill_name,
Expand All @@ -99,22 +106,26 @@ impl Plugin {

// buff initial events will happen at the start
if event.is_statechange != StateChange::BuffInitial {
self.reminder
.update_pending_check(&self.tracker.players, event.time);
let mut guard = Self::lock();
let plugin = guard.as_mut();
plugin
.reminder
.update_pending_check(&plugin.tracker.players, event.time);
}
} else {
// check for player tracking change
if src.elite == 0 {
let mut plugin = Self::lock();
if src.prof != 0 {
// add player
if let Some(player) =
dst.and_then(|dst| Player::from_tracking_change(src, dst))
{
self.tracker.add_player(player);
plugin.tracker.add_player(player);
}
} else {
// remove player
self.tracker.remove_player(src.id);
plugin.tracker.remove_player(src.id);
}
}
}
Expand Down
18 changes: 17 additions & 1 deletion src/plugin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ use arc_util::{
ui::{Window, WindowOptions},
};
use log::{info, warn};
use once_cell::sync::Lazy;
use semver::Version;
use std::fs;
use std::sync::Mutex;
use std::{fs, sync::MutexGuard};

#[cfg(feature = "demo")]
use crate::demo::Demo;
Expand All @@ -26,6 +28,10 @@ const SETTINGS_FILE: &str = "arcdps_food_reminder.json";
/// Definitions file name.
const DEFINITIONS_FILE: &str = "arcdps_food_reminder_definitions.json";

/// Main plugin instance.
// FIXME: a single mutex for the whole thing is potentially inefficient
static PLUGIN: Lazy<Mutex<Plugin>> = Lazy::new(|| Mutex::new(Plugin::new()));

/// Main plugin.
#[derive(Debug)]
pub struct Plugin {
Expand Down Expand Up @@ -82,6 +88,16 @@ impl Plugin {
}
}

/// Acquires access to the plugin instance.
pub fn lock() -> MutexGuard<'static, Self> {
PLUGIN.lock().unwrap()
}

/// Helper to convert [`MutexGuard`] to a mutable [`Plugin`] reference.
pub fn as_mut(&mut self) -> &mut Self {
self
}

/// Loads the plugin.
pub fn load(&mut self) {
// TODO: update notification
Expand Down
14 changes: 8 additions & 6 deletions src/plugin/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,23 +259,25 @@ impl Plugin {
}

/// Callback for ArcDPS option checkboxes.
pub fn render_window_options(&mut self, ui: &Ui, option_name: Option<&str>) -> bool {
pub fn render_window_options(ui: &Ui, option_name: Option<&str>) -> bool {
if option_name.is_none() {
ui.checkbox("Food Tracker", self.tracker.visible_mut());
let mut plugin = Self::lock();
ui.checkbox("Food Tracker", plugin.tracker.visible_mut());

#[cfg(feature = "demo")]
ui.checkbox("Food Demo", self.demo.visible_mut());
ui.checkbox("Food Demo", plugin.demo.visible_mut());
}
false
}

/// Handles a key event.
pub fn key_event(&mut self, key: usize, down: bool, prev_down: bool) -> bool {
pub fn key_event(key: usize, down: bool, prev_down: bool) -> bool {
// check for down
if down && !prev_down {
// check for hotkeys
if matches!(self.tracker.settings.hotkey, Some(hotkey) if hotkey as usize == key) {
self.tracker.toggle_visibility();
let mut plugin = Self::lock();
if matches!(plugin.tracker.settings.hotkey, Some(hotkey) if hotkey as usize == key) {
plugin.tracker.toggle_visibility();
return false;
}
}
Expand Down

0 comments on commit 145e0e9

Please sign in to comment.