Refactor multiple Heimdall modules to use class-based structure for improved organization and clarity

This commit is contained in:
2025-05-18 12:31:26 +02:00
parent 017cbf01f8
commit 565db30125
11 changed files with 2004 additions and 1929 deletions

View File

@@ -352,7 +352,7 @@ shared.Commander = {
enabled enabled
and ( and (
not command.commanderOnly not command.commanderOnly
-- if Heimdall_Data.config.commander.debug then print(string.format("[%s] Ignoring command, sender %s not commander %s", ModuleName, sender, Heimdall_Data.config.commander.commander)) end -- if Heimdall_Data.config.commander.debug then print(string.format("[%s] Ignoring command, sender %s not commander %s", ModuleName, sender, Heimdall_Data.config.commander.commander)) end
or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander) or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander)

View File

@@ -1,5 +1,6 @@
local _, shared = ... local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "Inviter"
---@class HeimdallInviterConfig ---@class HeimdallInviterConfig
---@field enabled boolean ---@field enabled boolean
@@ -14,8 +15,6 @@ local _, shared = ...
---@field afkThreshold number ---@field afkThreshold number
---@field listeningChannel table<string, boolean> ---@field listeningChannel table<string, boolean>
local ModuleName = "Inviter"
---@class Inviter ---@class Inviter
shared.Inviter = { shared.Inviter = {
Init = function() Init = function()

View File

@@ -1,13 +1,12 @@
local _, shared = ... local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "Macroer"
---@class HeimdallMacroerConfig ---@class HeimdallMacroerConfig
---@field enabled boolean ---@field enabled boolean
---@field debug boolean ---@field debug boolean
---@field priority string[] ---@field priority string[]
local ModuleName = "Macroer"
---@class Macroer ---@class Macroer
shared.Macroer = { shared.Macroer = {
Init = function() Init = function()

View File

@@ -2,175 +2,184 @@ local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "Messenger" local ModuleName = "Messenger"
---@diagnostic disable-next-line: missing-fields ---@class Message
shared.Messenger = {} ---@field message string
function shared.Messenger.Init() ---@field channel string
---@class Message ---@field data string
---@field message string
---@field channel string
---@field data string
local function FindOrJoinChannel(channelName, password) ---@class Messenger
local channelId = GetChannelName(channelName) shared.Messenger = {
if channelId == 0 then Init = function()
if Heimdall_Data.config.messenger.debug then local function FindOrJoinChannel(channelName, password)
print(string.format("[%s] Channel not found, joining: %s", ModuleName, channelName)) local channelId = GetChannelName(channelName)
end if channelId == 0 then
if password then
JoinPermanentChannel(channelName, password)
else
JoinPermanentChannel(channelName)
end
end
channelId = GetChannelName(channelName)
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Channel found with ID: %s (%s)", ModuleName, channelId, channelName))
end
return channelId
end
---@diagnostic disable-next-line: missing-fields
if not shared.messenger then shared.messenger = {} end
if not shared.messenger.queue then shared.messenger.queue = {} end
if not shared.messenger.ticker then
local function DoMessage()
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Processing message queue - Size: %d", ModuleName, #shared.messenger.queue))
end
if not Heimdall_Data.config.messenger.enabled then
if Heimdall_Data.config.messenger.debug then if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Module disabled, skipping message processing", ModuleName)) print(string.format("[%s] Channel not found, joining: %s", ModuleName, channelName))
end end
return if password then
end JoinPermanentChannel(channelName, password)
else
---@type Message JoinPermanentChannel(channelName)
local message = shared.messenger.queue[1]
if not message then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Message queue empty", ModuleName))
end end
return
end end
channelId = GetChannelName(channelName)
if Heimdall_Data.config.messenger.debug then if Heimdall_Data.config.messenger.debug then
print( print(string.format("[%s] Channel found with ID: %s (%s)", ModuleName, channelId, channelName))
string.format( end
"[%s] Processing message - Channel: %s, Data: %s", return channelId
ModuleName, end
message.channel or "nil",
message.data or "nil" ---@diagnostic disable-next-line: missing-fields
if not shared.messenger then shared.messenger = {} end
if not shared.messenger.queue then shared.messenger.queue = {} end
if not shared.messenger.ticker then
local function DoMessage()
if Heimdall_Data.config.messenger.debug then
print(
string.format("[%s] Processing message queue - Size: %d", ModuleName, #shared.messenger.queue)
) )
)
print(string.format("[%s] Message content: %s", ModuleName, message.message or "nil"))
end
if not message.message or message.message == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Invalid message: empty content", ModuleName))
end end
return
end
if not message.channel or message.channel == "" then if not Heimdall_Data.config.messenger.enabled then
if Heimdall_Data.config.messenger.debug then if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Invalid message: no channel specified", ModuleName)) print(string.format("[%s] Module disabled, skipping message processing", ModuleName))
end
return
end end
return
end
if string.find(message.channel, "^C") then ---@type Message
if Heimdall_Data.config.messenger.debug then local message = shared.messenger.queue[1]
print(string.format("[%s] Converting channel type from C to CHANNEL", ModuleName)) if not message then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Message queue empty", ModuleName))
end
return
end end
message.channel = "CHANNEL"
elseif string.find(message.channel, "^W") then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Converting channel type from W to WHISPER", ModuleName))
end
message.channel = "WHISPER"
end
if message.channel == "CHANNEL" and message.data and string.match(message.data, "%D") then
if Heimdall_Data.config.messenger.debug then if Heimdall_Data.config.messenger.debug then
print( print(
string.format( string.format(
"[%s] Processing channel message: '%s' to '%s'", "[%s] Processing message - Channel: %s, Data: %s",
ModuleName,
message.channel or "nil",
message.data or "nil"
)
)
print(string.format("[%s] Message content: %s", ModuleName, message.message or "nil"))
end
if not message.message or message.message == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Invalid message: empty content", ModuleName))
end
return
end
if not message.channel or message.channel == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Invalid message: no channel specified", ModuleName))
end
return
end
if string.find(message.channel, "^C") then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Converting channel type from C to CHANNEL", ModuleName))
end
message.channel = "CHANNEL"
elseif string.find(message.channel, "^W") then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Converting channel type from W to WHISPER", ModuleName))
end
message.channel = "WHISPER"
end
if message.channel == "CHANNEL" and message.data and string.match(message.data, "%D") then
if Heimdall_Data.config.messenger.debug then
print(
string.format(
"[%s] Processing channel message: '%s' to '%s'",
ModuleName,
message.message,
message.data
)
)
end
local channelId = GetChannelName(message.data)
if channelId == 0 then
if Heimdall_Data.config.messenger.debug then
print(
string.format(
"[%s] Channel not found, attempting to join: %s",
ModuleName,
message.data
)
)
end
channelId = FindOrJoinChannel(message.data)
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Channel join result - ID: %s", ModuleName, channelId))
end
end
message.data = tostring(channelId)
end
table.remove(shared.messenger.queue, 1)
if not message.message or message.message == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Skipping empty message", ModuleName))
end
return
end
if not message.channel or message.channel == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Skipping message with no channel", ModuleName))
end
return
end
if not message.data or message.data == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Skipping message with no data", ModuleName))
end
return
end
if Heimdall_Data.config.messenger.debug then
print(
string.format(
"[%s] Sending message: '%s' to %s:%s",
ModuleName, ModuleName,
message.message, message.message,
message.channel,
message.data message.data
) )
) )
end end
local channelId = GetChannelName(message.data) if string.len(message.message) > 255 then
if channelId == 0 then print(string.format("[%s] Message too long!!!!: %s", ModuleName, message.message))
if Heimdall_Data.config.messenger.debug then return
print(string.format("[%s] Channel not found, attempting to join: %s", ModuleName, message.data))
end
channelId = FindOrJoinChannel(message.data)
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Channel join result - ID: %s", ModuleName, channelId))
end
end end
message.data = tostring(channelId) SendChatMessage(message.message, message.channel, nil, message.data)
end end
local function Tick()
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Tick - Queue size: %d", ModuleName, #shared.messenger.queue))
end
DoMessage()
shared.messenger.ticker = C_Timer.NewTimer(Heimdall_Data.config.messenger.interval, Tick, 1)
end
Tick()
end
table.remove(shared.messenger.queue, 1) if Heimdall_Data.config.messenger.debug then
if not message.message or message.message == "" then print(
if Heimdall_Data.config.messenger.debug then string.format(
print(string.format("[%s] Skipping empty message", ModuleName)) "[%s] Module initialized with interval: %s",
end ModuleName,
return Heimdall_Data.config.messenger.interval
end
if not message.channel or message.channel == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Skipping message with no channel", ModuleName))
end
return
end
if not message.data or message.data == "" then
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Skipping message with no data", ModuleName))
end
return
end
if Heimdall_Data.config.messenger.debug then
print(
string.format(
"[%s] Sending message: '%s' to %s:%s",
ModuleName,
message.message,
message.channel,
message.data
)
) )
end
if string.len(message.message) > 255 then
print(string.format("[%s] Message too long!!!!: %s", ModuleName, message.message))
return
end
SendChatMessage(message.message, message.channel, nil, message.data)
end
local function Tick()
if Heimdall_Data.config.messenger.debug then
print(string.format("[%s] Tick - Queue size: %d", ModuleName, #shared.messenger.queue))
end
DoMessage()
shared.messenger.ticker = C_Timer.NewTimer(Heimdall_Data.config.messenger.interval, Tick, 1)
end
Tick()
end
if Heimdall_Data.config.messenger.debug then
print(
string.format(
"[%s] Module initialized with interval: %s",
ModuleName,
Heimdall_Data.config.messenger.interval
) )
) end
end print("[Heimdall] Messenger loaded")
print("[Heimdall] Messenger loaded") end,
end }

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ local ModuleName = "Network"
---@class HeimdallNetworkData ---@class HeimdallNetworkData
---@field ticker Timer? ---@field ticker Timer?
---@class Network
shared.Network = { shared.Network = {
Init = function() Init = function()
if not shared.network then shared.network = {} end if not shared.network then shared.network = {} end

View File

@@ -2,182 +2,190 @@ local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "NetworkMessenger" local ModuleName = "NetworkMessenger"
---@diagnostic disable-next-line: missing-fields ---@class NetworkMessenger
shared.NetworkMessenger = {} shared.NetworkMessenger = {
function shared.NetworkMessenger.Init() Init = function()
RegisterAddonMessagePrefix(Heimdall_Data.config.addonPrefix) RegisterAddonMessagePrefix(Heimdall_Data.config.addonPrefix)
if not shared.networkMessenger then shared.networkMessenger = {} end if not shared.networkMessenger then shared.networkMessenger = {} end
if not shared.networkMessenger.queue then shared.networkMessenger.queue = {} end if not shared.networkMessenger.queue then shared.networkMessenger.queue = {} end
if not shared.networkMessenger.ticker then if not shared.networkMessenger.ticker then
local function DoMessage() local function DoMessage()
--if Heimdall_Data.config.networkMessenger.debug then
-- print(string.format("[%s] Processing network message queue", ModuleName))
--end
if not Heimdall_Data.config.networkMessenger.enabled then
--if Heimdall_Data.config.networkMessenger.debug then --if Heimdall_Data.config.networkMessenger.debug then
-- print(string.format("[%s] Module disabled, skipping network message processing", ModuleName)) -- print(string.format("[%s] Processing network message queue", ModuleName))
--end --end
return if not Heimdall_Data.config.networkMessenger.enabled then
end --if Heimdall_Data.config.networkMessenger.debug then
---@type Message -- print(string.format("[%s] Module disabled, skipping network message processing", ModuleName))
local message = shared.networkMessenger.queue[1] --end
if not message then return
--if Heimdall_Data.config.networkMessenger.debug then
-- print(string.format("[%s] Network message queue empty", ModuleName))
--end
return
end
if not message.message or message.message == "" then
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Invalid network message: empty content", ModuleName))
end end
return ---@type Message
end local message = shared.networkMessenger.queue[1]
if not message.channel or message.channel == "" then if not message then
if Heimdall_Data.config.networkMessenger.debug then --if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Invalid network message: no channel specified", ModuleName)) -- print(string.format("[%s] Network message queue empty", ModuleName))
--end
return
end
if not message.message or message.message == "" then
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Invalid network message: empty content", ModuleName))
end
return
end
if not message.channel or message.channel == "" then
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Invalid network message: no channel specified", ModuleName))
end
return
end end
return
end
table.remove(shared.networkMessenger.queue, 1) table.remove(shared.networkMessenger.queue, 1)
if not message.message or message.message == "" then if not message.message or message.message == "" then
if Heimdall_Data.config.networkMessenger.debug then if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Skipping empty network message", ModuleName)) print(string.format("[%s] Skipping empty network message", ModuleName))
end
return
end end
return if not message.channel or message.channel == "" then
end if Heimdall_Data.config.networkMessenger.debug then
if not message.channel or message.channel == "" then print(string.format("[%s] Skipping network message with no channel", ModuleName))
if Heimdall_Data.config.networkMessenger.debug then end
print(string.format("[%s] Skipping network message with no channel", ModuleName)) return
end end
return if not message.data or message.data == "" then
end if Heimdall_Data.config.networkMessenger.debug then
if not message.data or message.data == "" then print(string.format("[%s] Skipping network message with no data", ModuleName))
if Heimdall_Data.config.networkMessenger.debug then end
print(string.format("[%s] Skipping network message with no data", ModuleName)) return
end end
return
end
if Heimdall_Data.config.networkMessenger.debug then if Heimdall_Data.config.networkMessenger.debug then
print( print(
string.format( string.format(
"[%s] Sending network message: '%s' to %s:%s", "[%s] Sending network message: '%s' to %s:%s",
ModuleName, ModuleName,
message.message, message.message,
message.channel, message.channel,
message.data message.data
)
) )
) end
local payload = string.format("dmessage|%s|%s|%s", message.message, message.channel, message.data)
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Payload: %s", ModuleName, payload))
end
if not shared.networkNodes or #shared.networkNodes == 0 then
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] No network nodes found, wtf????", ModuleName))
end
return
end
local target = shared.networkNodes[1]
SendAddonMessage(Heimdall_Data.config.addonPrefix, payload, "WHISPER", target)
end end
local payload = string.format("dmessage|%s|%s|%s", message.message, message.channel, message.data) local function Tick()
--if Heimdall_Data.config.networkMessenger.debug then
-- local queueSize = #shared.networkMessenger.queue
-- print(string.format("[%s] Queue check - Network messages pending: %d", ModuleName, queueSize))
--end
DoMessage()
shared.networkMessenger.ticker =
C_Timer.NewTimer(Heimdall_Data.config.networkMessenger.interval, Tick, 1)
end
Tick()
end
-- If we are the leader then we delegate messages (dmessage)
-- If we get a "message" command from leader then we send the message
local nextIdx = 1
local addonMsgFrame = CreateFrame("Frame")
addonMsgFrame:RegisterEvent("CHAT_MSG_ADDON")
addonMsgFrame:SetScript("OnEvent", function(self, event, prefix, message, channel, source)
if not Heimdall_Data.config.networkMessenger.enabled then return end
if prefix ~= Heimdall_Data.config.addonPrefix then return end
source = string.match(source, "[^%-]+")
if Heimdall_Data.config.networkMessenger.debug then if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Payload: %s", ModuleName, payload)) print(string.format("[%s] Received message from %s: %s", ModuleName, source, message))
end end
if not shared.networkNodes or #shared.networkNodes == 0 then if #shared.networkNodes == 0 then
if Heimdall_Data.config.networkMessenger.debug then if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] No network nodes found, wtf????", ModuleName)) print(string.format("[%s] No network nodes found, wtf????", ModuleName))
end end
return return
end end
local target = shared.networkNodes[1]
SendAddonMessage(Heimdall_Data.config.addonPrefix, payload, "WHISPER", target) -- There should always be at least one network node ergo should always exist a leader
end -- Because the us, the player, is also a node
local function Tick() --local networkLeader = shared.networkNodes[1]
--if Heimdall_Data.config.networkMessenger.debug then --if source ~= networkLeader then
-- local queueSize = #shared.networkMessenger.queue -- if Heimdall_Data.config.networkMessenger.debug then
-- print(string.format("[%s] Queue check - Network messages pending: %d", ModuleName, queueSize)) -- print(string.format("[%s] Message from %s is not from the network leader (%s)", ModuleName, source,
-- networkLeader))
-- end
-- return
--end --end
DoMessage()
shared.networkMessenger.ticker = C_Timer.NewTimer(Heimdall_Data.config.networkMessenger.interval, Tick, 1)
end
Tick()
end
-- If we are the leader then we delegate messages (dmessage) local parts = shared.Split(message, "|")
-- If we get a "message" command from leader then we send the message
local nextIdx = 1
local addonMsgFrame = CreateFrame("Frame")
addonMsgFrame:RegisterEvent("CHAT_MSG_ADDON")
addonMsgFrame:SetScript("OnEvent", function(self, event, prefix, message, channel, source)
if not Heimdall_Data.config.networkMessenger.enabled then return end
if prefix ~= Heimdall_Data.config.addonPrefix then return end
source = string.match(source, "[^%-]+")
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Received message from %s: %s", ModuleName, source, message))
end
if #shared.networkNodes == 0 then
if Heimdall_Data.config.networkMessenger.debug then if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] No network nodes found, wtf????", ModuleName)) print(string.format("[%s] Received message parts:", ModuleName))
shared.dumpTable(parts)
end end
return local command = strtrim(parts[1])
end if command == "message" then
local content = strtrim(tostring(parts[2]))
local targetchannel = strtrim(tostring(parts[3]))
local target = strtrim(tostring(parts[4]))
if Heimdall_Data.config.networkMessenger.debug then
print(
string.format(
"[%s] Received message command: %s %s %s",
ModuleName,
content,
targetchannel,
target
)
)
end
---@type Message
local msg = {
channel = targetchannel,
message = content,
data = target,
}
table.insert(shared.messenger.queue, msg)
elseif command == "dmessage" then
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Received dmessage command", ModuleName))
end
parts[1] = "message"
local content = table.concat(parts, "|")
-- There should always be at least one network node ergo should always exist a leader if nextIdx > #shared.networkNodes then nextIdx = 1 end
-- Because the us, the player, is also a node local recipient = shared.networkNodes[nextIdx]
--local networkLeader = shared.networkNodes[1] nextIdx = nextIdx + 1
--if source ~= networkLeader then if Heimdall_Data.config.networkMessenger.debug then
-- if Heimdall_Data.config.networkMessenger.debug then print(string.format("[%s] Sending message %s to %s", ModuleName, content, recipient))
-- print(string.format("[%s] Message from %s is not from the network leader (%s)", ModuleName, source, end
-- networkLeader)) SendAddonMessage(Heimdall_Data.config.addonPrefix, content, "WHISPER", recipient)
-- end
-- return
--end
local parts = shared.Split(message, "|")
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Received message parts:", ModuleName))
shared.dumpTable(parts)
end
local command = strtrim(parts[1])
if command == "message" then
local content = strtrim(tostring(parts[2]))
local targetchannel = strtrim(tostring(parts[3]))
local target = strtrim(tostring(parts[4]))
if Heimdall_Data.config.networkMessenger.debug then
print(
string.format("[%s] Received message command: %s %s %s", ModuleName, content, targetchannel, target)
)
end end
---@type Message end)
local msg = {
channel = targetchannel, --/run Heimdall_Data.Test()
message = content, Heimdall_Data.Test = function()
data = target, local testmsg = {
channel = "W",
message = "Hi, mom!",
data = "Secundus",
} }
table.insert(shared.messenger.queue, msg) for i = 1, 36 do
elseif command == "dmessage" then table.insert(shared.networkMessenger.queue, testmsg)
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Received dmessage command", ModuleName))
end end
parts[1] = "message"
local content = table.concat(parts, "|")
if nextIdx > #shared.networkNodes then nextIdx = 1 end
local recipient = shared.networkNodes[nextIdx]
nextIdx = nextIdx + 1
if Heimdall_Data.config.networkMessenger.debug then
print(string.format("[%s] Sending message %s to %s", ModuleName, content, recipient))
end
SendAddonMessage(Heimdall_Data.config.addonPrefix, content, "WHISPER", recipient)
end end
end)
--/run Heimdall_Data.Test() print("[Heimdall] NetworkMessenger module loaded")
Heimdall_Data.Test = function() end,
local testmsg = { }
channel = "W",
message = "Hi, mom!",
data = "Secundus",
}
for i = 1, 36 do
table.insert(shared.networkMessenger.queue, testmsg)
end
end
print("[Heimdall] NetworkMessenger module loaded")
end

View File

@@ -8,288 +8,291 @@ local ModuleName = "Noter"
---@field date string ---@field date string
---@field note string ---@field note string
---@diagnostic disable-next-line: missing-fields ---@class Noter
shared.Noter = {} shared.Noter = {
function shared.Noter.Init() Init = function()
-- ---Hopefully this will not be necessary -- ---Hopefully this will not be necessary
-- ---@param text string -- ---@param text string
-- ---@param size number -- ---@param size number
-- ---@return string[] -- ---@return string[]
-- local function Partition(text, size) -- local function Partition(text, size)
-- local words = {} -- local words = {}
-- for word in text:gmatch("[^,]+") do -- for word in text:gmatch("[^,]+") do
-- words[#words + 1] = word -- words[#words + 1] = word
-- end -- end
-- local ret = {} -- local ret = {}
-- local currentChunk = "" -- local currentChunk = ""
-- for _, word in ipairs(words) do -- for _, word in ipairs(words) do
-- if #currentChunk + #word + 1 <= size then -- if #currentChunk + #word + 1 <= size then
-- currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word) -- currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
-- else -- else
-- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end -- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
-- currentChunk = word -- currentChunk = word
-- end -- end
-- end -- end
-- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end -- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
-- return ret -- return ret
-- end -- end
---@param array any[] ---@param array any[]
---@return any[] ---@return any[]
local function Compact(array) local function Compact(array)
local compacted = {} local compacted = {}
for _, v in pairs(array) do for _, v in pairs(array) do
compacted[#compacted + 1] = v compacted[#compacted + 1] = v
end
return compacted
end
---@param name string
---@param args string[]
local function DeleteNotes(name, args)
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Delete note command received for: %s", ModuleName, name))
end
local range = args[4]
if range then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Range received for delete note: %s", ModuleName, range))
end end
local indices = shared.Split(range, "..") return compacted
if Heimdall_Data.config.noter.debug then end
print(string.format("[%s] Indices for range deletion: %s", ModuleName, table.concat(indices, ", ")))
shared.dumpTable(indices)
end
local start = tonumber(indices[1])
local finish = tonumber(indices[2])
if not start then ---@param name string
---@param args string[]
local function DeleteNotes(name, args)
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Delete note command received for: %s", ModuleName, name))
end
local range = args[4]
if range then
if Heimdall_Data.config.noter.debug then if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Invalid start range for delete note: %s", ModuleName, tostring(start))) print(string.format("[%s] Range received for delete note: %s", ModuleName, range))
end end
return local indices = shared.Split(range, "..")
end if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Indices for range deletion: %s", ModuleName, table.concat(indices, ", ")))
if not finish then finish = start end shared.dumpTable(indices)
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Deleting note range %s to %s for: %s", ModuleName, start, finish, name))
end
-- Here, because we are deleting random notes, we lose the "iterative" index property
-- Ie it's not longer 1..100, it might be 1..47, 50, 68..100
-- Which means that we cannot use ipairs, bad!
for i = start, finish do
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
if not Heimdall_Data.config.notes[name][i] then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Note at index %s does not exist", ModuleName, i))
end
else
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Deleting note %s at index %s", ModuleName, name, i))
shared.dumpTable(Heimdall_Data.config.notes[name][i])
end
Heimdall_Data.config.notes[name][i] = nil
end end
end local start = tonumber(indices[1])
Heimdall_Data.config.notes[name] = Compact(Heimdall_Data.config.notes[name]) local finish = tonumber(indices[2])
end
end
---@param channel string if not start then
---@param index number if Heimdall_Data.config.noter.debug then
---@param note Note print(
local function PrintNote(channel, index, note) string.format("[%s] Invalid start range for delete note: %s", ModuleName, tostring(start))
if Heimdall_Data.config.noter.debug then )
print(string.format("[%s] Printing note at index %d for: %s", ModuleName, index, note.source)) end
print(string.format("[%s] [%s][%d] %s: %s", ModuleName, note.source, index, note.date, note.note)) return
end
if not finish then finish = start end
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Deleting note range %s to %s for: %s", ModuleName, start, finish, name))
end
-- Here, because we are deleting random notes, we lose the "iterative" index property
-- Ie it's not longer 1..100, it might be 1..47, 50, 68..100
-- Which means that we cannot use ipairs, bad!
for i = start, finish do
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
if not Heimdall_Data.config.notes[name][i] then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Note at index %s does not exist", ModuleName, i))
end
else
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Deleting note %s at index %s", ModuleName, name, i))
shared.dumpTable(Heimdall_Data.config.notes[name][i])
end
Heimdall_Data.config.notes[name][i] = nil
end
end
Heimdall_Data.config.notes[name] = Compact(Heimdall_Data.config.notes[name])
end
end end
---@type Message
local msg = { ---@param channel string
channel = "C", ---@param index number
data = channel, ---@param note Note
message = string.format("[%s][%d] %s: %s", note.source, index, note.date, note.note), local function PrintNote(channel, index, note)
}
--table.insert(shared.messenger.queue, msg)
table.insert(shared.networkMessenger.queue, msg)
end
---@param name string
---@param args string[]
local function PrintNotes(channel, name, args)
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Print note command received for: %s", ModuleName, name))
end
local range = args[3]
if not range then
if Heimdall_Data.config.noter.debug then if Heimdall_Data.config.noter.debug then
print( print(string.format("[%s] Printing note at index %d for: %s", ModuleName, index, note.source))
string.format( print(string.format("[%s] [%s][%d] %s: %s", ModuleName, note.source, index, note.date, note.note))
"[%s] No range specified for print note, defaulting to last %d notes", end
ModuleName, ---@type Message
Heimdall_Data.config.noter.lastNotes local msg = {
channel = "C",
data = channel,
message = string.format("[%s][%d] %s: %s", note.source, index, note.date, note.note),
}
--table.insert(shared.messenger.queue, msg)
table.insert(shared.networkMessenger.queue, msg)
end
---@param name string
---@param args string[]
local function PrintNotes(channel, name, args)
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Print note command received for: %s", ModuleName, name))
end
local range = args[3]
if not range then
if Heimdall_Data.config.noter.debug then
print(
string.format(
"[%s] No range specified for print note, defaulting to last %d notes",
ModuleName,
Heimdall_Data.config.noter.lastNotes
)
) )
) end
end local notes = Heimdall_Data.config.notes[name] or {}
local notes = Heimdall_Data.config.notes[name] or {} local start = math.max(1, #notes - Heimdall_Data.config.noter.lastNotes + 1)
local start = math.max(1, #notes - Heimdall_Data.config.noter.lastNotes + 1) local finish = #notes
local finish = #notes
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Printing notes from %d to %d for: %s", ModuleName, start, finish, name))
end
for i = start, finish do
PrintNote(channel, i, notes[i])
end
return
end
if range then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Range received for print note: %s", ModuleName, range))
end
local indices = shared.Split(range, "..")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Indices for range printing: %s", ModuleName, table.concat(indices, ", ")))
shared.dumpTable(indices)
end
local start = tonumber(indices[1])
local finish = tonumber(indices[2])
if not start then
if Heimdall_Data.config.noter.debug then if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Invalid start range for print note: %s", ModuleName, tostring(start))) print(string.format("[%s] Printing notes from %d to %d for: %s", ModuleName, start, finish, name))
end
for i = start, finish do
PrintNote(channel, i, notes[i])
end
return
end
if range then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Range received for print note: %s", ModuleName, range))
end
local indices = shared.Split(range, "..")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Indices for range printing: %s", ModuleName, table.concat(indices, ", ")))
shared.dumpTable(indices)
end
local start = tonumber(indices[1])
local finish = tonumber(indices[2])
if not start then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Invalid start range for print note: %s", ModuleName, tostring(start)))
end
return
end
if not finish then finish = start end
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Printing note range %s to %s for: %s", ModuleName, start, finish, name))
end
for i = start, finish do
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
if not Heimdall_Data.config.notes[name][i] then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Note at index %s does not exist", ModuleName, i))
end
else
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Printing note %s at index %s", ModuleName, name, i))
shared.dumpTable(Heimdall_Data.config.notes[name][i])
end
PrintNote(channel, i, Heimdall_Data.config.notes[name][i])
end
end
end
end
---@param name string
---@param sender string
---@param args string[]
local function AddNote(name, sender, args)
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
shared.dumpTable(args)
end
local msgparts = {}
for i = 3, #args do
msgparts[#msgparts + 1] = args[i]
end
local msg = table.concat(msgparts, " ")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
print(string.format("[%s] Note: %s", ModuleName, msg))
end
local note = {
source = sender,
date = date("%Y-%m-%dT%H:%M:%S"),
note = msg,
}
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note", ModuleName))
shared.dumpTable(note)
end
table.insert(Heimdall_Data.config.notes[name], note)
end
-- Here's the plan:
-- Implement a "note" command, that will do everything
-- Saying "note <name> <note>" will add a note to the list for the character
-- Saying "note <name>" will list last N notes
-- Saying "note <name> i" will list the i-th note
-- Saying "note <name> i..j" will list notes from i to j
-- Saying "note <name> delete i" will delete the i-th note
-- Saying "note <name> delete i..j" will delete notes from i to j
local noterChannelFrame = CreateFrame("Frame")
noterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
noterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Event received", ModuleName))
-- shared.dumpTable(Heimdall_Data.config.noter)
--end
if not Heimdall_Data.config.noter.enabled then
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
--end
return
end
local channelId = select(6, ...)
local _, channelname = GetChannelName(channelId)
local ok = false
for _, channel in pairs(Heimdall_Data.config.noter.channels) do
if channelname == channel then
ok = true
break
end
end
if not ok then
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Channel %s does not match the master channel %s", ModuleName, channelname, Heimdall_Data.config.noter.masterChannel))
--end
return
end
sender = string.match(sender, "^[^-]+")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Message from: %s", ModuleName, sender))
shared.dumpTable(Heimdall_Data.config.noter)
end
if not msg or msg == "" then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Empty message, ignoring", ModuleName))
end end
return return
end end
if not finish then finish = start end local args = { strsplit(" ", msg) }
if Heimdall_Data.config.noter.debug then if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Printing note range %s to %s for: %s", ModuleName, start, finish, name)) print(string.format("[%s] Arguments received: %s", ModuleName, table.concat(args, ", ")))
shared.dumpTable(args)
end end
local command = args[1]
for i = start, finish do if command == "note" then
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end local name = strtrim(string.lower(args[2] or ""))
if not Heimdall_Data.config.notes[name][i] then if Heimdall_Data.config.noter.debug then
if Heimdall_Data.config.noter.debug then print(string.format("[%s] Note command received for: %s", ModuleName, name))
print(string.format("[%s] Note at index %s does not exist", ModuleName, i)) end
end local note = strtrim(args[3] or "")
if Heimdall_Data.config.noter.debug then print(string.format("[%s] Note: %s", ModuleName, note)) end
if note == "delete" then
DeleteNotes(name, args)
elseif string.find(note, "^[%d%.]*$") then
PrintNotes(channelname, name, args)
else else
if Heimdall_Data.config.noter.debug then AddNote(name, sender, args)
print(string.format("[%s] Printing note %s at index %s", ModuleName, name, i))
shared.dumpTable(Heimdall_Data.config.notes[name][i])
end
PrintNote(channel, i, Heimdall_Data.config.notes[name][i])
end end
end end
end end)
end
---@param name string print("[Heimdall] Commander module loaded")
---@param sender string end,
---@param args string[] }
local function AddNote(name, sender, args)
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
shared.dumpTable(args)
end
local msgparts = {}
for i = 3, #args do
msgparts[#msgparts + 1] = args[i]
end
local msg = table.concat(msgparts, " ")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
print(string.format("[%s] Note: %s", ModuleName, msg))
end
local note = {
source = sender,
date = date("%Y-%m-%dT%H:%M:%S"),
note = msg,
}
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Adding note", ModuleName))
shared.dumpTable(note)
end
table.insert(Heimdall_Data.config.notes[name], note)
end
-- Here's the plan:
-- Implement a "note" command, that will do everything
-- Saying "note <name> <note>" will add a note to the list for the character
-- Saying "note <name>" will list last N notes
-- Saying "note <name> i" will list the i-th note
-- Saying "note <name> i..j" will list notes from i to j
-- Saying "note <name> delete i" will delete the i-th note
-- Saying "note <name> delete i..j" will delete notes from i to j
local noterChannelFrame = CreateFrame("Frame")
noterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
noterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Event received", ModuleName))
-- shared.dumpTable(Heimdall_Data.config.noter)
--end
if not Heimdall_Data.config.noter.enabled then
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
--end
return
end
local channelId = select(6, ...)
local _, channelname = GetChannelName(channelId)
local ok = false
for _, channel in pairs(Heimdall_Data.config.noter.channels) do
if channelname == channel then
ok = true
break
end
end
if not ok then
--if Heimdall_Data.config.noter.debug then
-- print(string.format("[%s] Channel %s does not match the master channel %s", ModuleName, channelname, Heimdall_Data.config.noter.masterChannel))
--end
return
end
sender = string.match(sender, "^[^-]+")
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Message from: %s", ModuleName, sender))
shared.dumpTable(Heimdall_Data.config.noter)
end
if not msg or msg == "" then
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Empty message, ignoring", ModuleName))
end
return
end
local args = { strsplit(" ", msg) }
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Arguments received: %s", ModuleName, table.concat(args, ", ")))
shared.dumpTable(args)
end
local command = args[1]
if command == "note" then
local name = strtrim(string.lower(args[2] or ""))
if Heimdall_Data.config.noter.debug then
print(string.format("[%s] Note command received for: %s", ModuleName, name))
end
local note = strtrim(args[3] or "")
if Heimdall_Data.config.noter.debug then print(string.format("[%s] Note: %s", ModuleName, note)) end
if note == "delete" then
DeleteNotes(name, args)
elseif string.find(note, "^[%d%.]*$") then
PrintNotes(channelname, name, args)
else
AddNote(name, sender, args)
end
end
end)
print("[Heimdall] Commander module loaded")
end

View File

@@ -2,223 +2,226 @@ local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
local ModuleName = "Spotter" local ModuleName = "Spotter"
---@diagnostic disable-next-line: missing-fields ---@class Spotter
shared.Spotter = {} shared.Spotter = {
function shared.Spotter.Init() Init = function()
local function FormatHP(hp) local function FormatHP(hp)
if hp > 1e9 then if hp > 1e9 then
return string.format("%.1fB", hp / 1e9) return string.format("%.1fB", hp / 1e9)
elseif hp > 1e6 then elseif hp > 1e6 then
return string.format("%.1fM", hp / 1e6) return string.format("%.1fM", hp / 1e6)
elseif hp > 1e3 then elseif hp > 1e3 then
return string.format("%.1fK", hp / 1e3) return string.format("%.1fK", hp / 1e3)
else else
return hp return hp
end end
end
---@type table<string, number>
local throttleTable = {}
---@param unit string
---@param name string
---@param faction string
---@param hostile boolean
---@return boolean
---@return string? error
local function ShouldNotify(unit, name, faction, hostile)
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Checking notification criteria for %s (%s)", ModuleName, name, faction))
end end
if shared.AgentTracker.IsAgent(name) then ---@type table<string, number>
local throttleTable = {}
---@param unit string
---@param name string
---@param faction string
---@param hostile boolean
---@return boolean
---@return string? error
local function ShouldNotify(unit, name, faction, hostile)
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Skipping agent: %s", ModuleName, name)) print(string.format("[%s] Checking notification criteria for %s (%s)", ModuleName, name, faction))
end end
return false
end
if Heimdall_Data.config.spotter.stinky then if shared.AgentTracker.IsAgent(name) then
if shared.IsStinky(name) then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Notifying - Found stinky: %s", ModuleName, name)) print(string.format("[%s] Skipping agent: %s", ModuleName, name))
end end
return true return false
end end
end
if Heimdall_Data.config.spotter.alliance then if Heimdall_Data.config.spotter.stinky then
if faction == "Alliance" then if shared.IsStinky(name) then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Notifying - Found Alliance player: %s", ModuleName, name)) print(string.format("[%s] Notifying - Found stinky: %s", ModuleName, name))
end
return true
end end
return true
end end
end
if Heimdall_Data.config.spotter.hostile then if Heimdall_Data.config.spotter.alliance then
if hostile then if faction == "Alliance" then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Notifying - Found hostile player: %s", ModuleName, name)) print(string.format("[%s] Notifying - Found Alliance player: %s", ModuleName, name))
end
return true
end end
return true
end end
end
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.hostile then
print( if hostile then
string.format( if Heimdall_Data.config.spotter.debug then
"[%s] Using everyone setting: %s", print(string.format("[%s] Notifying - Found hostile player: %s", ModuleName, name))
ModuleName, end
tostring(Heimdall_Data.config.spotter.everyone) return true
end
end
if Heimdall_Data.config.spotter.debug then
print(
string.format(
"[%s] Using everyone setting: %s",
ModuleName,
tostring(Heimdall_Data.config.spotter.everyone)
)
) )
)
end
return Heimdall_Data.config.spotter.everyone
end
---@param unit string
---@return string?
local function NotifySpotted(unit)
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Processing spotted unit: %s", ModuleName, unit))
end
if not unit then return string.format("Could not find unit %s", tostring(unit)) end
if not UnitIsPlayer(unit) then
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Ignoring non-player unit: %s", ModuleName, unit))
end end
return nil return Heimdall_Data.config.spotter.everyone
end end
local name = UnitName(unit) ---@param unit string
if not name then return string.format("Could not find name for unit %s", tostring(unit)) end ---@return string?
if Heimdall_Data.config.spotter.debug then local function NotifySpotted(unit)
print(string.format("[%s] Processing player: %s", ModuleName, name))
end
local time = GetTime()
if throttleTable[name] and time - throttleTable[name] < Heimdall_Data.config.spotter.throttleTime then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
local remainingTime = Heimdall_Data.config.spotter.throttleTime - (time - throttleTable[name]) print(string.format("[%s] Processing spotted unit: %s", ModuleName, unit))
print(string.format("[%s] Player %s throttled for %.1f more seconds", ModuleName, name, remainingTime))
end end
return string.format("Throttled %s", tostring(name))
end
throttleTable[name] = time
local race = UnitRace(unit) if not unit then return string.format("Could not find unit %s", tostring(unit)) end
if not race then return string.format("Could not find race for unit %s", tostring(unit)) end if not UnitIsPlayer(unit) then
local faction = shared.raceMap[race] if Heimdall_Data.config.spotter.debug then
if not faction then return string.format("Could not find faction for race %s", tostring(race)) end print(string.format("[%s] Ignoring non-player unit: %s", ModuleName, unit))
if Heimdall_Data.config.spotter.debug then end
print(string.format("[%s] Player %s is %s (%s)", ModuleName, name, race, faction)) return nil
end
local hostile = UnitCanAttack("player", unit)
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Player %s is %s", ModuleName, name, hostile and "hostile" or "friendly"))
end
local doNotify = ShouldNotify(unit, name, faction, hostile)
if not doNotify then
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Skipping notification for %s", ModuleName, name))
end end
return string.format("Not notifying for %s", tostring(name))
end
local hp = UnitHealth(unit) local name = UnitName(unit)
if not hp then return string.format("Could not find hp for unit %s", tostring(unit)) end if not name then return string.format("Could not find name for unit %s", tostring(unit)) end
local maxHp = UnitHealthMax(unit)
if not maxHp then return string.format("Could not find maxHp for unit %s", tostring(unit)) end
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Player %s health: %s/%s", ModuleName, name, FormatHP(hp), FormatHP(maxHp)))
end
local class = UnitClass(unit)
if not class then return string.format("Could not find class for unit %s", tostring(unit)) end
local zone, subzone = GetZoneText() or "Unknown", GetSubZoneText() or "Unknown"
if Heimdall_Data.config.spotter.zoneOverride then
zone = Heimdall_Data.config.spotter.zoneOverride or ""
subzone = ""
end
local x, y = GetPlayerMapPosition("player")
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Player %s coordinates: %.2f, %.2f", ModuleName, name, x * 100, y * 100))
end
local pvpOn = UnitIsPVP(unit)
local stinky = shared.IsStinky(name) or false
SetMapToCurrentZone()
SetMapByID(GetCurrentMapAreaID())
local areaId = tostring(GetCurrentMapAreaID())
for _, channel in pairs(Heimdall_Data.config.spotter.channels) do
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Processing channel: %s", ModuleName, channel)) print(string.format("[%s] Processing player: %s", ModuleName, name))
end end
local locale = shared.GetLocaleForChannel(channel)
local text = string.format(
shared._L("spotterSpotted", locale),
hostile and shared._L("hostile", locale) or shared._L("friendly", locale),
name,
shared._L(class, locale),
stinky and string.format("(%s)", "!!!!") or "",
shared._L(race, locale),
shared._L(faction, locale),
pvpOn and shared._L("pvpOn", locale) or shared._L("pvpOff", locale),
string.gsub(FormatHP(hp), "M", "kk"),
string.gsub(FormatHP(maxHp), "M", "kk"),
shared._L(zone, locale),
shared._L(subzone, locale),
areaId,
x * 100,
y * 100
)
---@type Message local time = GetTime()
local msg = { if throttleTable[name] and time - throttleTable[name] < Heimdall_Data.config.spotter.throttleTime then
channel = "C", if Heimdall_Data.config.spotter.debug then
data = channel, local remainingTime = Heimdall_Data.config.spotter.throttleTime - (time - throttleTable[name])
message = text, print(
} string.format("[%s] Player %s throttled for %.1f more seconds", ModuleName, name, remainingTime)
if Heimdall_Data.config.spotter.debug then )
print(string.format("[%s] Queuing spotter message", ModuleName)) end
shared.dumpTable(msg) return string.format("Throttled %s", tostring(name))
end end
table.insert(shared.messenger.queue, msg) throttleTable[name] = time
end
end
local frame = CreateFrame("Frame") local race = UnitRace(unit)
frame:RegisterEvent("NAME_PLATE_UNIT_ADDED") if not race then return string.format("Could not find race for unit %s", tostring(unit)) end
frame:RegisterEvent("UNIT_TARGET") local faction = shared.raceMap[race]
frame:SetScript("OnEvent", function(self, event, unit) if not faction then return string.format("Could not find faction for race %s", tostring(race)) end
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Event received: %s for unit: %s", ModuleName, event, unit or "target"))
end
if not Heimdall_Data.config.spotter.enabled then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Module disabled, ignoring event", ModuleName)) print(string.format("[%s] Player %s is %s (%s)", ModuleName, name, race, faction))
end end
return
end
if event == "UNIT_TARGET" then unit = "target" end local hostile = UnitCanAttack("player", unit)
local err = NotifySpotted(unit)
if err then
if Heimdall_Data.config.spotter.debug then if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Error processing unit %s: %s", ModuleName, unit, err)) print(string.format("[%s] Player %s is %s", ModuleName, name, hostile and "hostile" or "friendly"))
end
local doNotify = ShouldNotify(unit, name, faction, hostile)
if not doNotify then
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Skipping notification for %s", ModuleName, name))
end
return string.format("Not notifying for %s", tostring(name))
end
local hp = UnitHealth(unit)
if not hp then return string.format("Could not find hp for unit %s", tostring(unit)) end
local maxHp = UnitHealthMax(unit)
if not maxHp then return string.format("Could not find maxHp for unit %s", tostring(unit)) end
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Player %s health: %s/%s", ModuleName, name, FormatHP(hp), FormatHP(maxHp)))
end
local class = UnitClass(unit)
if not class then return string.format("Could not find class for unit %s", tostring(unit)) end
local zone, subzone = GetZoneText() or "Unknown", GetSubZoneText() or "Unknown"
if Heimdall_Data.config.spotter.zoneOverride then
zone = Heimdall_Data.config.spotter.zoneOverride or ""
subzone = ""
end
local x, y = GetPlayerMapPosition("player")
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Player %s coordinates: %.2f, %.2f", ModuleName, name, x * 100, y * 100))
end
local pvpOn = UnitIsPVP(unit)
local stinky = shared.IsStinky(name) or false
SetMapToCurrentZone()
SetMapByID(GetCurrentMapAreaID())
local areaId = tostring(GetCurrentMapAreaID())
for _, channel in pairs(Heimdall_Data.config.spotter.channels) do
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Processing channel: %s", ModuleName, channel))
end
local locale = shared.GetLocaleForChannel(channel)
local text = string.format(
shared._L("spotterSpotted", locale),
hostile and shared._L("hostile", locale) or shared._L("friendly", locale),
name,
shared._L(class, locale),
stinky and string.format("(%s)", "!!!!") or "",
shared._L(race, locale),
shared._L(faction, locale),
pvpOn and shared._L("pvpOn", locale) or shared._L("pvpOff", locale),
string.gsub(FormatHP(hp), "M", "kk"),
string.gsub(FormatHP(maxHp), "M", "kk"),
shared._L(zone, locale),
shared._L(subzone, locale),
areaId,
x * 100,
y * 100
)
---@type Message
local msg = {
channel = "C",
data = channel,
message = text,
}
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Queuing spotter message", ModuleName))
shared.dumpTable(msg)
end
table.insert(shared.messenger.queue, msg)
end end
end end
end)
if Heimdall_Data.config.spotter.debug then print(string.format("[%s] Module initialized", ModuleName)) end local frame = CreateFrame("Frame")
print("[Heimdall] Spotter loaded") frame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
end frame:RegisterEvent("UNIT_TARGET")
frame:SetScript("OnEvent", function(self, event, unit)
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Event received: %s for unit: %s", ModuleName, event, unit or "target"))
end
if not Heimdall_Data.config.spotter.enabled then
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
end
return
end
if event == "UNIT_TARGET" then unit = "target" end
local err = NotifySpotted(unit)
if err then
if Heimdall_Data.config.spotter.debug then
print(string.format("[%s] Error processing unit %s: %s", ModuleName, unit, err))
end
end
end)
if Heimdall_Data.config.spotter.debug then print(string.format("[%s] Module initialized", ModuleName)) end
print("[Heimdall] Spotter loaded")
end,
}

View File

@@ -1,72 +1,74 @@
local addonname, shared = ... local _, shared = ...
---@cast shared HeimdallShared ---@cast shared HeimdallShared
---@cast addonname string
local ModuleName = "StinkyCache" local ModuleName = "StinkyCache"
---@diagnostic disable-next-line: missing-fields ---@class StinkyCache
shared.StinkyCache = {} shared.StinkyCache = {
function shared.StinkyCache.Init() Init = function()
shared.stinkyCache = { shared.stinkyCache = {
stinkies = {}, stinkies = {},
} }
---@param name string ---@param name string
local function AskCommander(name) local function AskCommander(name)
if Heimdall_Data.config.stinkyCache.debug then
print(
string.format(
"[%s] Asking commander %s about %s",
ModuleName,
Heimdall_Data.config.stinkyCache.commander,
name
)
)
end
local messageParts = { "isstinky", name }
local message = table.concat(messageParts, "|")
SendAddonMessage(
Heimdall_Data.config.addonPrefix,
message,
"WHISPER",
Heimdall_Data.config.stinkyCache.commander
)
return
end
local addonMessageFrame = CreateFrame("Frame")
addonMessageFrame:RegisterEvent("CHAT_MSG_ADDON")
addonMessageFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
if sender == Heimdall_Data.config.stinkyCache.commander then
if Heimdall_Data.config.stinkyCache.debug then if Heimdall_Data.config.stinkyCache.debug then
print( print(
string.format( string.format(
"[%s] Received stinky from commander %s: %s", "[%s] Asking commander %s about %s",
ModuleName, ModuleName,
Heimdall_Data.config.stinkyCache.commander, Heimdall_Data.config.stinkyCache.commander,
msg name
) )
) )
end end
local parts = { strsplit("|", msg) } local messageParts = { "isstinky", name }
local name, value = parts[1], parts[2] local message = table.concat(messageParts, "|")
shared.stinkyCache.stinkies[name] = { value = value, timestamp = time() } SendAddonMessage(
else Heimdall_Data.config.addonPrefix,
if Heimdall_Data.config.stinkyCache.debug then message,
print(string.format("[%s] Received stinky from non-commander %s: %s", ModuleName, sender, msg)) "WHISPER",
end Heimdall_Data.config.stinkyCache.commander
local parts = { strsplit("|", msg) } )
local command, name = parts[1], parts[2] return
if parts[1] == "isstinky" then local res = Heimdall_Data.config.stinkies[parts[2]] end
end end
end)
setmetatable(shared.stinkyCache.stinkies, { local addonMessageFrame = CreateFrame("Frame")
__index = function(self, key) addonMessageFrame:RegisterEvent("CHAT_MSG_ADDON")
local value = rawget(self, key) addonMessageFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
local now = GetTime() if sender == Heimdall_Data.config.stinkyCache.commander then
if value == nil or now - value.timestamp > Heimdall_Data.config.stinkyCache.ttl then AskCommander(key) end if Heimdall_Data.config.stinkyCache.debug then
return rawget(self, key) print(
end, string.format(
}) "[%s] Received stinky from commander %s: %s",
print("[Heimdall] StinkyCache module loaded") ModuleName,
end Heimdall_Data.config.stinkyCache.commander,
msg
)
)
end
local parts = { strsplit("|", msg) }
local name, value = parts[1], parts[2]
shared.stinkyCache.stinkies[name] = { value = value, timestamp = time() }
else
if Heimdall_Data.config.stinkyCache.debug then
print(string.format("[%s] Received stinky from non-commander %s: %s", ModuleName, sender, msg))
end
local parts = { strsplit("|", msg) }
local command, name = parts[1], parts[2]
if parts[1] == "isstinky" then local res = Heimdall_Data.config.stinkies[parts[2]] end
end
end)
setmetatable(shared.stinkyCache.stinkies, {
__index = function(self, key)
local value = rawget(self, key)
local now = GetTime()
if value == nil or now - value.timestamp > Heimdall_Data.config.stinkyCache.ttl then
AskCommander(key)
end
return rawget(self, key)
end,
})
print("[Heimdall] StinkyCache module loaded")
end,
}

File diff suppressed because it is too large Load Diff