require "core.Object" require "core.Form" require "core.FormModel" require "dialog.AdminPanel" require "dialog.ArrangeModels" require "dialog.HelpPanel" require "dialog.ModelDebug" require "dialog.PinPanel" require "dialog.SummaryPanel" require "dialog.StatisticPanel" require "dialog.Settings" require "dialog.Download" require "dialog.Calculator" require "dialog.RecipeExplorer" require "dialog.ProductionPanel" require "dialog.PropertiesPanel" require "dialog.PrototypeFiltersPanel" require "dialog.UnitTestPanel" require "dialog.RichTextPanel" require "edition.LogisticEdition" require "edition.ModelEdition" require "edition.RecipeEdition" require "edition.ParametersEdition" require "edition.ProductEdition" require "edition.RuleEdition" require "edition.PreferenceEdition" require "selector.EntitySelector" require "selector.RecipeSelector" require "selector.TechnologySelector" require "selector.ItemSelector" require "selector.FluidSelector" require "model.Prototype" require "model.ElectricPrototype" require "model.EnergySourcePrototype" require "model.EntityPrototype" require "model.FluidboxPrototype" require "model.FluidPrototype" require "model.ItemPrototype" require "model.Product" require "model.RecipePrototype" require "model.Technology" ModGui = require "mod-gui" Cache = require "data.Cache" User = require "data.User" Model = require "data.Model" ModelCompute = require "data.ModelCompute" ModelBuilder = require "data.ModelBuilder" PrototypeFilters = require "model.PrototypeFilters" Converter = require "core.Converter" Blueprint = require "core.Blueprint" PLANNER_COMMAND = "helmod_planner-command" local Controller = newclass(Object,function(base,classname) Object.init(base,classname) end) Controller.classname = "HMController" local views = nil local locate = "center" local pinLocate = "left" local nextEvent = nil ------------------------------------------------------------------------------- ---Prepare Views --- function Controller:prepare() local forms = {} table.insert(forms, AdminPanel("HMAdminPanel")) table.insert(forms, ArrangeModels("HMArrangeModels")) table.insert(forms, HelpPanel("HMHelpPanel")) table.insert(forms, ModelDebug("HMModelDebug")) table.insert(forms, Download("HMDownload")) table.insert(forms, Calculator("HMCalculator")) table.insert(forms, RecipeExplorer("HMRecipeExplorer")) table.insert(forms, ProductionPanel("HMProductionPanel")) table.insert(forms, PropertiesPanel("HMPropertiesPanel")) table.insert(forms, PrototypeFiltersPanel("HMPrototypeFiltersPanel")) table.insert(forms, UnitTestPanel("HMUnitTestPanel")) table.insert(forms, RichTextPanel("HMRichTextPanel")) table.insert(forms, EntitySelector("HMEntitySelector")) table.insert(forms, RecipeSelector("HMRecipeSelector")) table.insert(forms, TechnologySelector("HMTechnologySelector")) table.insert(forms, ItemSelector("HMItemSelector")) table.insert(forms, FluidSelector("HMFluidSelector")) table.insert(forms, LogisticEdition("HMLogisticEdition")) table.insert(forms, ModelEdition("HMModelEdition")) table.insert(forms, RecipeEdition("HMRecipeEdition")) table.insert(forms, ParametersEdition("HMParametersEdition")) table.insert(forms, ProductEdition("HMProductEdition")) table.insert(forms, RuleEdition("HMRuleEdition")) table.insert(forms, PreferenceEdition("HMPreferenceEdition")) table.insert(forms, PinPanel("HMPinPanel")) table.insert(forms, SummaryPanel("HMSummaryPanel")) table.insert(forms, StatisticPanel("HMStatisticPanel")) views = {} for _,form in pairs(forms) do form:bind() views[form.classname] = form end end ------------------------------------------------------------------------------- ---On initialization --- function Controller:on_init() local caches_data = Cache.get() if caches_data["HMPlayer"] == nil then Player.getResources() end local forms = {} table.insert(forms, EntitySelector("HMEntitySelector")) table.insert(forms, RecipeSelector("HMRecipeSelector")) table.insert(forms, TechnologySelector("HMTechnologySelector")) table.insert(forms, ItemSelector("HMItemSelector")) table.insert(forms, FluidSelector("HMFluidSelector")) for _,form in pairs(forms) do form:prepare() end end ------------------------------------------------------------------------------- ---Bind Dispatcher --- function Controller:bind() Dispatcher:bind("on_gui_action", self, self.onGuiAction) Dispatcher:bind("on_gui_event", self, self.onGuiEvent) Dispatcher:bind("on_gui_setting", self, self.onGuiSetting) Dispatcher:bind("on_gui_hotkey", self, self.onGuiHotkey) Dispatcher:bind("on_gui_shortcut", self, self.onGuiShortcut) Dispatcher:bind("on_gui_queue", self, self.onGuiQueue) Dispatcher:bind("on_gui_tips", self, self.onGuiTips) end ------------------------------------------------------------------------------- --- Get views --- ---@return table --- function Controller:getViews() if views == nil then Controller.prepare() end return views end ------------------------------------------------------------------------------- ---Get View --- ---@param name string --- ---@return table --- function Controller:getView(name) if views == nil then Controller.prepare() end return views[name] end ------------------------------------------------------------------------------- ---Cleanup --- ---@param player table --- function Controller:cleanController(player) for _,location in pairs({"center", "left", "top", "screen"}) do local lua_gui_element = player.gui[location] for _,children_name in pairs(lua_gui_element.children_names) do if children_name ~= "HMPinPanel" and self:getView(children_name) then self:getView(children_name):close() end if children_name ~= "HMPinPanel" and not(string.find(children_name,"mod_gui")) and lua_gui_element[children_name] ~= nil and lua_gui_element[children_name].get_mod() == "helmod" then lua_gui_element[children_name].destroy() end end end end ------------------------------------------------------------------------------- ---closeEditionOrSelector --- function Controller:closeEditionOrSelector() local lua_gui_element = Player.getGui("screen") for _,children_name in pairs(lua_gui_element.children_names) do if self:getView(children_name) and (string.find(children_name,"Edition") ~= nil) then self:getView(children_name):close() end end end ------------------------------------------------------------------------------- ---Bind all controllers --- ---@param player table --- function Controller:bindController(player) if player ~= nil then local lua_gui_element = Player.getGui("top") if lua_gui_element["helmod_planner-command"] ~= nil then lua_gui_element["helmod_planner-command"].destroy() end -- Destroy gui button if lua_gui_element["helmod_planner-command"] ~= nil then lua_gui_element["helmod_planner-command"].destroy() end local flow = lua_gui_element.mod_gui_button_flow or (lua_gui_element.mod_gui_top_frame and lua_gui_element.mod_gui_top_frame.mod_gui_inner_frame) if flow and flow["helmod_planner-command"] then flow["helmod_planner-command"].destroy() -- Remove empty frame if we're the only thing there, remove the parent frame if we just removed the only child if #flow.children_names == 0 then local parent = flow.parent flow.destroy() if parent and parent.name ~= "top" and #parent.children_names == 0 then parent.destroy() end end end -- Create gui button if User.getModSetting("display_main_icon") then lua_gui_element = ModGui.get_button_flow(player) if lua_gui_element ~= nil then local gui_button = GuiElement.add(lua_gui_element, GuiButton("helmod_planner-command"):sprite("menu", defines.sprites.calculator.white, defines.sprites.calculator.black):style("helmod_button_menu_dark"):tooltip({"helmod_planner-command"})) gui_button.style.width = 37 gui_button.style.height = 37 end end User.update() end end ------------------------------------------------------------------------------- ---On tick --- ---@param event table --- function Controller:onTick(event) if Player.native() ~= nil and Player.native().valid then local next_event = User.getParameter("next_event") if next_event ~= nil then if (next_event.event.iteration or 0) < 1000 then next_event.event.iteration = (next_event.event.iteration or 0) + 1 Dispatcher:send(next_event.type_event, next_event.event, next_event.classname) else User.setParameter("next_event", nil) event.message = {"", {"helmod_error.excessive-event-iteration"}, " (>1000)"} Dispatcher:send("on_gui_error", event, next_event.classname) end end local event_queue = User.getParameter("event_queue") if event_queue ~= nil then local current_tick = game.tick for _,event in pairs(event_queue) do if event.is_tips == true then if current_tick - event.tick > User.delay_tips then Dispatcher:send("on_gui_tips", event, Controller.classname) event_queue[event.classname] = nil end else if current_tick - event.tick > 60 then event.is_queue = true Dispatcher:send("on_gui_action", event, Controller.classname) event_queue[event.element.name] = nil end end end if table.size(event_queue) == 0 then User.setParameter("event_queue", nil) end end end end ------------------------------------------------------------------------------- ---On gui queue --- ---@param event table --- function Controller:onGuiQueue(event) local event_queue = User.getParameter("event_queue") or {} event.element = {name=event.element.name, text=event.element.text} event_queue[event.element.name] = event User.setParameter("event_queue", event_queue) end ------------------------------------------------------------------------------- ---On gui tips --- ---@param event table --- function Controller:onGuiTips(event) local form = self:getView(event.classname) if form ~= nil then form:destroyTips() end end ------------------------------------------------------------------------------- ---On tick --- ---@param NthTickEvent table {tick=#number, nth_tick=#number} --- function Controller:onNthTick(NthTickEvent) if Player.native() ~= nil then local next_event = User.getParameter("next_event") if next_event ~= nil and next_event.event.tick < NthTickEvent.tick then Player.load(next_event.event) next_event.event.tick = NthTickEvent.tick script.raise_event(next_event.type_event, next_event.event) User.setParameter("next_event",nil) end end end ------------------------------------------------------------------------------- ---On string translated --- ---@param event table {player_index=number, localised_ string=string, result=string, translated=boolean} --- function Controller:onStringTranslated(event) User.addTranslate(event) end ------------------------------------------------------------------------------- ---On gui closed --- ---@param event table --- function Controller:onGuiClosed(event) self:cleanController(Player.native()) end local pattern = "([^=]*)=?([^=]*)=?([^=]*)=?([^=]*)=?([^=]*)=?([^=]*)=?([^=]*)" ------------------------------------------------------------------------------- ---On gui action --- ---@param event table --- function Controller:onGuiAction(event) if event.element ~= nil and (string.find(event.element.name,"^HM.*") or string.find(event.element.name,"^helmod.*")) then if views == nil then self:prepare() end event.classname, event.action, event.item1, event.item2, event.item3, event.item4, event.item5 = string.match(event.element.name,pattern) if event.classname == self.classname and event.action == "CLOSE" then Controller:cleanController(Player.native()) elseif event.classname == "helmod_planner-command" then Controller:openMainPanel() else if event.action == "CLOSE" then Controller:send("on_gui_close", event, event.classname) end self:onGuiEvent(event) end end end ------------------------------------------------------------------------------- ---On gui event --- ---@param event table --- function Controller:onGuiEvent(event) if event.action == "OPEN" and event.continue ~= true then User.setActiveForm(event.classname) Controller:send("on_gui_open", event, event.classname) end Controller:send("on_gui_event", event, event.classname) end ------------------------------------------------------------------------------- ---On gui hotkey --- ---@param event table --- function Controller:onGuiHotkey(event) if views == nil then self:prepare() end if event.input_name == "helmod-close" then if self:isOpened() then self:cleanController(Player.native()) end end if event.input_name == "helmod-open-close" then self:openMainPanel() end if event.input_name == "helmod-production-line-open" then if not(self:isOpened()) then self:openMainPanel() end end if event.input_name == "helmod-recipe-selector-open" then if not(self:isOpened()) then self:openMainPanel() end self:send("on_gui_open", event, "HMRecipeSelector") end if event.input_name == "helmod-recipe-explorer-open" then local view = Controller:getView("HMRecipeExplorer") if not(view:isOpened()) then self:send("on_gui_open", event, "HMRecipeExplorer") else view:close() end end if event.input_name == "helmod-richtext-open" then local view = Controller:getView("HMRichTextPanel") if not(view:isOpened()) then self:send("on_gui_open", event, "HMRichTextPanel") else view:close() end end end ------------------------------------------------------------------------------- ---On gui shortcut --- ---@param event table --- function Controller:onGuiShortcut(event) if views == nil then self:prepare() end if event.prototype_name == "helmod-shortcut" then self:openMainPanel() end end ------------------------------------------------------------------------------- ---On gui setting --- ---@param event table --- function Controller:onGuiSetting(event) if views == nil then self:prepare() end self:bindController(Player.native()) if self:isOpened() then self:cleanController(Player.native()) self:openMainPanel() else -- prevent change location self:cleanController(Player.native()) end end ------------------------------------------------------------------------------- ---Prepare main display --- function Controller:openMainPanel() if self:isOpened() then self:cleanController(Player.native()) game.tick_paused = false else local current_tab = "HMProductionPanel" local parameter_name = string.format("%s_%s", current_tab, "objects") local parameter_objects = User.getParameter(parameter_name) local event = {name="OPEN"} if parameter_objects == nil then parameter_objects = {name=parameter_name} else event.item2 = parameter_objects.block end local model, block, recipe = Model.getParameterObjects(parameter_objects) event.item1 = model.id self:send("on_gui_open", event, current_tab) end end ------------------------------------------------------------------------------- ---Is opened main panel ---@return boolean --- function Controller:isOpened() local lua_player = Player.native() if lua_player == nil then return false end local panel = self:getView("HMProductionPanel") return panel:isOpened() end ------------------------------------------------------------------------------- ---Send event ---@param event_type string ---@param data table ---@param classname string --- function Controller:send(event_type, data, classname) if classname ~= nil then data.classname = classname end Dispatcher:send(event_type, data, classname) end local MyController = Controller(Controller.classname) MyController:bind() return MyController