z_mirror/TaskList

git clone https://git.raiguard.me/z_mirror/TaskList

Caleb HeuerType shenanigans12eeab5

fix/blueprint-sandboxes-force
6.5 KiB205 linesraw
1--[[
2  DESIGN GOALS:
3  - Extremely simple to-do list
4  - Compact and full versions of the UI
5    - Compact for reference, full for manipulation
6  - Opt-in advanced features
7    - Timed reminders (interval, absolute time)
8    - Notifications for reminders
9    - Task assignment
10    - Maybe projects?
11  - Current task must be easily visible in some way
12    - Consider using the bottom-right of the screen for this
13  - "Private" and "public" tasks
14    - Private is visible only to you, public is visible to your force
15  - An infinite amount of subtask nesting
16  - Import and export TODOs
17
18  DESIGN NOTES:
19  - Each task will have an entirely unique ID
20    - Store the next ID in the root of `global`
21  - Tasks will be stored in a one-dimensional table keyed by task ID
22  - Tasks can be owned by the force, or by the player
23    - Player tasks will be shown separately from force tasks
24  - A task can have infinite subtasks
25    - Subtasks are just pointers to other tasks, so they support the full feature suite, including more subtasks
26    - Subtasks may have a different assignee from their parent
27  - Import and export will use the standard method
28  - Each owner (force, player, or task) will have a `tasks` array containing the task IDs to show, in order
29    - Subtasks are also stored in the same manner, but are in a `subtasks` table instead
30  - When a task is completed, it is added to its owners `completed_tasks` array at the front
31    - Completed tasks will be listed after active tasks, in the order that they were completed
32    - Store completion time?
33]]
34
35local gui = require("__flib__/gui")
36local migration = require("__flib__/migration")
37
38local active_task_button = require("__TaskList__/scripts/gui/active-task-button")
39local migrations = require("__TaskList__/scripts/migrations")
40local edit_task_gui = require("__TaskList__/scripts/gui/edit-task/index")
41local player_data = require("__TaskList__/scripts/player-data")
42local task = require("__TaskList__/scripts/task")
43local tasks_gui = require("__TaskList__/scripts/gui/tasks/index")
44local util = require("__TaskList__/scripts/util")
45
46--- @param force LuaForce
47local function init_force(force)
48  --- @class ForceTable
49  global.forces[force.index] = {
50    --- @type number[]
51    completed_tasks = {},
52    --- @type number[]
53    tasks = {},
54  }
55end
56
57-- BOOTSTRAP
58
59script.on_init(function()
60  --- @type table<uint, ForceTable>
61  global.forces = {}
62  global.next_task_id = 1
63  --- @type table<uint, PlayerTable>
64  global.players = {}
65  --- @type table<number, Task>
66  global.tasks = {}
67
68  for _, force in pairs(game.forces) do
69    init_force(force)
70  end
71  for _, player in pairs(game.players) do
72    player_data.init(player)
73  end
74
75  migrations.generic()
76end)
77
78script.on_load(function()
79  for _, Task in pairs(global.tasks) do
80    task.load(Task)
81  end
82
83  for _, player_table in pairs(global.players) do
84    tasks_gui.load(player_table.guis.tasks)
85    if player_table.guis.edit_task then
86      edit_task_gui.load(player_table.guis.edit_task)
87    end
88  end
89end)
90
91script.on_configuration_changed(function(e)
92  if migration.on_config_changed(e, migrations.versions) then
93    migrations.generic()
94  end
95end)
96
97-- FORCE
98
99script.on_event(defines.events.on_force_created, function(e)
100  init_force(e.force)
101end)
102
103-- INTERACTION
104
105gui.hook_events(function(e)
106  local msg = gui.read_action(e)
107  if msg then
108    local Gui = util.get_gui(e.player_index, msg.gui)
109    if Gui then
110      Gui:dispatch(msg, e)
111    end
112  end
113end)
114
115script.on_event("tlst-linked-confirm-gui", function(e)
116  local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
117  local EditTaskGui = util.get_gui(e.player_index, "edit_task")
118  if EditTaskGui then
119    EditTaskGui:dispatch({ action = "confirm" })
120    player.play_sound({ path = "utility/confirm" })
121  elseif player.mod_settings["tlst-new-task-on-confirm"].value then
122    local TasksGui = util.get_gui(e.player_index, "tasks")
123    if TasksGui and TasksGui.state.visible and not TasksGui.state.pinned then
124      TasksGui:dispatch({ action = "edit_task", confirmed = true })
125    end
126  end
127end)
128
129--- @param player_index uint
130local function toggle_new_task(player_index)
131  local EditTaskGui = util.get_gui(player_index, "edit_task")
132  if EditTaskGui then
133    EditTaskGui:destroy()
134  else
135    local player = game.get_player(player_index) --[[@as LuaPlayer]]
136    local player_table = global.players[player_index]
137    edit_task_gui.new(player, player_table, { standalone = true })
138  end
139end
140
141script.on_event("tlst-new-task", function(e)
142  toggle_new_task(e.player_index)
143end)
144
145script.on_event({ "tlst-toggle-gui", defines.events.on_lua_shortcut }, function(e)
146  if (e.input_name or e.prototype_name) == "tlst-toggle-gui" then
147    local player_table = global.players[e.player_index]
148    local Gui = util.get_gui(e.player_index, "tasks")
149    if Gui then
150      Gui:toggle()
151    else
152      local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
153      player_data.refresh(player, player_table)
154    end
155  elseif e.prototype_name == "tlst-new-task" then
156    toggle_new_task(e.player_index)
157  end
158end)
159
160-- PLAYER
161
162script.on_event(defines.events.on_player_created, function(e)
163  local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
164
165  player_data.init(player)
166  player_data.refresh(player, global.players[e.player_index])
167end)
168
169script.on_event(defines.events.on_player_removed, function(e)
170  -- Remove all player tasks
171  local player_table = global.players[e.player_index]
172  for _, task_ids in pairs({ player_table.completed_tasks, player_table.tasks }) do
173    for _, task_id in pairs(task_ids) do
174      local Task = global.tasks[task_id]
175      if Task then
176        Task:delete()
177      end
178    end
179  end
180
181  global.players[e.player_index] = nil
182end)
183
184script.on_event(defines.events.on_runtime_mod_setting_changed, function(e)
185  if e.setting == "tlst-new-task-on-confirm" then
186    local TasksGui = util.get_gui(e.player_index, "tasks")
187    if TasksGui then
188      local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
189      local tooltip = { "gui.tlst-new-task" }
190      if player.mod_settings[e.setting].value then
191        tooltip[1] = tooltip[1] .. "-instruction"
192      end
193      TasksGui.refs.new_task_button.tooltip = tooltip
194    end
195  elseif e.setting == "tlst-show-active-task" or e.setting == "tlst-active-filter-assigned" then
196    local player = game.get_player(e.player_index) --[[@as LuaPlayer]]
197    local player_table = global.players[e.player_index]
198    local value = player.mod_settings["tlst-show-active-task"].value
199    if value == "off" then
200      active_task_button.destroy(player_table)
201    else
202      active_task_button.build(player, player_table)
203    end
204  end
205end)