mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
974 lines
No EOL
30 KiB
Lua
974 lines
No EOL
30 KiB
Lua
-- Thanks to Kenuvis for his great work on Gate.
|
|
-- For more info on the original code,
|
|
-- see the text file supplied with this code.
|
|
|
|
if (MapMgr == nil) then --Serverstart
|
|
if GetLuaEngine() == "ElunaEngine" then
|
|
print("[ElunaGate]: Loaded Server Side Framework!")
|
|
else
|
|
print("[Gate]: Unknown and unsupported LuaEngine")
|
|
return;
|
|
end
|
|
end
|
|
|
|
-- Definitions
|
|
|
|
-- These definitions should be identical to the client definitions.
|
|
local Gate = {
|
|
Prefix = "ElunaGate",
|
|
Version = "8",
|
|
StreamStart = "\129", --"§",
|
|
BlockStart = "\130", --"#",
|
|
BlockIdent = "\131", --"!",
|
|
StreamBlock = "\132", --"~",
|
|
StreamBlockEnd = "\133", --"!",
|
|
True = "\134", --"%",
|
|
False = "\135", --"&",
|
|
|
|
-- For New-Life
|
|
Insert = "\140",
|
|
EventInsert = "\141",
|
|
|
|
AllowNamelessObjects = false}
|
|
|
|
-- Shortforms of parameter. Every parameter listed here become a command and only if a parameter is listed here, it would send. Any other parameter stay at the server.
|
|
Gate.shortKeys = {
|
|
["Text"] = "t",
|
|
["Width"] = "w",
|
|
["Height"] = "h",
|
|
["Name"] = "n",
|
|
["Parent"] = "p",
|
|
["XOffset"] = "x",
|
|
["YOffset"] = "y",
|
|
["Offset"] = "o",
|
|
["StatusLink"] = "l",
|
|
["Event"] = "e",
|
|
["Tooltip"] = "tt",
|
|
["Hidden"] = "hi",
|
|
["FadeIn"] ="fi",
|
|
["FadeOut"] = "fo",
|
|
["Red"] = "r",
|
|
["Green"] = "g",
|
|
["Blue"] = "b",
|
|
["Alpha"] = "a",
|
|
["Style"] = "s",
|
|
["Cursor"] = "c",
|
|
|
|
-- Only for Frames
|
|
["CantClose"] = "cc",
|
|
["CantMove"] = "cm",
|
|
["InfoText"] = "in", -- also for Editbox and StatusBar !
|
|
["Front"] = "f",
|
|
["Tabbed"] = "tf",
|
|
["LeaveOpen"] = "lo",
|
|
["Texture"] = "tex",
|
|
-- Only for TabbedFrames
|
|
["Tab"] = "tab",
|
|
["SelectedTab"] = "st",
|
|
-- Only for Panels
|
|
["Border"] = "br",
|
|
["Background"] = "bg",
|
|
-- Only for Buttons
|
|
["Texture"] = "tex",
|
|
-- Only for EditBoxes
|
|
["MultiLine"] = "ml",
|
|
["MinValue"] = "min",
|
|
["MaxValue"] = "max",
|
|
-- Only for Check/Radiobuttons
|
|
["Checked"] = "ch",
|
|
-- Only for Yes/No-Frame
|
|
["Yes"] = "yes",
|
|
["No"] = "no",
|
|
-- Only for StaticPopUp
|
|
["Arg1"] = "1",
|
|
["Arg2"] = "2",
|
|
-- Only for Statusbar/Slider
|
|
["MinValue"] = "min",
|
|
["MaxValue"] = "max",
|
|
["ValueStep"] = "stp",
|
|
["Value"] = "val",
|
|
["Countdown"] = "cd",
|
|
["LowText"] = "lt",
|
|
["HighText"] = "ht",
|
|
["AutoReset"] = "ar",
|
|
["Flow"] = "fl",
|
|
["RunBack"] = "rb",
|
|
["Vertical"] = "ve",
|
|
-- Only for LinkExsits
|
|
["Version"] = "v",
|
|
["Component"] = "cmd",
|
|
-- Only for Minimapbuttons
|
|
["Texture"] = "tex",
|
|
["Degree"] = "deg",
|
|
-- Only for GetStatus
|
|
["GetType"] = "gt",
|
|
-- Only for DropDownMenus
|
|
["DropDownItem"] = "ddi",
|
|
["SelectedItem"] = "si",
|
|
-- Only for ListBox
|
|
["ListBoxItem"] = "lbi",
|
|
-- Only for InputFrames
|
|
["ButtonText"] = "bt",
|
|
["FrameText"] = "ft",
|
|
["DontCloseAfterSend"] = "dc",
|
|
-- Only for TextBoxes
|
|
["TextHeight"] = "th",
|
|
-- Only for Keybind
|
|
["Key"] = "ky"}
|
|
|
|
-- The Masterobject
|
|
-- Its funny, because its only a metatable, which simulate existing commands. Every Get/Set/Change/Create command is here! Easy and usefull.
|
|
local GateObject = {}
|
|
local GateObject_MT = {__index =
|
|
function (Obj, Type)
|
|
-- we parse and see, what we have to give it in the right way
|
|
local oType = string.match(Type, "Create(%w+)")
|
|
if oType then
|
|
return function (_, Name, Parameter)
|
|
Parameter = Parameter or {}
|
|
Parameter.Parent = Obj.Name
|
|
|
|
return CreateObject(oType, Name, Parameter, 3)
|
|
end
|
|
end
|
|
|
|
oType = string.match(Type, "Get(%w+)")
|
|
if oType then
|
|
local newoType, status = string.gsub(oType, "FromPlayer", "")
|
|
return function (func, ...)
|
|
if status > 0 and Gate.shortKeys[newoType] then
|
|
Reg_Gate_Event("Get"..newoType.."from"..Obj.Name,
|
|
function(event, Player, Message)
|
|
func(Obj, Player, Message[1])
|
|
-- I know, the memory ...
|
|
--Del_Gate_Event("Get"..newoType.."from"..Obj.Name)
|
|
end)
|
|
|
|
local Stream = Gate:CreateNewGateStream("getstatus")
|
|
Stream:AddParameter("Name", Obj.Name)
|
|
Stream:AddParameter("GetType", newoType)
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
else
|
|
return Obj[newoType]
|
|
end
|
|
end
|
|
end
|
|
|
|
oType = string.match(Type, "Set(%w+)")
|
|
if oType then
|
|
return function (_, Value)
|
|
if type(Value) == "table" then
|
|
Value = Value.Name
|
|
end
|
|
|
|
if type(Value) == "string" then
|
|
if string.find(Value, Gate.StreamStart) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.StreamStart, 2)
|
|
elseif string.find(Value, Gate.BlockStart) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.BlockStart, 2)
|
|
elseif string.find(Value, Gate.BlockIdent) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.BlockIdent, 2)
|
|
elseif string.find(Value, Gate.StreamBlock) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.StreamBlock, 2)
|
|
elseif string.find(Value, Gate.StreamBlockEnd) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.StreamBlockEnd, 2)
|
|
elseif string.find(Value, Gate.True) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.True, 2)
|
|
elseif string.find(Value, Gate.False) then
|
|
error(Gate.Prefix..": Invalid character in "..Type.." "..Gate.False, 2)
|
|
end
|
|
end
|
|
|
|
-- Objectchange to Changeset
|
|
if Obj._ChangeSet then
|
|
table.insert(Obj._ChangeSet.Changes, {Object = Obj, Key = oType, Value = Value})
|
|
--Obj._ChangeSet = nil
|
|
else
|
|
Obj[oType] = Value
|
|
end
|
|
return Obj
|
|
end
|
|
end
|
|
return nil --function() error(Gate.Prefix..": Invalid command "..Type, 2) end
|
|
end}
|
|
|
|
-- Every Object have to save, so an event can dedicated to an object an start the action
|
|
Gate.SavedObjects = {}
|
|
|
|
-- Allowed Events and Objects with some parameter
|
|
Gate.specialEvent = {}
|
|
Gate.Events = {
|
|
["NoEvents"] = {id = 0},
|
|
["OnClick"] = {id = 10},
|
|
["OnDoubleClick"] = {id = 11},
|
|
["OnHide"] = {id = 12},
|
|
["OnEnter"] = {id = 13},
|
|
["OnEnterPressed"] = {id = 14},
|
|
["OnKeyDown"] = {id = 15}}
|
|
|
|
Gate.Objects = {
|
|
["Frame"] = {Type = "frame"},
|
|
["BlindFrame"] = {Type = "bf", CantChange = true},
|
|
["TabbedFrame"] = {Type = "tf"},
|
|
["Button"] = {Type = "btn"},
|
|
["CheckBox"] = {Type = "cb"},
|
|
["CheckButton"] = {Type = "cb"},
|
|
["RadioButton"] = {Type = "rb"},
|
|
["RadioBox"] = {Type = "rb"},
|
|
["EditBox"] = {Type = "eb"},
|
|
["InputBox"] = {Type = "eb"},
|
|
["TextBox"] = {Type = "tb"},
|
|
["StatusBar"] = {Type = "sb"},
|
|
["Slider"] = {Type = "sl"},
|
|
["Panel"] = {Type = "pl"},
|
|
["ListBox"] = {Type = "lb", CantParent = true, CantChange = true},
|
|
["DropDownMenu"] = {Type = "ddm", CantParent = true, CantChange = true},
|
|
["CursorKeys"] = {Type = "ck", CantParent = true, CantChange = true},
|
|
["DialogFrame"] = {Type = "df", CantParent = true, CantChild = true, CantChange = true},
|
|
["InputFrame"] = {Type = "if", CantParent = true, CantChild = true, CantChange = true},
|
|
["EditFrame"] = {Type = "if", CantParent = true, CantChild = true, CantChange = true},
|
|
["OkFrame"] = {Type = "of", CantParent = true, CantChild = true, CantChange = true},
|
|
["YesNoFrame"] = {Type = "yn", CantParent = true, CantChild = true, CantChange = true},
|
|
["StaticPopup"] = {Type = "sb", CantParent = true, CantChild = true, CantChange = true},
|
|
["StaticFrame"] = {Type = "sf", CantParent = true, CantChange = true},
|
|
["MinimapButton"] = {Type = "mmb", CantParent = true, CantChild = true, CantChange = true},
|
|
["SlashCommand"] = {Type = "slash", CantParent = true, CantChild = true, CantChange = true},
|
|
["Action"] = {Type = "action", CantParent = true, CantChild = true, CantChange = true},
|
|
["KeyBind"] = {Type = "kb", CantParent = true, CantChild = true, CantChange = true},
|
|
["Event"] = {Type = "ev", CantParent = true, CantChild = true, CantChange = true}}
|
|
|
|
-- Every Object get his own Createcommand without a parent object
|
|
for Type,Obj in pairs(Gate.Objects) do
|
|
_G["Create"..Type] = function (Name, Parameter) return CreateObject(Type, Name, Parameter, 3) end
|
|
end
|
|
|
|
-- a simple way to combinate two tables
|
|
table.combine = function(master,slave)
|
|
slave = slave or {}
|
|
master = master or {}
|
|
if type(slave) ~= "table" or type(master) ~= "table" then return master end
|
|
for k,v in pairs(slave) do
|
|
master[k] = master[k] or v
|
|
end
|
|
return master
|
|
end
|
|
|
|
-- [[Outsource]]
|
|
|
|
-- Here, with this 3 commands, you can create your own objects/moduls
|
|
-- If you understood Gate, I should explain this.
|
|
|
|
function Reg_Gate_Object(Name, ident, CantChild, CantParent)
|
|
Gate.Objects[Name] = {Type = ident, CantChild = CantChild, CantParent = CantParent}
|
|
_G["Create"..Name] = function (ObjName, Parameter) return CreateObject(Name, ObjName, Parameter, 3) end
|
|
return Gate
|
|
end
|
|
|
|
function Reg_Gate_shortKeys(Key, Short)
|
|
Gate.shortKeys[Key] = Short
|
|
end
|
|
|
|
function Reg_Gate_Event(ident, func)
|
|
Gate.specialEvent[ident] = func
|
|
end
|
|
|
|
function Del_Get_Event(ident)
|
|
Gate.specialEvent[ident] = nil
|
|
end
|
|
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------- Changeset-handle -----------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
function CreateChangeSet()
|
|
local ChangeSet = {}
|
|
|
|
ChangeSet.Changes = {}
|
|
function ChangeSet:Send(...)
|
|
local msg = ""
|
|
for _,Change in ipairs(self.Changes) do
|
|
if Change then
|
|
local Stream = Gate:CreateNewGateStream(Change.Object.Type)
|
|
Stream:AddParameter("Name", Change.Object.Name)
|
|
Stream:AddParameter(Change.Key, Change.Value)
|
|
msg = msg..Stream.msg
|
|
Stream:Clear()
|
|
Change.Object._ChangeSet = nil
|
|
end
|
|
end
|
|
Gate:Send(msg, ...)
|
|
end
|
|
function ChangeSet:Clear()
|
|
self.Changes = {}
|
|
end
|
|
function ChangeSet:RemoveChange(Name, Key)
|
|
for index,Change in ipairs(self.Changes) do
|
|
if Change.Name == Name and ((Key and Key == Change.Key) or not Key) then
|
|
self.Changes[index] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function ChangeSet:AddObject(...)
|
|
local a = 1
|
|
local Objects = {}
|
|
while select(a, ...) do
|
|
local Object = GetObject(select(a, ...))
|
|
if Object.CantChange then
|
|
print(Gate.Prefix..": "..Object.Type.." cannot be part of a changeset!")
|
|
Object = nil
|
|
end
|
|
if Object then
|
|
Object._ChangeSet = self
|
|
end
|
|
Objects[a] = Object
|
|
a = a + 1
|
|
end
|
|
|
|
return unpack(Objects)
|
|
end
|
|
|
|
return ChangeSet
|
|
end
|
|
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------- Object-handle --------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
-- No need to explain
|
|
function Gate:SaveObject(Name, Object)
|
|
--[[ if Gate.SavedObjects[Name] then
|
|
print(Gate.Prefix..": Object ["..Name.."] was overwrite!")
|
|
end]]
|
|
Gate.SavedObjects[Name] = Object
|
|
end
|
|
|
|
function GetObject(Name)
|
|
if type(Name) == "table" then
|
|
return Name
|
|
else
|
|
return Gate.SavedObjects[Name]
|
|
end
|
|
end
|
|
|
|
function NewFrame(Stream) -- Stream have to come from the Builder
|
|
local SObject = {} -- StreamObject
|
|
SObject.ToSend = ""
|
|
|
|
for byte in string.gfind(Stream, "(%w%w)") do
|
|
SObject.ToSend = SObject.ToSend..string.char(tonumber("0x"..byte))
|
|
end
|
|
|
|
function SObject:Send(...)
|
|
if string.find(self.ToSend, Gate.EventInsert) then
|
|
error(Gate.Prefix..": There is an unhandled Event in the NewFrame and this cannot be send!", 2)
|
|
end
|
|
Gate:Send(self.ToSend, ...)
|
|
end
|
|
|
|
for name in string.gfind(SObject.ToSend, Gate.Insert.."(%w+)"..Gate.Insert) do
|
|
SObject[name] = function(self,Value) self.ToSend = string.gsub(self.ToSend, Gate.Insert..name..Gate.Insert, Value) end
|
|
end
|
|
|
|
for Event, Object, Eventfunc in string.gfind(SObject.ToSend, Gate.EventInsert.."(%w+)%s(%w+)%s(%w+)"..Gate.EventInsert) do
|
|
assert(Gate.Events[Event], Gate.Prefix..": Invalid "..Event.." Event in NewFrame for "..Object)
|
|
|
|
local NewObject = GetObject(Object) or {}
|
|
if not NewObject.Events then NewObject.Events = {} end
|
|
NewObject.Events[Event] = Eventfunc
|
|
Gate:SaveObject(Object, NewObject)
|
|
|
|
SObject.ToSend = string.gsub(SObject.ToSend, Gate.EventInsert..Event.." "..Object.." "..Eventfunc..Gate.EventInsert, Gate.Events[Event].id)
|
|
end
|
|
|
|
return SObject
|
|
end
|
|
|
|
-- Every Object would created here. If you know, what you do, you dont need the CreateFrame commands, only this!
|
|
function CreateObject(Type, Name, Parameter, ErrLevel)
|
|
local func
|
|
if type(Parameter) == "function" then
|
|
func = Parameter
|
|
Parameter = {}
|
|
end
|
|
|
|
Parameter = Parameter or {}
|
|
Parameter.Name = Parameter.Name or Name
|
|
|
|
-- Some rules and errors
|
|
if not Type or not Gate.Objects[Type] then
|
|
error(Gate.Prefix..": Invalid ObjectType", ErrLevel)
|
|
elseif not Name then
|
|
if not Gate.AllowNamelessObjects then
|
|
error(Gate.Prefix..":Cannot create a nameless "..Type..". Usage: Create"..Type.."(\"Name\", [{Parameter}])", ErrLevel)
|
|
else
|
|
Parameter.Name = Type..tostring(os.time())
|
|
end
|
|
elseif Parameter.Parent then
|
|
if Gate.Objects[Type].CantChild then
|
|
error(Gate.Prefix..": "..Parameter.Name.." cannot get a parent", ErrLevel)
|
|
elseif not Gate.SavedObjects[Parameter.Parent] then
|
|
error(Gate.Prefix..": "..Parameter.Parent.." as parent for "..Parameter.Name.." not found", ErrLevel)
|
|
elseif Gate.SavedObjects[Parameter.Parent].CantParent then
|
|
error(Gate.Prefix..":The parent of "..Parameter.Name.." cannot be "..Parameter.Parent, ErrLevel)
|
|
else
|
|
table.insert(Gate.SavedObjects[Parameter.Parent].Childs, Parameter.Name)
|
|
end
|
|
end
|
|
|
|
-- Now we create, save and return the object for handling
|
|
local Object = {}
|
|
|
|
Object = table.combine(Object, GateObject)
|
|
Object = table.combine(Object, Gate.Objects[Type])
|
|
Object = table.combine(Object, Parameter)
|
|
|
|
Object.Childs = {}
|
|
Object.Event = {}
|
|
Object.Events = {}
|
|
Object.StatusLink = {}
|
|
|
|
-- Standard Events for special Objects
|
|
if Type == "SlashCommand" then
|
|
Object.Events["Slash"] = func
|
|
Object.Text = Parameter.Name
|
|
elseif Type == "MinimapButton" then
|
|
Object.Events["OnClick"] = func
|
|
elseif Type == "Event" then
|
|
Gate.specialEvent[Name] = func
|
|
end
|
|
|
|
setmetatable(Object, GateObject_MT)
|
|
Gate:SaveObject(Parameter.Name, Object)
|
|
|
|
return Object
|
|
end
|
|
|
|
-- how a command work, is easy.
|
|
function SendSystemMessage(Message, ...)
|
|
-- Frist, we should Create a new Stream (because it's a new Command for the Client)
|
|
-- Here, we need the identificator for the Client, which should know, what to do
|
|
local Stream = Gate:CreateNewGateStream("sys")
|
|
-- Now we add as many paramenter as we want and need f¨¹r this command
|
|
Stream:AddParameter("Text", Message)
|
|
-- Finally, we should send it ^^
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
-- Same like "function SendSystemMessage"
|
|
function ShowStaticPopup(Name, arg1, arg2, ...)
|
|
local Stream = Gate:CreateNewGateStream("sp")
|
|
Stream:AddParameter("Name", Name)
|
|
if arg1 then Stream:AddParameter("Arg1", arg1) end
|
|
if arg2 then Stream:AddParameter("Arg2", arg2) end
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
-- Here, we compare the version and if the object, the user asked, is handled by the client
|
|
Gate.LinkCheck = {}
|
|
function LinkExists(Link, func, ...)
|
|
assert(Gate.Objects[Link], Link.." is not handled by the Server")
|
|
|
|
local Stream = Gate:CreateNewGateStream("version")
|
|
Stream:AddParameter("Version", Gate.Version)
|
|
Stream:AddParameter("Component", Gate.Objects[Link].Type)
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
|
|
-- This command should trigger a returnmessage, so we handle it like a event
|
|
Gate.LinkCheck[string.lower(Link)] = func
|
|
end
|
|
|
|
-- If the user only want to know, if gate is running on the player, we use the LinkExists command and ask for frame, because
|
|
-- its a basic object and this have to supported in gate since the first version
|
|
function GateExists(func, ...)
|
|
return LinkExists("Frame", func, ...)
|
|
end
|
|
|
|
Reg_Gate_Event("version", function(event, Player, Message) Gate.LinkCheck[Message[1]](event, Player, Message[2], Message[3]) end)
|
|
|
|
-- A Event is easy, when we store it at the right place
|
|
function GateObject:SetEvent(Event, EventFunc)
|
|
if Event == "NoEvents" then
|
|
self.Event = {}
|
|
elseif not Gate.Events[Event] then
|
|
error(Gate.Prefix..": "..Event.." is and invalid Event for "..self.Name, 2)
|
|
else
|
|
if type(EventFunc) == "string" then EventFunc = _G[EventFunc] end
|
|
-- For Send
|
|
table.insert(self.Event, Gate.Events[Event].id)
|
|
-- For Receive
|
|
self.Events[Event] = EventFunc
|
|
end
|
|
end
|
|
|
|
function GateObject:SetStatusLink(...)
|
|
local a = 1
|
|
while select(a, ...) do
|
|
local NameOrObject = select(a, ...)
|
|
if type(NameOrObject) == "table" then
|
|
NameOrObject = NameOrObject.Name
|
|
end
|
|
|
|
if type(NameOrObject) == "nil" then
|
|
self.StatusLink = {}
|
|
else
|
|
table.insert(self.StatusLink, NameOrObject)
|
|
end
|
|
|
|
a = a + 1
|
|
end
|
|
end
|
|
|
|
function GateObject:SetColor(r,g,b)
|
|
self.Red = r
|
|
self.Green = g
|
|
self.Blue = b
|
|
end
|
|
|
|
function GateObject:SetTab(...)
|
|
local resultTable = {}
|
|
if self.Tab then
|
|
for k,v in ipairs({...}) do
|
|
table.insert(self.Tab, v)
|
|
table.insert(resultTable, v)
|
|
end
|
|
else
|
|
self.Tab = {...}
|
|
resultTable = {...}
|
|
end
|
|
|
|
for k,v in ipairs(resultTable) do
|
|
local index
|
|
for i,name in ipairs(self.Tab) do
|
|
if name == v then
|
|
index = i
|
|
break
|
|
end
|
|
end
|
|
|
|
if index then
|
|
resultTable[k] = self:CreateBlindFrame(self.Name.."TabFrame"..index)
|
|
else
|
|
error(Gate.Prefix..": Unexpected error while creating a TabFrame!", 2)
|
|
end
|
|
end
|
|
|
|
return unpack(resultTable)
|
|
end
|
|
|
|
function GateObject:SetSelectedTab(selectedTab)
|
|
for k,v in ipairs(self.Tab) do
|
|
if v == selectedTab then
|
|
self.SelectedTab = k
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function GateObject:SetDropDownItem(Item, IconOrFunc, func)
|
|
if not self.DropDownItem then self.DropDownItem = {} end
|
|
if not self.SpecialDropDownItem then self.SpecialDropDownItem = {} end
|
|
|
|
local icon
|
|
if type(IconOrFunc) == "number" then
|
|
icon = (IconOrFunc < 10 and "0"..IconOrFunc) or tostring(IconOrFunc)
|
|
else
|
|
icon = "00"
|
|
func = IconOrFunc
|
|
end
|
|
|
|
if type(func) == "string" then func = _G[func] end
|
|
if func then
|
|
local id
|
|
for k,v in ipairs(self.SpecialDropDownItem) do
|
|
if v == func then id = k break end
|
|
end
|
|
if not id then
|
|
id = #self.SpecialDropDownItem+1
|
|
if id == 100 then error(Gate.Prefix..": DropDownMenu cannot handle more than 99 Itemfunctions", 2) end
|
|
table.insert(self.SpecialDropDownItem, func)
|
|
end
|
|
if id < 10 then id = "0"..id else id = tostring(id) end
|
|
table.insert(self.DropDownItem, id..icon..Item)
|
|
else
|
|
-- the first two entries in the ItemString are the ID.
|
|
table.insert(self.DropDownItem, "00"..icon..Item)
|
|
end
|
|
end
|
|
|
|
function GateObject:SetDropDownItems(...)
|
|
local a = 1
|
|
while select(a, ...) do
|
|
self:SetDropDownItem(select(a, ...))
|
|
a = a + 1
|
|
end
|
|
end
|
|
|
|
function GateObject:SetSelectedItem(Item)
|
|
for k,v in ipairs(self.DropDownItem) do
|
|
if v == Item then
|
|
self.SelectedItem = k
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function GateObject:SetListBoxItem(Item)
|
|
if not self.ListBoxItem then self.ListBoxItem = {} end
|
|
table.insert(self.ListBoxItem, Item)
|
|
end
|
|
|
|
function GateObject:SetListBoxItems(...)
|
|
local a = 1
|
|
while select(a, ...) do
|
|
self:SetListBoxItem(select(a, ...))
|
|
a = a + 1
|
|
end
|
|
end
|
|
|
|
-- all is self explain
|
|
function GateObject:SetOffset(XOffset, YOffset)
|
|
self.XOffset = XOffset
|
|
self.YOffset = YOffset
|
|
end
|
|
|
|
function GateObject:Hide(...)
|
|
local Stream = Gate:CreateNewGateStream(self.Type)
|
|
Stream:AddParameter("Name", self.Name)
|
|
Stream:AddParameter("Hidden", true)
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
function HideAll(Status, ...)
|
|
local Stream
|
|
if Status then
|
|
Stream = Gate:CreateNewGateStream("ha")
|
|
else
|
|
Stream = Gate:CreateNewGateStream("sa")
|
|
end
|
|
Stream:AddParameter("Name", "Hideall")
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
function GateObject:Show(...)
|
|
local Stream = Gate:CreateNewGateStream(self.Type)
|
|
Stream:AddParameter("Name", self.Name)
|
|
Stream:AddParameter("Hidden", false)
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
function GateObject:GetStatus(func, ...)
|
|
if Object.Type == "cb" then
|
|
self:GetCheckedFromPlayer(func, ...)
|
|
elseif Object.Type == "eb" then
|
|
self:GetTextFromPlayer(func, ...)
|
|
elseif Object.Type == "sb" then
|
|
self:GetValueFromPlayer(func, ...)
|
|
else
|
|
self:GetHiddenFromPlayer(func, ...)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------- Send & Receive ----------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
-- Dont working, dont know why, but this isnt important
|
|
-- RegisterServerHook(19, function(_,Ply) Ply:SendBroadcastMessage("Server support Lua Gate Project Build "..Gate.Version.." by Kenuvis") end)
|
|
|
|
function Gate_ChatHook(Event, Player, Type, Prefix, Message, Target)
|
|
if Prefix == "C"..Gate.Prefix then
|
|
Gate:IncomingStream(Message, Player)
|
|
print(1)
|
|
return 0
|
|
end
|
|
end
|
|
|
|
-- RegisterPlayerEvent(18, Gate_ChatHook)
|
|
RegisterServerEvent(30, Gate_ChatHook)
|
|
-- For Streams which are over 255 letters long
|
|
Gate.Stream = {}
|
|
|
|
function Gate:IncomingStream(Stream, Player)
|
|
-- If a message is over 255 letters long and the limit reached, it cuts in blocks
|
|
-- StreamBlock Stream1
|
|
-- StreamBlock Stream2
|
|
-- StreamBlock StreamBlockEnd Stream3 --> Stream1 Stream2 Stream3
|
|
if string.find(Stream, Gate.StreamBlock) == 1 then
|
|
if string.find(Stream, Gate.StreamBlockEnd) == 2 then
|
|
Gate.Stream[Player] = Gate.Stream[Player]..string.sub(Stream, 3)
|
|
Gate:IncomingStream(Gate.Stream[Player], Player)
|
|
Gate.Stream[Player] = nil
|
|
else
|
|
if not Gate.Stream[Player] then Gate.Stream[Player] = "" end
|
|
Gate.Stream[Player] = Gate.Stream[Player]..string.sub(Stream, 2)
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Easy parse of all little incoming events
|
|
for a in string.gmatch(Stream, "%"..Gate.StreamStart.."(.[^"..Gate.StreamStart.."]+)") do
|
|
Gate:IncomingMessage(a, Player)
|
|
end
|
|
end
|
|
|
|
function Gate:IncomingMessage(Text, Player)
|
|
-- splitt the message and put it in a table to work better with it
|
|
local Message = {}
|
|
for a in string.gmatch(Text, "%"..Gate.BlockStart.."(.[^"..Gate.BlockStart.."]*)") do
|
|
if a == "+" then a = true elseif a == "-" then a = false end
|
|
table.insert(Message, a)
|
|
end
|
|
|
|
-- The first parameter is always that one, the show, what is it
|
|
local event = Message[1]
|
|
table.remove(Message, 1)
|
|
|
|
if not event then return end
|
|
|
|
-- lets have a look, what is it
|
|
if event == "e" then --Event
|
|
Gate:IncomingEvent(Message, Player)
|
|
elseif event == "dde" then --dropdown event
|
|
Gate:IncomingDropDownEvent(Message, Player)
|
|
elseif Gate.specialEvent[event] then
|
|
Gate.specialEvent[event](event, Player, Message)
|
|
end
|
|
end
|
|
|
|
function Gate:IncomingEvent(Message, Player)
|
|
local ObjectName = Message[1]
|
|
table.remove(Message, 1)
|
|
|
|
local Event = Message[1]
|
|
table.remove(Message, 1)
|
|
|
|
if not GetObject(ObjectName) then
|
|
print(Gate.Prefix..": Incoming Event from "..Player:GetName().." for not valid Object "..ObjectName)
|
|
elseif not GetObject(ObjectName).Events[Event] then
|
|
print(Gate.Prefix..": Incoming invalid "..Event.." Event from "..Player:GetName().." for "..ObjectName)
|
|
else
|
|
local EventFunc = GetObject(ObjectName).Events[Event]
|
|
if type(EventFunc) == "string" then EventFunc = _G[EventFunc] end
|
|
|
|
-- EventFunction(Object, Event, Player, Arg-Table)
|
|
EventFunc(GetObject(ObjectName), Event, Player, Message)
|
|
end
|
|
end
|
|
|
|
function Gate:IncomingDropDownEvent(Message, Player)
|
|
local ObjectName = Message[1]
|
|
table.remove(Message, 1)
|
|
|
|
local Event = Message[1]
|
|
table.remove(Message, 1)
|
|
|
|
local ID = tonumber(Message[1])
|
|
table.remove(Message, 1)
|
|
|
|
if not GetObject(ObjectName) then
|
|
print(Gate.Prefix..": Incoming Event from "..Player:GetName().." for not valid Object "..ObjectName)
|
|
elseif not GetObject(ObjectName).SpecialDropDownItem or not GetObject(ObjectName).SpecialDropDownItem[ID] then
|
|
print(Gate.Prefix..": Incoming invalid Event from "..Player:GetName().." for "..ObjectName)
|
|
else
|
|
-- EventFunction(Object, Event, Player, Arg-Table)
|
|
GetObject(ObjectName).SpecialDropDownItem[ID](GetObject(ObjectName), Event, Player, Message)
|
|
end
|
|
end
|
|
|
|
function Gate:CreateNewGateStream(ident)
|
|
local Stream = {}
|
|
|
|
Stream.msg = Gate.StreamStart..ident
|
|
function Stream:AddObject(newObject)
|
|
newObject = GetObject(newObject)
|
|
if newObject.Type ~= "bf" then -- Blindframes are blind, because, they do not send
|
|
Stream:IntroSubStream(newObject.Type)
|
|
end
|
|
Stream:AddParameter(nil, newObject)
|
|
end
|
|
function Stream:AddParameter(Key, Parameter, Disband)
|
|
local _type = type(Parameter)
|
|
if _type == "string" or _type == "number" then
|
|
if Gate.shortKeys[Key] then
|
|
Stream.msg = Stream.msg..Gate.BlockStart..Gate.shortKeys[Key]..Gate.BlockIdent..tostring(Parameter)
|
|
end
|
|
elseif _type == "boolean" then
|
|
if Gate.shortKeys[Key] then
|
|
Stream.msg = Stream.msg..Gate.BlockStart..Gate.shortKeys[Key]..Gate.BlockIdent..((Parameter and Gate.True) or Gate.False)
|
|
end
|
|
elseif _type == "table" then
|
|
if Parameter.Type ~= "bf" then -- Blindframes are blind, because, they do not send
|
|
for k,v in pairs(Parameter) do
|
|
if type(k) == "number" then
|
|
Stream:AddParameter(Disband, v) -- 2D Tables
|
|
elseif Gate.shortKeys[k] then
|
|
Stream:AddParameter(k, v, k)
|
|
end
|
|
end
|
|
end
|
|
if Parameter.Type then -- if it is a object
|
|
-- check the Childs
|
|
for _,Child in ipairs(Parameter.Childs) do
|
|
Stream:AddObject(Child)
|
|
end
|
|
end
|
|
elseif _type == "nil" or _type == "function" then
|
|
-- do nothing and ignore it
|
|
else
|
|
error("Unknown type of parameter to add to stream")
|
|
end
|
|
end
|
|
function Stream:Clear()
|
|
Stream = nil
|
|
end
|
|
function Stream:IntroSubStream(_ident)
|
|
Stream.msg = Stream.msg..Gate.StreamStart.._ident
|
|
end
|
|
function Stream:Send(...)
|
|
Gate:Send(Stream.msg, ...)
|
|
end
|
|
|
|
return Stream
|
|
end
|
|
|
|
CreateNewGateStream = Gate.CreateNewGateStream
|
|
|
|
function Gate:Send(ToSend, ...)
|
|
if not ToSend then return end
|
|
if not ... then return end
|
|
|
|
-- Add the Prefix for Addonmessages to the Buffer and then go to every Player it should go
|
|
Prefix = "S"..Gate.Prefix
|
|
Message = ToSend
|
|
|
|
local a = 1
|
|
while select(a, ...) do
|
|
if GetLuaEngine() == "ElunaEngine" then
|
|
select(a, ...):SendAddonMessage(Prefix, Message, 7, select(a, ...))
|
|
else
|
|
error("Unknown LuaEngine")
|
|
end
|
|
a = a + 1
|
|
end
|
|
end
|
|
|
|
-- Only Objects would send with this function
|
|
function GateObject:Send(...)
|
|
local Stream = Gate:CreateNewGateStream(self.Type)
|
|
Stream:AddParameter(nil, self)
|
|
Stream:Send(...)
|
|
Stream:Clear()
|
|
end
|
|
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------- Static-Frame-handle -----------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
-- Static Frame represent a methode to record something and trigger it at another moment, without doing
|
|
-- all things (create, set..., and so on) again
|
|
|
|
Reg_Gate_Event("sf", function(_, Player, Message) Gate:SendSF(Message[1], Player) end)
|
|
|
|
Gate.SF = {}
|
|
function Gate:SendSF(Name, ...)
|
|
if not Gate.SF[Name] then
|
|
return
|
|
end
|
|
|
|
local Stream = Gate:CreateNewGateStream("sfstart")
|
|
Stream:AddParameter("Name", Name)
|
|
Stream:AddObject(Gate.SF[Name])
|
|
Stream:IntroSubStream("sfstop")
|
|
Stream:AddParameter("Name", Name)
|
|
Stream:Send(...)
|
|
end
|
|
|
|
function GateObject:SetAsStaticFrame(Name)
|
|
if Gate.SF[Name] then
|
|
print(Gate.Prefix..": StaticFrame ["..Name.."] was overwrite!")
|
|
end
|
|
|
|
Gate.SF[Name] = {}
|
|
for k,v in pairs(self) do
|
|
Gate.SF[Name][k] = v
|
|
end
|
|
|
|
Gate.SF[Name].Childs = {}
|
|
for _,name in pairs(self.Childs) do
|
|
-- I just create a copy, because static frames shouldnt change
|
|
local NewObject = {}
|
|
for k,v in pairs(GetObject(name)) do
|
|
NewObject[k] = v
|
|
end
|
|
|
|
table.insert(Gate.SF[Name].Childs, NewObject)
|
|
end
|
|
end
|
|
|
|
function SendStaticFrame(Name, ...)
|
|
local Stream = Gate:CreateNewGateStream("sf")
|
|
Stream:AddParameter("Name", Name)
|
|
Stream:Send(...)
|
|
end
|
|
|
|
function ResendStaticFrame(Name, ...)
|
|
Gate:SendSF(Name, ...)
|
|
end
|
|
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------- MasterObject-handle --------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------
|
|
|
|
function CreateMaster(Name, Parameter)
|
|
local Object = {}
|
|
|
|
Object = table.combine(Object, GateObject)
|
|
Object = table.combine(Object, Parameter)
|
|
|
|
Object.Name = nil
|
|
|
|
setmetatable(Object, GateObject_MT)
|
|
Gate:SaveObject(Name, Object)
|
|
|
|
return Object
|
|
end
|
|
|
|
function GetMasterObject(Name)
|
|
return GetObject(Name)
|
|
end
|
|
|
|
function GateObject:SetMaster(MasterObject, overwrite)
|
|
if type(MasterObject) == "string" then
|
|
MasterObject = GetMasterObject(MasterObject)
|
|
end
|
|
|
|
for k,v in pairs(MasterObject) do
|
|
self[k] = (not overwrite and self[k]) or v
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
function GateObject:SetAsMaster(Name)
|
|
return CreateMaster(Name, self)
|
|
end |