Приветствуем вас на форуме проекта WoW Circle. Если вы читаете это, значит не зарегистрировались у нас. Для того, чтобы получить доступ к расширенным возможностям нашего форума нажмите сюда и пройди регистрацию, которая не займет у вас много времени. После регистрации будут доступны новые, более расширенные, возможности.
Создание фреймворка для модульно сборки.

Упомянутые в теме пользователи:

Показано с 1 по 2 из 2
  1. #1
    Дедушка форума
    Регистрация
    20.03.2012
    Сообщений
    4,173
    Поблагодарил(а)
    358
    Получено благодарностей: 1,437 (сообщений: 836).
    Репутация: 2397

    Создание фреймворка для модульно сборки.

    Для начала , что же такое фреймврок и нужен ли он? Постараюсь без заумных фраз. Сразу скажу - можно и без него, но толку писать модульную сборку без него нет смысла.

    Что же это такое?
    -- Если кто то начинал что то писать наверное сталкивался с такой ситуацией , когда одни и те же действие нужно выполнять по нескольку раз в разных местах, будь то вывод формата времени, обработка событий, создание какой то графики, иконок и тд. Так вот, это набор функций, которые используются по нескольку раз в разных местах. Например зачем создавать для каждого модуля обработчик событий , когда можно создать один обработчик событий с обратным вызовом и получить тот же результат. Или зачем создавать кучу различных кнопок содержащих одинаковый код. Для этого и нужен фрейворк.

    Итак начнем. Все что будет далее - создание так называемого фреймворка
    Состоять он будет из нескольких частей:

    1) Функция для создание модулей.
    2) Списки очереди загрузки для наших модулей. Луа элементы массива сортирует как ему угодно и если мы захотим загружать какой то из модулей , который использует элементы созданные другим модулем , а эти элементы загрузятся после нашего модуля , то будем ловить ошибки.
    3) Обработчик обратных вызовов - регистрация событий для наших будущих модулей.
    4) Функции, которые часто используются в разных частях разных модулей. Думаю можно назвать это API.

    Начнем:

    PHP код:
    -- Получаем текущее окружение в котором выполняется наш аддон
    -- первый аргумент возвращается название аддона в строчном формате
    -- второй аргумент возвращает пространство ивент (массив)
    local addonns = ...

    -- 
    простенький обработчик ошибок
    local error 
    = function(...) print("|cffff0000Error:|r "..string.format(...)) end

    -- будущий обработчик обратных вызовов
    local frame 
    CreateFrame"frame"

    -- создаем прототип нашего будущего модуля и массив в котором будем хранить ссылки на модули
    local Modules
    module = {}, {__index = {}}

    -- 
    сократим время жизни некоторых переменных которые ниже не понадобятся
    do
        -- 
    небольшая перегрузкавызываетсякогда луа запускает функцию.
        
    local eventsevent_meta = {}, {
            
    __call = function(funcsself, ...)
                for 
    _func in nextfuncs do
                    
    func(self, ...)
                
    end
            end
    ,
        }
        
        -- 
    нужен небольшой перехват и переопределение функции регистрации событий
        local RegisterEvent 
    frame.RegisterEvent
        
        
    -- переопределяем метод RegisterEvent для обьекта frame
        
    function frame:RegisterEvent(eventmodulefunc)
        
            -- 
    небольшое исключение для методов модуля
            
    if(type(func) == 'string' and type(module[event]) == 'function'then
                func 
    module[func]
            
    end
            
            
    -- создаем массив обратных вызовов вызовов для регистрируемого событияесли его нет
            
    if not events[eventthen events[event] = {} end

            local curev 
    module[event]
            
            -- 
    в случае если для этого события необходимо обработать несколько функций делаем перегрузку
            
    if(curev and functhen
                
    -- если таблица уже существует нет смысла создавать ее зановопросто регистрируем событие
                
    if type(curev)=="table" and not self:IsEventRegistered(eventthen
                    RegisterEvent
    (selfevent)
                else
                    -- 
    в противпном случае делаем перегрузку
                    
    if(type(curev) == 'function'then
                        module
    [event] = setmetatable({curevfunc}, event_meta)
                    else
                        for 
    _infunc in nextcurev do
                            if(
    infunc == functhen return end
                        end
                        
    -- заносим функцию в массив обратных вызовов
                        table
    .insert(curevfunc)
                    
    end
                end
            
    else
                -- 
    если функция всего одна перегрузка не нужнадобавляем ее в массив обратных вызовов и регистрируем событие
                
    if(functhen
                    module
    [event] = func
                    table
    .insert(events[event], module)
                elseif(
    not module[event]) then
                    
    return error("Обработчик событий [%s] не существует."event)
                
    end
                RegisterEvent
    (selfevent)
            
    end
            
        end
        
        
    -- метод для регистрации события для прототипа модуля
        
    function module.__index:RegisterEvent(eventfunc)
            return 
    frame:RegisterEvent(eventselffunc)
        
    end
        
        local UnregisterEvent 
    frame.UnregisterEvent
        
    function frame:UnregisterEvent(eventmodulefunc)
            
    local curev module[event]
            if(
    type(curev) == 'table' and functhen
                
    for kinfunc in nextcurev do
                    if(
    infunc == functhen
                        curev
    [k] = nil

                        
    if(#curev == 0) then
                            
    table.remove(curevk)
                            
    events[event] = nil
                            UnregisterEvent
    (selfevent)
                        
    end

                        
    break
                    
    end
                end
            
    else
                
    module[event] = nil
                events
    [event] = nil
                UnregisterEvent
    (selfevent)
            
    end
        end
        
        
    --метод для удаления ивента и обратных вызовов для него с модуля
        
    function module.__index:UnregisterEvent(eventfunc)
            return 
    frame:UnregisterEvent(eventselffunc)
        
    end
        
        
    -- рукурсивная обработка массива обратных вызовов
        local 
    function burst(imodulesevent, ...)
            
    local module modules[i]
            if 
    module then
                module
    [event](moduleevent, ...)
                return 
    burst(i+1modulesevent, ...)
            
    end
        end
        
        
    -- обработка событий
        frame
    :SetScript("OnEvent", function(selfevent, ...)
            return 
    burst(1events[event], event, ...)
        
    end)
    end

    -- создаем API при вызове которого будет создан модуль с обработчик событий и тд
    function ns:NewModule(namedependency)

        -- 
    если модуль существуетвозвращаем ошибку
        
    if Modules[namethen
            
    return error("Модуль с именем [%s] уже существует."name)
        
    end
        
        
    -- наследуем мету из прототипа модуля
        local Module 
    setmetatable({}, module)
        
        -- 
    создаем очередь загрузки
        Module
    .Queue = {}

        
    Modules[name] = Module
        
        
    if dependency then
            local Parent 
    Modules[dependency]
            
            if 
    Parent then
                Parent
    .Queue[name] = Module
                Module
    .HasDependency true
            end
        end
        
        
    return Module
    end

    -- получаем ссылку на наш модуль по имени модуля
    function ns:GetModule(name)
        
        if 
    Modules[namethen
            
    return Modules[name]
        else
            return 
    error("Модуль с именем [%s] не существует."name)
        
    end
    end

    -- "Инициализация" наших модулей
    -- Ивент PLAYER_LOGIN необходиминаче наши модули будут созданы позжечем будет выполнена их загрузка
    local f 
    CreateFrame"frame"
    f:RegisterEvent("PLAYER_LOGIN")
    f:SetScript("OnEvent", function()
        -- 
    загрузка
        
    for _Module in pairs(Modules) do
            -- 
    инициализация для модулей без очереди загрузки
            
    if (Module.Init and not Module.HasDependencythen
                Module
    :Init()
            
    end
            
            
    -- инициализация очереди загрузки
            
    for _ChildModule in pairs(Module.Queue) do
                if 
    ChildModule.Init then
                    ChildModule
    :Init()
                
    end
            end
        end
    end

    Вот собственно и все.
    Последний раз редактировалось DreamlØlz; 16.05.2016 в 14:26.

  2. 1 пользователь сказал cпасибо DreamlØlz за это полезное сообщение:

    Arena_noTdie (02.07.2019)

  3. #2
    Дедушка форума
    Регистрация
    20.03.2012
    Сообщений
    4,173
    Поблагодарил(а)
    358
    Получено благодарностей: 1,437 (сообщений: 836).
    Репутация: 2397
    Небольшой набор функций для формата времени и хуки для анимации кулдауна с последующим выводом текста (похожий внешний вид имеет omnicc и аналоги). Именно эти функции и будут использованы мной далее. Возможно пополнение.

    PHP код:
    local addonns = ...

    ns.FormatValue = function(value)
        if (
    value >= 1e6then
            
    return format('%.1f'value/1e6)..'m'
        
    elseif (value >= 1e3then
            
    return format('%.1f'value/1e3)..'k'
        
    else
            return 
    value
        end
    end

    local FormatTime
    do
        
    FormatTime = function(s)
        
    local dayhourminute 86400360060
        local ceil
    format ceilformat
            
    if >= day then
                
    return format("%dd"ceil(hour))
            elseif 
    >= hour then
                
    return format("%dh"ceil(hour))
            elseif 
    >= minute then
                
    return format("%dm"ceil(minute))
            elseif 
    >= minute 12 then
                
    return floor(s)
            
    end
            
    return format("%.1f"s)
        
    end
        ns
    .FormatTime FormatTime
    end

    local HandleCD
    do
        
    local OnUpdate = function(self)
            
    local endTime self.timeLeft GetTime()
            -- print(
    endTime)
            if 
    endTime 0 then
                
    -- print(endTime)
                
    local Remaining self.Remaining
                
    if endTime 2 then
                    Remaining
    :SetTextColor(1,1,1)
                else
                    
    Remaining:SetTextColor(1,0,0)
                
    end
                Remaining
    :SetText(FormatTime(endTime))
            else
                
    self.Remaining:Hide()
            
    end
        end
        
        local OnSetCooldown 
    = function(selfstartduration)
            
    self.timeLeft start duration
            self
    .duration duration
            
    if duration 0 then
                self
    .Remaining:Show()
            
    end
            
    return self.__SetCooldown(selfstartduration)
        
    end
        
        local OnSetCooldownMin 
    = function(selfstartduration)
            
    self.timeLeft start duration
            self
    .duration duration
            
    if duration 2 then
                self
    .Remaining:Show()
            
    end
            
    return self.__SetCooldown(selfstartduration)
        
    end
        
        HandleCD 
    = function(cdsizeminduration)
            
    local Remaining cd:CreateFontString(nil'ARTWORK')
            
    Remaining:SetFont("Fonts/FRIZQT__.ttf"size'OUTLINE')
            
    Remaining:Hide()
            
    Remaining:SetJustifyH("CENTER")
            
    Remaining:SetShadowOffset(00)
            
    Remaining:SetPoint('CENTER'cd00)
            
    cd.Remaining Remaining
            cd
    .__SetCooldown cd.SetCooldown
            
    if minduration then
                cd
    .SetCooldown OnSetCooldownMin
            
    else
                
    cd.SetCooldown OnSetCooldown
            end
            cd
    :SetScript("OnUpdate"OnUpdate)
        
    end
        
        ns
    .HandleCD HandleCD
    end 

  4. 2 пользователей сказали cпасибо DreamlØlz за это полезное сообщение:

    Arena_noTdie (02.07.2019),Blacken (18.10.2016)

Похожие темы

  1. За что может забанить античит [обязательно к прочтению]
    от EvTech в разделе Новости проекта WoW Circle
    Ответов: 6
    Последнее сообщение: 30.09.2018, 17:02
  2. Ответов: 1
    Последнее сообщение: 29.10.2012, 15:59

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •