Initial code push
This commit is contained in:
141
Client/CMH.lua
Normal file
141
Client/CMH.lua
Normal file
@ -0,0 +1,141 @@
|
||||
local CMH = {}
|
||||
|
||||
local links = {}
|
||||
|
||||
function CMH.OnReceive(self, event, prefix, _, Type, sender)
|
||||
if event == "CHAT_MSG_ADDON" and sender == UnitName("player") and Type == "WHISPER" then
|
||||
local source, functionId, link, linkCount, MSG = prefix:match("(%D)(%d%d)(%d%d%d)(%d%d%d)(.+)");
|
||||
if not source or not functionId or not link or not linkCount or not MSG then
|
||||
return
|
||||
end
|
||||
|
||||
if(source == "S") then
|
||||
functionId, link, linkCount = tonumber(functionId), tonumber(link), tonumber(linkCount);
|
||||
links[functionId] = links[functionId] or {count = 0};
|
||||
links[functionId][link] = MSG;
|
||||
links[functionId].count = links[functionId].count + 1;
|
||||
if (links[functionId].count ~= linkCount) then
|
||||
return
|
||||
end
|
||||
|
||||
local fullMessage = table.concat(links[functionId]);
|
||||
links[functionId] = {count = 0};
|
||||
|
||||
local VarTable = ParseMessage(fullMessage)
|
||||
if not VarTable then
|
||||
return
|
||||
end
|
||||
|
||||
if not(CMH[VarTable[1]]) then
|
||||
return
|
||||
end
|
||||
|
||||
local func = CMH[VarTable[1]][functionId]
|
||||
if func then
|
||||
_G[func](sender, VarTable)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local CMHFrame = CreateFrame("Frame")
|
||||
CMHFrame:RegisterEvent("CHAT_MSG_ADDON")
|
||||
CMHFrame:SetScript("OnEvent", CMH.OnReceive)
|
||||
|
||||
function RegisterServerResponses(config)
|
||||
if(CMH[config.Prefix]) then
|
||||
return;
|
||||
end
|
||||
|
||||
CMH[config.Prefix] = {}
|
||||
|
||||
for functionId, functionName in pairs(config.Functions) do
|
||||
CMH[config.Prefix][functionId] = functionName
|
||||
end
|
||||
end
|
||||
|
||||
function ParseMessage(str)
|
||||
local output = {}
|
||||
local valTemp = {}
|
||||
local typeTemp = {}
|
||||
local delim = {"♠", "♥", "♚", "♛", "♜"}
|
||||
|
||||
local valMatch = "[^"..table.concat(delim).."]+"
|
||||
local typeMatch = "["..table.concat(delim).."]+"
|
||||
|
||||
-- Get values
|
||||
for value in str:gmatch(valMatch) do
|
||||
table.insert(valTemp, value)
|
||||
end
|
||||
|
||||
-- Get type from delimiter
|
||||
for varType in str:gmatch(typeMatch) do
|
||||
for k, v in pairs(delim) do
|
||||
if(v == varType) then
|
||||
table.insert(typeTemp, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Convert value to correct type
|
||||
for k, v in pairs(valTemp) do
|
||||
local varType = typeTemp[k]
|
||||
if(varType == 3) then -- Ints
|
||||
v = tonumber(v)
|
||||
elseif(varType == 4) then -- Tables
|
||||
v = Smallfolk.loads(v, #v)
|
||||
elseif(varType == 5) then -- Booleans
|
||||
if(v == "true") then v = true else v = false end
|
||||
end
|
||||
table.insert(output, v)
|
||||
end
|
||||
|
||||
valTemp = nil
|
||||
typeTemp = nil
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function SendClientRequest(prefix, functionId, ...)
|
||||
-- ♠ = Prefix prefix
|
||||
-- ♥ = ArgumentPrefix for Strings
|
||||
-- ♚ = ArgumentPrefix for Ints
|
||||
-- ♛ = ArgumentPrefix for Tables
|
||||
-- ♜ = ArgumentPrefix for Boolean
|
||||
|
||||
local arg = {...}
|
||||
local splitLength = 230
|
||||
local msg = "♠" .. prefix
|
||||
|
||||
for _, v in pairs(arg) do
|
||||
if(type(v) == "string") then
|
||||
msg = msg .. "♥"
|
||||
elseif(type(v) == "number") then
|
||||
msg = msg .. "♚"
|
||||
elseif(type(v) == "table") then
|
||||
-- use Smallfolk to convert table structure to string
|
||||
v = Smallfolk.dumps(v)
|
||||
msg = msg .. "♛"
|
||||
elseif(type(v) == "boolean") then
|
||||
v = tostring(v)
|
||||
msg = msg .. "♜"
|
||||
end
|
||||
msg = msg .. v
|
||||
end
|
||||
|
||||
local splits = math.ceil(msg:len() / splitLength)
|
||||
local send
|
||||
local counter = 1
|
||||
for i=1, msg:len(), splitLength do
|
||||
send = string.format("%01s%03d%02d%02d", "C", functionId, counter, splits)
|
||||
if ((i + splitLength) > msg:len()) then
|
||||
send = send .. msg:sub(i, msg:len())
|
||||
else
|
||||
send = send .. msg:sub(i, i + splitLength - 1)
|
||||
end
|
||||
counter = counter + 1
|
||||
|
||||
SendAddonMessage(send, "", "WHISPER", UnitName("player"))
|
||||
end
|
||||
end
|
||||
8
Client/CMH.toc
Normal file
8
Client/CMH.toc
Normal file
@ -0,0 +1,8 @@
|
||||
## Interface: 30300
|
||||
## Title: CMH
|
||||
## Notes: Client & Server Message Handler framework for communication between server and client.
|
||||
## Version: 1.0
|
||||
## Author: Foereaper, Stoneharry, Terrorblade
|
||||
|
||||
smallfolk.lua
|
||||
CMH.lua
|
||||
152
Client/FrameXML.toc
Normal file
152
Client/FrameXML.toc
Normal file
@ -0,0 +1,152 @@
|
||||
# Do not delete the following line!
|
||||
## Interface: 30300
|
||||
##DebugHook.lua
|
||||
GlobalStrings.lua
|
||||
Constants.lua
|
||||
Fonts.xml
|
||||
FontStyles.xml
|
||||
Localization.xml
|
||||
## add new modules below here
|
||||
|
||||
## CMH START
|
||||
smallfolk.lua
|
||||
CMH.lua
|
||||
## CMH END
|
||||
|
||||
BasicControls.xml
|
||||
WorldFrame.xml
|
||||
UIParent.xml
|
||||
AnimTimerFrame.xml
|
||||
MoneyFrame.lua
|
||||
MoneyFrame.xml
|
||||
MoneyInputFrame.lua
|
||||
MoneyInputFrame.xml
|
||||
GameTooltip.xml
|
||||
UIMenu.xml
|
||||
UIDropDownMenu.xml
|
||||
UIPanelTemplates.lua
|
||||
UIPanelTemplates.xml
|
||||
SecureTemplates.xml
|
||||
SecureHandlerTemplates.xml
|
||||
ItemButtonTemplate.xml
|
||||
SparkleFrame.xml
|
||||
HybridScrollFrame.lua
|
||||
HybridScrollFrame.xml
|
||||
GameMenuFrame.xml
|
||||
CharacterFrameTemplates.xml
|
||||
TextStatusBar.lua
|
||||
TextStatusBar.xml
|
||||
UIErrorsFrame.xml
|
||||
AutoComplete.xml
|
||||
StaticPopup.xml
|
||||
Sound.lua
|
||||
OptionsFrameTemplates.xml
|
||||
OptionsPanelTemplates.xml
|
||||
VideoOptionsFrame.xml
|
||||
VideoOptionsPanels.xml
|
||||
AudioOptionsFrame.xml
|
||||
AudioOptionsPanels.xml
|
||||
InterfaceOptionsFrame.xml
|
||||
InterfaceOptionsPanels.xml
|
||||
AlertFrames.xml
|
||||
MirrorTimer.xml
|
||||
CoinPickupFrame.xml
|
||||
StackSplitFrame.xml
|
||||
FadingFrame.xml
|
||||
ZoneText.xml
|
||||
BattlefieldFrame.xml
|
||||
MainMenuBar.xml
|
||||
MainMenuBarMicroButtons.xml
|
||||
TutorialFrame.xml
|
||||
Minimap.xml
|
||||
GameTime.xml
|
||||
Cooldown.xml
|
||||
ActionButtonTemplate.xml
|
||||
ActionBarFrame.xml
|
||||
MultiActionBars.xml
|
||||
##ActionWindow.xml
|
||||
BuffFrame.xml
|
||||
CombatFeedback.xml
|
||||
CastingBarFrame.xml
|
||||
UnitPopup.xml
|
||||
UnitFrame.xml
|
||||
BNet.xml
|
||||
HistoryKeeper.lua
|
||||
BNConversations.xml
|
||||
ChatFrame.xml
|
||||
FloatingChatFrame.xml
|
||||
VoiceChat.xml
|
||||
ReadyCheck.xml
|
||||
PlayerFrame.xml
|
||||
PartyFrame.xml
|
||||
TargetFrame.xml
|
||||
TotemFrame.xml
|
||||
PetFrame.xml
|
||||
StatsFrame.xml
|
||||
SpellBookFrame.xml
|
||||
CharacterFrame.xml
|
||||
EquipmentManager.lua
|
||||
PaperDollFrame.xml
|
||||
PetPaperDollFrame.xml
|
||||
SkillFrame.xml
|
||||
ReputationFrame.xml
|
||||
HonorFrame.xml
|
||||
QuestFrame.xml
|
||||
QuestPOI.xml
|
||||
WatchFrame.xml
|
||||
QuestLogFrame.xml
|
||||
QuestInfo.xml
|
||||
MerchantFrame.xml
|
||||
TradeFrame.xml
|
||||
ContainerFrame.xml
|
||||
LootFrame.xml
|
||||
ItemTextFrame.xml
|
||||
TaxiFrame.xml
|
||||
BankFrame.xml
|
||||
FriendsFrame.xml
|
||||
RaidFrame.xml
|
||||
ChannelFrame.xml
|
||||
PetActionBarFrame.xml
|
||||
MultiCastActionBarFrame.xml
|
||||
BonusActionBarFrame.xml
|
||||
MainMenuBarBagButtons.xml
|
||||
WorldMapFrame.xml
|
||||
CinematicFrame.xml
|
||||
ItemRef.xml
|
||||
ComboFrame.xml
|
||||
TabardFrame.xml
|
||||
GuildRegistrarFrame.xml
|
||||
PetitionFrame.xml
|
||||
HelpFrame.xml
|
||||
KnowledgeBaseFrame.xml
|
||||
ColorPickerFrame.xml
|
||||
GossipFrame.xml
|
||||
MailFrame.xml
|
||||
PetStable.xml
|
||||
DurabilityFrame.xml
|
||||
WorldStateFrame.xml
|
||||
DressUpFrame.xml
|
||||
RaidWarning.xml
|
||||
ClassTrainerFrameTemplates.xml
|
||||
PVPFrame.xml
|
||||
PVPBattlegroundFrame.xml
|
||||
ArenaFrame.xml
|
||||
ArenaRegistrarFrame.xml
|
||||
LFGFrame.xml
|
||||
LFDFrame.xml
|
||||
LFRFrame.xml
|
||||
MovieRecordingProgress.xml
|
||||
MacOptionsFrame.xml
|
||||
RatingMenuFrame.xml
|
||||
TalentFrameBase.lua
|
||||
TalentFrameTemplates.xml
|
||||
RuneFrame.xml
|
||||
EasyMenu.lua
|
||||
ChatConfigFrame.xml
|
||||
MovieFrame.xml
|
||||
VehicleMenuBar.xml
|
||||
AlternatePowerBar.xml
|
||||
AnimationSystem.lua
|
||||
|
||||
## add new modules above here
|
||||
LocalizationPost.xml
|
||||
218
Client/smallfolk.lua
Normal file
218
Client/smallfolk.lua
Normal file
@ -0,0 +1,218 @@
|
||||
local M = {}
|
||||
Smallfolk = M
|
||||
local expect_object, dump_object
|
||||
local error, tostring, pairs, type, floor, huge, concat = error, tostring, pairs, type, math.floor, math.huge, table.concat
|
||||
|
||||
local dump_type = {}
|
||||
|
||||
function dump_type:string(nmemo, memo, acc)
|
||||
local nacc = #acc
|
||||
acc[nacc + 1] = '"'
|
||||
acc[nacc + 2] = self:gsub('"', '""')
|
||||
acc[nacc + 3] = '"'
|
||||
return nmemo
|
||||
end
|
||||
|
||||
function dump_type:number(nmemo, memo, acc)
|
||||
acc[#acc + 1] = ("%.17g"):format(self)
|
||||
return nmemo
|
||||
end
|
||||
|
||||
function dump_type:table(nmemo, memo, acc)
|
||||
--[[
|
||||
if memo[self] then
|
||||
acc[#acc + 1] = '@'
|
||||
acc[#acc + 1] = tostring(memo[self])
|
||||
return nmemo
|
||||
end
|
||||
nmemo = nmemo + 1
|
||||
]]
|
||||
memo[self] = nmemo
|
||||
acc[#acc + 1] = '{'
|
||||
local nself = #self
|
||||
for i = 1, nself do -- don't use ipairs here, we need the gaps
|
||||
nmemo = dump_object(self[i], nmemo, memo, acc)
|
||||
acc[#acc + 1] = ','
|
||||
end
|
||||
for k, v in pairs(self) do
|
||||
if type(k) ~= 'number' or floor(k) ~= k or k < 1 or k > nself then
|
||||
nmemo = dump_object(k, nmemo, memo, acc)
|
||||
acc[#acc + 1] = ':'
|
||||
nmemo = dump_object(v, nmemo, memo, acc)
|
||||
acc[#acc + 1] = ','
|
||||
end
|
||||
end
|
||||
acc[#acc] = acc[#acc] == '{' and '{}' or '}'
|
||||
return nmemo
|
||||
end
|
||||
|
||||
function dump_object(object, nmemo, memo, acc)
|
||||
if object == true then
|
||||
acc[#acc + 1] = 't'
|
||||
elseif object == false then
|
||||
acc[#acc + 1] = 'f'
|
||||
elseif object == nil then
|
||||
acc[#acc + 1] = 'n'
|
||||
elseif object ~= object then
|
||||
if (''..object):sub(1,1) == '-' then
|
||||
acc[#acc + 1] = 'N'
|
||||
else
|
||||
acc[#acc + 1] = 'Q'
|
||||
end
|
||||
elseif object == huge then
|
||||
acc[#acc + 1] = 'I'
|
||||
elseif object == -huge then
|
||||
acc[#acc + 1] = 'i'
|
||||
else
|
||||
local t = type(object)
|
||||
if not dump_type[t] then
|
||||
error('cannot dump type ' .. t)
|
||||
end
|
||||
return dump_type[t](object, nmemo, memo, acc)
|
||||
end
|
||||
return nmemo
|
||||
end
|
||||
|
||||
function M.dumps(object)
|
||||
local nmemo = 0
|
||||
local memo = {}
|
||||
local acc = {}
|
||||
dump_object(object, nmemo, memo, acc)
|
||||
return concat(acc)
|
||||
end
|
||||
|
||||
local function invalid(i)
|
||||
error('invalid input at position ' .. i)
|
||||
end
|
||||
|
||||
local nonzero_digit = {['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true}
|
||||
local is_digit = {['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, ['5'] = true, ['6'] = true, ['7'] = true, ['8'] = true, ['9'] = true}
|
||||
local function expect_number(string, start)
|
||||
local i = start
|
||||
local head = string:sub(i, i)
|
||||
if head == '-' then
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
end
|
||||
if nonzero_digit[head] then
|
||||
repeat
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
until not is_digit[head]
|
||||
elseif head == '0' then
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
else
|
||||
invalid(i)
|
||||
end
|
||||
if head == '.' then
|
||||
local oldi = i
|
||||
repeat
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
until not is_digit[head]
|
||||
if i == oldi + 1 then
|
||||
invalid(i)
|
||||
end
|
||||
end
|
||||
if head == 'e' or head == 'E' then
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
if head == '+' or head == '-' then
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
end
|
||||
if not is_digit[head] then
|
||||
invalid(i)
|
||||
end
|
||||
repeat
|
||||
i = i + 1
|
||||
head = string:sub(i, i)
|
||||
until not is_digit[head]
|
||||
end
|
||||
return tonumber(string:sub(start, i - 1)), i
|
||||
end
|
||||
|
||||
local expect_object_head = {
|
||||
t = function(string, i) return true, i end,
|
||||
f = function(string, i) return false, i end,
|
||||
n = function(string, i) return nil, i end,
|
||||
Q = function(string, i) return -(0/0), i end,
|
||||
N = function(string, i) return 0/0, i end,
|
||||
I = function(string, i) return 1/0, i end,
|
||||
i = function(string, i) return -1/0, i end,
|
||||
['"'] = function(string, i)
|
||||
local nexti = i - 1
|
||||
repeat
|
||||
nexti = string:find('"', nexti + 1, true) + 1
|
||||
until string:sub(nexti, nexti) ~= '"'
|
||||
return string:sub(i, nexti - 2):gsub('""', '"'), nexti
|
||||
end,
|
||||
['0'] = function(string, i)
|
||||
return expect_number(string, i - 1)
|
||||
end,
|
||||
['{'] = function(string, i, tables)
|
||||
local nt, k, v = {}
|
||||
local j = 1
|
||||
tables[#tables + 1] = nt
|
||||
if string:sub(i, i) == '}' then
|
||||
return nt, i + 1
|
||||
end
|
||||
while true do
|
||||
k, i = expect_object(string, i, tables)
|
||||
if string:sub(i, i) == ':' then
|
||||
v, i = expect_object(string, i + 1, tables)
|
||||
nt[k] = v
|
||||
else
|
||||
nt[j] = k
|
||||
j = j + 1
|
||||
end
|
||||
local head = string:sub(i, i)
|
||||
if head == ',' then
|
||||
i = i + 1
|
||||
elseif head == '}' then
|
||||
return nt, i + 1
|
||||
else
|
||||
invalid(i)
|
||||
end
|
||||
end
|
||||
end,
|
||||
--[[
|
||||
['@'] = function(string, i, tables)
|
||||
local match = string:match('^%d+', i)
|
||||
local ref = tonumber(match)
|
||||
if tables[ref] then
|
||||
return tables[ref], i + #match
|
||||
end
|
||||
invalid(i)
|
||||
end,
|
||||
]]
|
||||
}
|
||||
expect_object_head['1'] = expect_object_head['0']
|
||||
expect_object_head['2'] = expect_object_head['0']
|
||||
expect_object_head['3'] = expect_object_head['0']
|
||||
expect_object_head['4'] = expect_object_head['0']
|
||||
expect_object_head['5'] = expect_object_head['0']
|
||||
expect_object_head['6'] = expect_object_head['0']
|
||||
expect_object_head['7'] = expect_object_head['0']
|
||||
expect_object_head['8'] = expect_object_head['0']
|
||||
expect_object_head['9'] = expect_object_head['0']
|
||||
expect_object_head['-'] = expect_object_head['0']
|
||||
expect_object_head['.'] = expect_object_head['0']
|
||||
|
||||
expect_object = function(string, i, tables)
|
||||
local head = string:sub(i, i)
|
||||
if expect_object_head[head] then
|
||||
return expect_object_head[head](string, i + 1, tables)
|
||||
end
|
||||
invalid(i)
|
||||
end
|
||||
|
||||
function M.loads(string, maxsize)
|
||||
if #string > (maxsize or 10000) then
|
||||
error 'input too large'
|
||||
end
|
||||
return (expect_object(string, 1, {}))
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user