local _ , addonTable = ...
local Serialization = { }
-- Upvalues
local R = Rarity
-- Externals
local compress = LibStub ( " LibCompress " )
local L = LibStub ( " AceLocale-3.0 " ) : GetLocale ( " Rarity " )
-- Lua APIs
local tonumber = tonumber
local pairs = pairs
local type = type
local CONSTANTS = addonTable.constants
local FormatTime = Rarity.Utils . PrettyPrint.FormatTime -- Utils are loaded before Core modules, so this should be fine
--- Sets some default values for items (used before importing them)?
--- TODO: LuaDoc
function Serialization : CleanItemForImport ( item )
item.attempts = 0
item.lastAttempts = 0
item.enabled = true
item.found = false
item.enableAnnouncements = true
item.holidayReminder = true
end
--- Returns true if an item has a valid format ?
-- TODO: LuaDoc
function Serialization : CanItemBeExportedImported ( item )
if not item then
return false
end
if not item.method then
return false
end
if not item.type then
return false
end
if not item.itemId or tonumber ( item.itemId ) == nil or item.itemId <= 0 then
return false
end
if not item.chance or tonumber ( item.chance ) == nil or item.chance <= 0 then
return false
end
if item.method == CONSTANTS.DETECTION_METHODS . COLLECTION then
if not item.collectedItemId or tonumber ( item.collectedItemId ) == nil or item.collectedItemId <= 0 then
return false
end
end
if item.type ~= CONSTANTS.ITEM_TYPES . ITEM then
if not item.spellId or tonumber ( item.spellId ) == nil or item.spellId <= 0 then
return false
end
end
if item.type == CONSTANTS.ITEM_TYPES . PET then
if not item.creatureId or tonumber ( item.creatureId ) == nil or item.creatureId <= 0 then
return false
end
end
if item.method == CONSTANTS.DETECTION_METHODS . ARCH then
if not item.raceId or tonumber ( item.raceId ) == nil or item.raceId <= 0 then
return false
end
end
if item.method == CONSTANTS.DETECTION_METHODS . ZONE or item.method == CONSTANTS.DETECTION_METHODS . FISHING then
if not item.zones or # item.zones <= 0 then
return false
end
end
if item.method == CONSTANTS.DETECTION_METHODS . USE then
if not item.items or # item.items <= 0 then
return false
end
end
if item.method == CONSTANTS.DETECTION_METHODS . NPC or item.method == CONSTANTS.DETECTION_METHODS . BOSS then
if ( not item.npcs or # item.npcs <= 0 ) and ( not item.statisticId or # item.statisticId <= 0 ) then
return false
end
end
return true
end
--- Attempts to import data from the BunnyHunter addon?
-- This must be ancient, I've never even heard of it before...
-- TODO: LuaDoc
function Serialization : ImportFromBunnyHunter ( )
self = Rarity
if self.db . profile.importedFromBunnyHunter then
return
end
if BunnyHunterDB then
StaticPopupDialogs [ " RARITY_IMPORT_FROM_BUNNYHUNTER " ] = {
text = L [ " Bunny Hunter is running. Would you like Rarity to import data from Bunny Hunter now? Disable Bunny Hunter or click Yes if you don't want to be asked again. " ] ,
button1 = YES ,
button2 = NO ,
hideOnEscape = 1 ,
timeout = 0 ,
exclusive = 1 ,
whileDead = 1 ,
OnAccept = function ( )
self = Rarity
-- Do the import
if BunnyHunterDB.loots and type ( BunnyHunterDB.loots ) == " table " then
for k , v in pairs ( BunnyHunterDB.loots ) do
for groupkey , group in pairs ( self.db . profile.groups ) do
for itemkey , item in pairs ( group ) do
if item.itemId == tonumber ( k ) then
self : Debug ( " Resetting found record for %s " , itemkey )
item.finds = nil
item.totalFinds = nil
end
end
end
end
for k , v in pairs ( BunnyHunterDB.loots ) do
for groupkey , group in pairs ( self.db . profile.groups ) do
for itemkey , item in pairs ( group ) do
if item.itemId == tonumber ( k ) then
for kk , vv in pairs ( v ) do
self : Debug (
" %s: adding a kill after %d attempts, %s time " ,
itemkey ,
vv.loots ,
FormatTime ( vv.time )
)
if not item.finds then
item.finds = { }
end
local count = 0
for x , y in pairs ( item.finds ) do
count = count + 1
end
table.insert ( item.finds , {
num = count + 1 ,
totalAttempts = vv.loots ,
totalTime = vv.time ,
attempts = vv.loots ,
time = vv.time ,
} )
item.totalFinds = ( item.totalFinds or 0 ) + 1
end
end
end
end
end
end
if BunnyHunterDB.kills_by_id and type ( BunnyHunterDB.kills_by_id ) == " table " then
for k , v in pairs ( BunnyHunterDB.kills_by_id ) do
for groupkey , group in pairs ( self.db . profile.groups ) do
for itemkey , item in pairs ( group ) do
if item.npcs then
for npckey , npcid in pairs ( item.npcs ) do
if npcid == tonumber ( k ) then
self : Debug ( " Resetting attempts for %s " , itemkey )
item.attempts = 0
item.lastAttempts = nil
end
end
end
end
end
end
for k , v in pairs ( BunnyHunterDB.kills_by_id ) do
for groupkey , group in pairs ( self.db . profile.groups ) do
for itemkey , item in pairs ( group ) do
if item.npcs then
for npckey , npcid in pairs ( item.npcs ) do
if npcid == tonumber ( k ) then
self : Debug ( " %s: adding %d attempt(s) " , itemkey , v )
item.attempts = ( item.attempts or 0 ) + v
end
end
end
end
end
end
end
if BunnyHunterDB.times and type ( BunnyHunterDB.times ) == " table " then
for k , v in pairs ( BunnyHunterDB.times ) do
for groupkey , group in pairs ( self.db . profile.groups ) do
for itemkey , item in pairs ( group ) do
if item.itemId == tonumber ( k ) then
self : Debug ( " %s: updating time to %f " , itemkey , v )
item.time = v
item.lastTime = nil
end
end
end
end
end
self : UpdateInterestingThings ( )
Rarity.GUI : UpdateText ( )
-- if self:InTooltip() then self:ShowTooltip() end
self.db . profile.importedFromBunnyHunter = true
self : Print ( L [ " Data has been imported from Bunny Hunter " ] )
end ,
}
StaticPopup_Show ( " RARITY_IMPORT_FROM_BUNNYHUNTER " )
end
end
-- Compression encoding
local encode_translate = { [ 255 ] = " \255 \001 " , [ 0 ] = " \255 \002 " }
local function encode_helper ( char )
return encode_translate [ char : byte ( ) ]
end
local decode_translate = { [ " \001 " ] = " \255 " , [ " \002 " ] = " \000 " }
local function decode_helper ( text )
return decode_translate [ text ]
end
function R : Encode ( data )
return data : gsub ( " ([ \255 %z]) " , encode_helper )
end
function R : Decode ( data )
return data : gsub ( " \255 ([ \001 \002 ]) " , decode_helper )
end
function R : Compress ( data )
return self : Encode ( compress : Compress ( data ) )
end
function R : Decompress ( data )
return compress : Decompress ( self : Decode ( data ) )
end
local b = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ "
function Serialization : DecodeBase64 ( encodedString )
if not encodedString then
return nil
end
encodedString = string.gsub ( encodedString , " [^ " .. b .. " =] " , " " )
return (
encodedString
: gsub ( " . " , function ( x )
if x == " = " then
return " "
end
local r , f = " " , ( b : find ( x ) - 1 )
for i = 6 , 1 , - 1 do
r = r .. ( f % 2 ^ i - f % 2 ^ ( i - 1 ) > 0 and " 1 " or " 0 " )
end
return r
end )
: gsub ( " %d%d%d?%d?%d?%d?%d?%d? " , function ( x )
if # x ~= 8 then
return " "
end
local c = 0
for i = 1 , 8 do
c = c + ( x : sub ( i , i ) == " 1 " and 2 ^ ( 8 - i ) or 0 )
end
return string.char ( c )
end )
)
end
function Serialization : EncodeBase64 ( input )
return (
( input : gsub ( " . " , function ( x )
local r , byte = " " , x : byte ( )
for i = 8 , 1 , - 1 do
r = r .. ( byte % 2 ^ i - byte % 2 ^ ( i - 1 ) > 0 and " 1 " or " 0 " )
end
return r
end ) .. " 0000 " ) : gsub ( " %d%d%d?%d?%d?%d? " , function ( x )
if # x < 6 then
return " "
end
local c = 0
for i = 1 , 6 do
c = c + ( x : sub ( i , i ) == " 1 " and 2 ^ ( 6 - i ) or 0 )
end
return b : sub ( c + 1 , c + 1 )
end ) .. ( { " " , " == " , " = " } ) [ # input % 3 + 1 ]
)
end
function Serialization : DeserializeItemString ( compressedEncodedItemString )
local decodedItemString = self : DecodeBase64 ( compressedEncodedItemString )
local decompressedItemString = self : Decompress ( decodedItemString )
local success , deserializedItemEntry = R : Deserialize ( decompressedItemString )
assert ( success , " Failed to deserialize item string " )
return deserializedItemEntry
end
Serialization.Decode = R.Decode
Serialization.Decompress = R.Decompress
Rarity.Serialization = Serialization
return Serialization