-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSync.lua
More file actions
247 lines (224 loc) · 8.85 KB
/
Copy pathSync.lua
File metadata and controls
247 lines (224 loc) · 8.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
-- ============================================================
-- RT v2 — Sync.lua
-- Backbone communication inter-addon via SendAddonMessage
-- Prefix "RTSYNC" — compatible WoW 1.12 / TurtleWoW
-- ============================================================
-- Types de messages :
-- VER : version broadcast
-- ROLES : sync des rôles roster
-- TIMER : pull timer start/cancel
-- CD : cooldown utilisé/reset
-- NOTE : note raid
-- MARK : markers raid
-- ============================================================
RT_Sync = RT_Sync or {}
local SYNC_PREFIX = "RTSYNC"
local SYNC_SEP = "\031" -- unit separator (safe, non-printable)
local SYNC_VERSION = "2"
local SYNC_RATE_MIN = 0.2 -- secondes entre deux envois identiques
local RT_SYNC_LAST_SENT = {}
-- ── Encode / Decode ────────────────────────────────────────
local function Sync_Encode(msgType, ...)
-- Lua 5.0 : varargs accessibles via `arg`, pas via { ... }
local parts = { msgType }
for i = 1, table.getn(arg) do
table.insert(parts, tostring(arg[i] or ""))
end
return table.concat(parts, SYNC_SEP)
end
local function Sync_Decode(raw)
local parts = {}
local s = raw or ""
-- split on SYNC_SEP (char 31)
local i = 1
local len = string.len(s)
local cur = ""
while i <= len do
local c = string.sub(s, i, i)
if c == SYNC_SEP then
table.insert(parts, cur)
cur = ""
else
cur = cur .. c
end
i = i + 1
end
table.insert(parts, cur)
return parts
end
-- ── Envoi ──────────────────────────────────────────────────
function RT_Sync_Send(msgType, ...)
if not msgType then return end
local _a = arg -- capture varargs avant tout appel interne
local payload = Sync_Encode(msgType, unpack(_a))
-- Rate-limit pour éviter le spam
local now = GetTime and GetTime() or 0
local key = msgType .. "|" .. tostring(_a[1] or "")
if (now - (RT_SYNC_LAST_SENT[key] or 0)) < SYNC_RATE_MIN then return end
RT_SYNC_LAST_SENT[key] = now
local channel = "RAID"
if GetNumRaidMembers and GetNumRaidMembers() == 0 then
if GetNumPartyMembers and GetNumPartyMembers() > 0 then
channel = "PARTY"
else
-- Solo : on s'envoie à soi-même pour les tests
local player = UnitName and UnitName("player") or ""
if player ~= "" then
pcall(SendAddonMessage, SYNC_PREFIX, payload, "WHISPER", player)
end
return
end
end
pcall(SendAddonMessage, SYNC_PREFIX, payload, channel)
end
-- Envoi ciblé (whisper) à un joueur
function RT_Sync_Whisper(target, msgType, ...)
if not target or target == "" or not msgType then return end
local _a = arg
local payload = Sync_Encode(msgType, unpack(_a))
pcall(SendAddonMessage, SYNC_PREFIX, payload, "WHISPER", target)
end
-- ── Handlers enregistrés ───────────────────────────────────
local RT_SYNC_HANDLERS = {}
function RT_Sync_Register(msgType, fn)
RT_SYNC_HANDLERS[msgType] = fn
end
-- ── Reception ──────────────────────────────────────────────
local RT_SyncListenFrame = CreateFrame("Frame", "RT_SyncListenFrame", UIParent)
RT_SyncListenFrame:RegisterEvent("CHAT_MSG_ADDON")
RT_SyncListenFrame:SetScript("OnEvent", function(self, evName, a1, a2, a3, a4)
local prefix = a1 or arg1 or ""
local payload = a2 or arg2 or ""
local channel = a3 or arg3 or ""
local sender = a4 or arg4 or ""
if prefix ~= SYNC_PREFIX then return end
if not payload or payload == "" then return end
local parts = Sync_Decode(payload)
local msgType = parts[1] or ""
if msgType == "" then return end
local handler = RT_SYNC_HANDLERS[msgType]
if handler then
local args = {}
for i = 2, table.getn(parts) do
table.insert(args, parts[i])
end
-- handler(sender, arg1, arg2, ...)
handler(sender, unpack(args))
end
end)
-- ── Version broadcast ──────────────────────────────────────
RT_SYNC_MEMBERS = RT_SYNC_MEMBERS or {} -- {name = version}
RT_Sync_Register("VER", function(sender, ver)
RT_SYNC_MEMBERS[sender] = ver or "?"
end)
function RT_Sync_BroadcastVersion()
RT_Sync_Send("VER", SYNC_VERSION)
end
-- ── Sync Rôles ─────────────────────────────────────────────
-- Encode le roster en mini-format compact : "Name:Class:Role|Name:Class:Role|..."
function RT_Sync_SendRoles()
RT_DB = RT_DB or {}
local roster = RT_DB.roster or {}
local parts = {}
for name, data in pairs(roster) do
local c = (data.class or ""):sub(1,3)
local r = (data.role or "D"):sub(1,1)
table.insert(parts, name .. ":" .. c .. ":" .. r)
end
if table.getn(parts) == 0 then return end
-- Envoie par chunks de 200 chars
local chunk = ""
for i = 1, table.getn(parts) do
local seg = parts[i]
if string.len(chunk) + string.len(seg) + 1 > 200 then
RT_Sync_Send("ROLES", chunk)
chunk = seg
else
chunk = chunk == "" and seg or (chunk .. "|" .. seg)
end
end
if chunk ~= "" then RT_Sync_Send("ROLES", chunk) end
end
RT_Sync_Register("ROLES", function(sender, encoded)
if not encoded or encoded == "" then return end
RT_DB = RT_DB or {}
RT_DB.roster = RT_DB.roster or {}
-- Décode "Name:Cls:Role|..."
local i = 1
local len = string.len(encoded)
local seg = ""
while i <= len + 1 do
local c = i <= len and string.sub(encoded, i, i) or "|"
if c == "|" then
if seg ~= "" then
-- parse Name:Cls:Role
local p = {}
local si = 1
local slen = string.len(seg)
local cur = ""
while si <= slen + 1 do
local sc = si <= slen and string.sub(seg, si, si) or ":"
if sc == ":" then
table.insert(p, cur)
cur = ""
else
cur = cur .. sc
end
si = si + 1
end
local pname = p[1] or ""
local pcls = p[2] or ""
local prole = p[3] or "D"
if pname ~= "" then
local existing = RT_DB.roster[pname] or {}
if pcls ~= "" and (not existing.class or existing.class == "") then
existing.class = pcls
end
local roleMap = { T="Tank", H="Heal", D="DPS" }
if not existing.role or existing.role == "" then
existing.role = roleMap[prole] or "DPS"
end
RT_DB.roster[pname] = existing
end
end
seg = ""
else
seg = seg .. c
end
i = i + 1
end
if RT_RosterDisplay then RT_RosterDisplay() end
end)
-- ── Sync Note raid ─────────────────────────────────────────
function RT_Sync_SendNote(noteText)
if not noteText or noteText == "" then return end
RT_Sync_Send("NOTE", noteText)
end
RT_Sync_Register("NOTE", function(sender, note)
if not note or note == "" then return end
RT_DB = RT_DB or {}
RT_DB.sharedNotes = RT_DB.sharedNotes or {}
RT_DB.sharedNotes[sender] = note
RT_Print("|cff88CCFF[Sync]|r Note de " .. sender .. " reçue.")
local nb = getglobal("RT_NotesContent")
if nb then
local cur = nb:GetText() or ""
if not string.find(cur, note, 1, true) then
nb:SetText(cur ~= "" and (cur .. "\n-- " .. sender .. " --\n" .. note) or note)
end
end
end)
-- ── Init on VARIABLES_LOADED ───────────────────────────────
local RT_SyncInitFrame = CreateFrame("Frame")
RT_SyncInitFrame:RegisterEvent("VARIABLES_LOADED")
RT_SyncInitFrame:SetScript("OnEvent", function()
-- broadcast version après 3s pour laisser les autres charger
if RT_Sync_BroadcastVersion then
local _tStart = GetTime()
RT_SyncInitFrame:SetScript("OnUpdate", function()
if (GetTime() - _tStart) < 3 then return end
RT_SyncInitFrame:SetScript("OnUpdate", nil)
pcall(RT_Sync_BroadcastVersion)
end)
end
end)