|
|
|
|
@ -12,8 +12,8 @@ local TSM = select(2, ...)
|
|
|
|
|
local ChannelSync = TSM:NewModule("ChannelSync", "AceEvent-3.0") |
|
|
|
|
|
|
|
|
|
local CHANNEL_NAME = "TSM_AuctionDB" |
|
|
|
|
local COMM_PREFIX = "TSMAuctionDB" |
|
|
|
|
local CHUNK_SIZE = 180 |
|
|
|
|
local COMM_PREFIX = "TSMADB1" |
|
|
|
|
local CHUNK_SIZE = 200 |
|
|
|
|
local BUNDLE_TIMEOUT = 45 |
|
|
|
|
|
|
|
|
|
local private = { |
|
|
|
|
@ -26,16 +26,16 @@ local private = {
|
|
|
|
|
local strbyte = string.byte |
|
|
|
|
|
|
|
|
|
local libS = LibStub:GetLibrary("AceSerializer-3.0") |
|
|
|
|
local libC = LibStub:GetLibrary("LibCompress") |
|
|
|
|
local libCE |
|
|
|
|
|
|
|
|
|
local function GetCodec() |
|
|
|
|
if libCE then return libCE end |
|
|
|
|
libCE = libC:GetChatEncodeTable("", "\031") |
|
|
|
|
if not libCE then |
|
|
|
|
libCE = libC:GetChatEncodeTable() |
|
|
|
|
local libD = LibStub("LibDeflate", true) |
|
|
|
|
local warnedNoDeflate |
|
|
|
|
|
|
|
|
|
local function CanEncode() |
|
|
|
|
if libD then return true end |
|
|
|
|
if not warnedNoDeflate then |
|
|
|
|
warnedNoDeflate = true |
|
|
|
|
TSM:Print("AuctionDB channel sync requires LibDeflate. Install or enable an addon that provides it.") |
|
|
|
|
end |
|
|
|
|
return libCE |
|
|
|
|
return false |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function HashString(str) |
|
|
|
|
@ -43,7 +43,7 @@ local function HashString(str)
|
|
|
|
|
for i = 1, #str do |
|
|
|
|
hash = (hash * 31 + strbyte(str, i)) % 4294967296 |
|
|
|
|
end |
|
|
|
|
return tostring(hash) |
|
|
|
|
return hash |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function EnsureChannel() |
|
|
|
|
@ -58,7 +58,7 @@ end
|
|
|
|
|
|
|
|
|
|
local function ChatFilter(_, _, msg, _, _, _, _, _, channelName) |
|
|
|
|
if channelName ~= CHANNEL_NAME then return end |
|
|
|
|
if strsub(msg, 1, #COMM_PREFIX + 1) == COMM_PREFIX .. "|" then |
|
|
|
|
if strsub(msg, 1, #COMM_PREFIX) == COMM_PREFIX then |
|
|
|
|
return true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
@ -82,25 +82,18 @@ function ChannelSync:OnChannelNotice()
|
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function EncodePayload(payload) |
|
|
|
|
if not CanEncode() then return end |
|
|
|
|
local serialized = libS:Serialize(payload) |
|
|
|
|
local codec = GetCodec() |
|
|
|
|
if not codec then return end |
|
|
|
|
local encoded = codec:Encode(libC:CompressHuffman(serialized)) |
|
|
|
|
if not encoded then |
|
|
|
|
encoded = codec:Encode(libC:CompressLZW(serialized)) |
|
|
|
|
end |
|
|
|
|
if not encoded then |
|
|
|
|
encoded = codec:Encode("\001" .. serialized) |
|
|
|
|
end |
|
|
|
|
return encoded |
|
|
|
|
local compressed = libD:CompressDeflate(serialized, { level = 7 }) |
|
|
|
|
if not compressed then return end |
|
|
|
|
return libD:EncodeForPrint(compressed) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local function DecodePayload(encoded) |
|
|
|
|
local codec = GetCodec() |
|
|
|
|
if not codec then return end |
|
|
|
|
local decoded = codec:Decode(encoded) |
|
|
|
|
if not CanEncode() then return end |
|
|
|
|
local decoded = libD:DecodeForPrint(encoded) |
|
|
|
|
if not decoded then return end |
|
|
|
|
local decompressed = libC:Decompress(decoded) |
|
|
|
|
local decompressed = libD:DecompressDeflate(decoded) |
|
|
|
|
if not decompressed then return end |
|
|
|
|
local ok, payload = libS:Deserialize(decompressed) |
|
|
|
|
if not ok then return end |
|
|
|
|
@ -131,11 +124,11 @@ function ChannelSync:BroadcastScanData(scanType)
|
|
|
|
|
local hash = HashString(encoded) |
|
|
|
|
if hash == private.lastBroadcastHash then return end |
|
|
|
|
private.lastBroadcastHash = hash |
|
|
|
|
|
|
|
|
|
local total = ceil(#encoded / CHUNK_SIZE) |
|
|
|
|
if total > 65535 then return end |
|
|
|
|
for i = 1, total do |
|
|
|
|
local chunk = strsub(encoded, (i - 1) * CHUNK_SIZE + 1, i * CHUNK_SIZE) |
|
|
|
|
local msg = strjoin("|", COMM_PREFIX, hash, i .. "/" .. total, chunk) |
|
|
|
|
local msg = COMM_PREFIX .. string.format("%08x%04x%04x", tonumber(hash), i, total) .. chunk |
|
|
|
|
SendChatMessage(msg, "CHANNEL", nil, private.channelId) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
@ -166,17 +159,22 @@ end
|
|
|
|
|
|
|
|
|
|
function ChannelSync:OnChannelMessage(_, msg, source, _, _, _, _, _, channelName) |
|
|
|
|
if channelName ~= CHANNEL_NAME then return end |
|
|
|
|
if strsub(msg or "", 1, #COMM_PREFIX + 1) ~= COMM_PREFIX .. "|" then return end |
|
|
|
|
if strsub(msg or "", 1, #COMM_PREFIX) ~= COMM_PREFIX then return end |
|
|
|
|
|
|
|
|
|
source = ("-"):split(source or "") |
|
|
|
|
if strlower(source or "") == strlower(UnitName("player") or "") then return end |
|
|
|
|
|
|
|
|
|
local header, hash, seqInfo, chunk = msg:match("^(.-)|([^|]+)|([^|]+)|(.+)$") |
|
|
|
|
if header ~= COMM_PREFIX or not hash or not seqInfo or not chunk then return end |
|
|
|
|
|
|
|
|
|
local seq, total = seqInfo:match("^(%d+)%/(%d+)$") |
|
|
|
|
seq, total = tonumber(seq), tonumber(total) |
|
|
|
|
if not seq or not total then return end |
|
|
|
|
local headerLen = #COMM_PREFIX + 16 |
|
|
|
|
if #msg <= headerLen then return end |
|
|
|
|
local meta = strsub(msg, #COMM_PREFIX + 1, headerLen) |
|
|
|
|
local chunk = strsub(msg, headerLen + 1) |
|
|
|
|
local hashHex = strsub(meta, 1, 8) |
|
|
|
|
local seqHex = strsub(meta, 9, 12) |
|
|
|
|
local totalHex = strsub(meta, 13, 16) |
|
|
|
|
local hash = tonumber(hashHex, 16) |
|
|
|
|
local seq = tonumber(seqHex, 16) |
|
|
|
|
local total = tonumber(totalHex, 16) |
|
|
|
|
if not hash or not seq or not total then return end |
|
|
|
|
|
|
|
|
|
local bundle = private.incoming[hash] |
|
|
|
|
if not bundle or (time() - bundle.time) > BUNDLE_TIMEOUT then |
|
|
|
|
|