7 doc
.VERSION
.STRING
= doc
.VERSION
.MAJOR
.."."..doc
.VERSION
.MINOR
.."."..doc
.VERSION
.PATCH
11 doc
.data
.categories
= {}
12 doc
.data
.category_order
= {}
15 -- Space for additional APIs
18 --[[ Core API functions ]]
21 function doc
.new_category(id
, def
)
22 if doc
.data
.categories
[id
] == nil and id
~= nil then
23 doc
.data
.categories
[id
] = {}
24 doc
.data
.categories
[id
].entries
= {}
25 doc
.data
.categories
[id
].entry_count
= 0
26 doc
.data
.categories
[id
].def
= def
27 doc
.data
.categories
[id
].entry_aliases
= {}
28 table.insert(doc
.data
.category_order
, id
)
36 function doc
.new_entry(category_id
, entry_id
, def
)
37 if doc
.data
.categories
[category_id
] ~= nil then
38 doc
.data
.categories
[category_id
].entries
[entry_id
] = def
39 doc
.data
.categories
[category_id
].entry_count
= doc
.data
.categories
[category_id
].entry_count
+ 1
46 -- Marks a particular entry as viewed by a certain player
47 function doc
.mark_entry_as_viewed(playername
, category_id
, entry_id
)
48 if doc
.data
.players
[playername
].stored_data
.viewed
[category_id
] == nil then
49 doc
.data
.players
[playername
].stored_data
.viewed
[category_id
] = {}
50 doc
.data
.players
[playername
].stored_data
.viewed_count
[category_id
] = 0
52 if doc
.data
.players
[playername
].stored_data
.viewed
[category_id
][entry_id
] ~= true then
53 doc
.data
.players
[playername
].stored_data
.viewed
[category_id
][entry_id
] = true
54 doc
.data
.players
[playername
].stored_data
.viewed_count
[category_id
] = doc
.data
.players
[playername
].stored_data
.viewed_count
[category_id
] + 1
55 -- Needed because viewed entries get a different color
56 doc
.data
.players
[playername
].entry_textlist_needs_updating
= true
60 -- Returns true if the specified entry has been viewed by the player
61 function doc
.entry_viewed(playername
, category_id
, entry_id
)
62 if doc
.data
.players
[playername
].stored_data
.viewed
[category_id
] == nil then
65 return doc
.data
.players
[playername
].stored_data
.viewed
[category_id
][entry_id
] == true
69 -- Opens the main documentation formspec for the player
70 function doc
.show_doc(playername
)
71 local formspec
= doc
.formspec_core()..doc
.formspec_main()
72 minetest
.show_formspec(playername
, "doc:main", formspec
)
75 -- Opens the documentation formspec for the player at the specified category
76 function doc
.show_category(playername
, category_id
)
77 doc
.data
.players
[playername
].catsel
= nil
78 doc
.data
.players
[playername
].category
= category_id
79 doc
.data
.players
[playername
].entry
= nil
80 local formspec
= doc
.formspec_core(2)..doc
.formspec_category(category_id
, playername
)
81 minetest
.show_formspec(playername
, "doc:category", formspec
)
84 -- Opens the documentation formspec for the player showing the specified entry in a category
85 function doc
.show_entry(playername
, category_id
, entry_id
)
86 doc
.data
.players
[playername
].catsel
= nil
87 doc
.data
.players
[playername
].category
= category_id
88 doc
.data
.players
[playername
].entry
= entry_id
89 doc
.mark_entry_as_viewed(playername
, category_id
, entry_id
)
90 local eids
, catsel
= doc
.data
.players
[playername
].entry_ids
, doc
.data
.players
[playername
].catsel
91 local formspec
= doc
.formspec_core(3)..doc
.formspec_entry(category_id
, entry_id
)
92 minetest
.show_formspec(playername
, "doc:entry", formspec
)
95 -- Returns true if and only if:
96 -- * The specified category exists
97 -- * This category contains the specified entry
98 function doc
.entry_exists(category_id
, entry_id
)
99 if doc
.data
.categories
[category_id
] ~= nil then
100 if doc
.data
.categories
[category_id
].entries
[entry_id
] ~= nil then
104 -- Entry of this ID does not exist, so we check if there's an alis for it
105 return doc
.data
.categories
[category_id
].entry_aliases
[entry_id
] ~= nil
112 -- Adds aliases for an entry. Attempting to open an entry by an alias name
113 -- results in opening the entry of the original name.
114 -- Aliases are true within one category only.
115 function doc
.add_entry_aliases(category_id
, entry_id
, aliases
)
117 doc
.data
.categories
[category_id
].entry_aliases
[aliases
[a]]
= entry_id
121 -- Same as above, but only adds one alias
122 function doc
.add_entry_alias(category_id
, entry_id
, alias
)
123 doc
.data
.categories
[category_id
].entry_aliases
[alias
] = entry_id
126 -- Returns number of categories
127 function doc
.get_category_count()
128 return #doc
.data
.category_order
131 -- Returns number of entries in category
132 function doc
.get_entry_count(category_id
)
133 return doc
.data
.categories
[category_id
].entry_count
136 -- Returns how many entries have been viewed by the player
137 function doc
.get_viewed_count(playername
, category_id
)
138 if doc
.data
.players
[playername
] == nil then
141 local count
= doc
.data
.players
[playername
].stored_data
.viewed_count
[category_id
]
149 --[[ Functions for internal use ]]
151 function doc
.formspec_core(tab
)
152 if tab
== nil then tab
= 1 else tab
= tostring(tab
) end
153 return "size[12,9]tabheader[0,0;doc_header;Main,Category,Entry;"..tab
..";true;false]"
156 function doc
.formspec_main()
158 local formstring
= "label[0,0;Available help topics:]"
159 for c
=1,#doc
.data
.category_order
do
160 local id
= doc
.data
.category_order
[c
]
161 local data
= doc
.data
.categories
[id
]
162 local button
= "button[0,"..y
..";3,1;doc_button_category_"..id
..";"..minetest
.formspec_escape(data
.def
.name
).."]"
163 formstring
= formstring
.. button
169 function doc
.generate_entry_list(cid
, playername
)
171 if doc
.data
.players
[playername
].entry_textlist
== nil
172 or doc
.data
.players
[playername
].category
~= cid
173 or doc
.data
.players
[playername
].entry_textlist_needs_updating
== true then
174 local entry_textlist
= "textlist[0,1;11,7;doc_catlist;"
176 doc
.data
.players
[playername
].entry_ids
= {}
177 local entries
= doc
.get_sorted_entry_names(cid
)
179 local eid
= entries
[i
].eid
180 table.insert(doc
.data
.players
[playername
].entry_ids
, eid
)
181 -- Colorize entries based on viewed status
183 local viewedprefix
= "#00FFFF"
184 if doc
.entry_viewed(playername
, cid
, eid
) then
186 viewedprefix
= "#FFFFFF"
188 entry_textlist
= entry_textlist
.. viewedprefix
.. minetest
.formspec_escape(entries
[i
].name
) .. ","
189 counter
= counter
+ 1
192 entry_textlist
= string.sub(entry_textlist
, 1, #entry_textlist
-1)
194 local catsel
= doc
.data
.players
[playername
].catsel
196 entry_textlist
= entry_textlist
.. ";"..catsel
198 entry_textlist
= entry_textlist
.. "]"
199 doc
.data
.players
[playername
].entry_textlist
= entry_textlist
200 formstring
= entry_textlist
201 doc
.data
.players
[playername
].entry_testlist_needs_updating
= false
203 formstring
= doc
.data
.players
[playername
].entry_textlist
208 function doc
.get_sorted_entry_names(cid
)
209 local sort_table
= {}
210 local entry_table
= {}
211 for eid
,entry
in pairs(doc
.data
.categories
[cid
].entries
) do
212 local new_entry
= table.copy(entry
)
214 table.insert(entry_table
, new_entry
)
215 table.insert(sort_table
, entry
.name
)
217 table.sort(sort_table
)
218 local reverse_sort_table
= table.copy(sort_table
)
219 for i
=1, #sort_table
do
220 reverse_sort_table
[sort_table
[i]]
= i
222 local comp
= function(e1
, e2
)
223 if reverse_sort_table
[e1
.name
] < reverse_sort_table
[e2
.name
] then return true else return false end
225 table.sort(entry_table
, comp
)
230 function doc
.formspec_category(id
, playername
)
233 formstring
= "label[0,0;You haven't selected a help topic yet. Please select one in the category list first.]"
234 formstring
= formstring
.. "button[0,1;3,1;doc_button_goto_main;Go to category list]"
236 formstring
= "label[0,0;Current help topic: "..doc
.data
.categories
[id
].def
.name
.."]"
237 formstring
= formstring
.. "label[0,0.5;Available entries:]"
238 formstring
= formstring
.. doc
.generate_entry_list(id
, playername
)
239 formstring
= formstring
.. "button[0,8;3,1;doc_button_goto_entry;Show entry]"
244 function doc
.formspec_entry(category_id
, entry_id
)
246 if category_id
== nil then
247 formstring
= "label[0,0;You haven't selected a help topic yet. Please select one in the category list first.]"
248 formstring
= formstring
.. "button[0,1;3,1;doc_button_goto_main;Go to category list]"
249 elseif entry_id
== nil then
250 formstring
= "label[0,0;You haven't selected an help entry yet. Please select one in the list of entries first.]"
251 formstring
= formstring
.. "button[0,1;3,1;doc_button_goto_category;Go to entry list]"
254 local category
= doc
.data
.categories
[category_id
]
255 local entry
= category
.entries
[entry_id
]
256 -- Check if entry has an alias
258 local resolved_alias
= doc
.data
.categories
[category_id
].entry_aliases
[entry_id
]
259 if resolved_alias
~= nil then
260 entry
= category
.entries
[resolved_alias
]
264 formstring
= "label[0,0;Help > "..category
.def
.name
.." > "..entry
.name
.."]"
265 formstring
= formstring
.. category
.def
.build_formspec(entry
.data
)
270 function doc
.process_form(player
,formname
,fields
)
271 local playername
= player
:get_player_name()
272 --[[ process clicks on the tab header ]]
273 if(formname
== "doc:main" or formname
== "doc:category" or formname
== "doc:entry") then
274 if fields
.doc_header
~= nil then
275 local tab
= tonumber(fields
.doc_header
)
276 local formspec
, subformname
, contents
278 cid
= doc
.data
.players
[playername
].category
279 eid
= doc
.data
.players
[playername
].entry
281 contents
= doc
.formspec_main()
284 contents
= doc
.formspec_category(cid
, playername
)
285 subformname
= "category"
287 contents
= doc
.formspec_entry(cid
, eid
)
288 if cid
~= nil and eid
~= nil then
289 doc
.mark_entry_as_viewed(playername
, cid
, eid
)
291 subformname
= "entry"
293 formspec
= doc
.formspec_core(tab
)..contents
294 minetest
.show_formspec(playername
, "doc:" .. subformname
, formspec
)
298 if(formname
== "doc:main") then
299 for id
,category
in pairs(doc
.data
.categories
) do
300 if fields
["doc_button_category_"..id
] then
301 local formspec
= doc
.formspec_core(2)..doc
.formspec_category(id
, playername
)
302 doc
.data
.players
[playername
].catsel
= nil
303 doc
.data
.players
[playername
].category
= id
304 doc
.data
.players
[playername
].entry
= nil
305 minetest
.show_formspec(playername
, "doc:category", formspec
)
309 elseif(formname
== "doc:category") then
310 if fields
["doc_button_goto_entry"] then
311 local cid
= doc
.data
.players
[playername
].category
314 local eids
, catsel
= doc
.data
.players
[playername
].entry_ids
, doc
.data
.players
[playername
].catsel
315 if eids
~= nil and catsel
~= nil then
318 local formspec
= doc
.formspec_core(3)..doc
.formspec_entry(cid
, eid
)
319 minetest
.show_formspec(playername
, "doc:entry", formspec
)
320 doc
.mark_entry_as_viewed(playername
, cid
, eid
)
323 if fields
["doc_button_goto_main"] then
324 local formspec
= doc
.formspec_core(1)..doc
.formspec_main()
325 minetest
.show_formspec(playername
, "doc:main", formspec
)
327 if fields
["doc_catlist"] then
328 local event
= minetest
.explode_textlist_event(fields
["doc_catlist"])
329 if event
.type == "CHG" then
330 doc
.data
.players
[playername
].catsel
= event
.index
331 doc
.data
.players
[playername
].entry
= doc
.data
.players
[playername
].entry_ids
[event
.index
]
332 elseif event
.type == "DCL" then
333 local cid
= doc
.data
.players
[playername
].category
335 local eids
, catsel
= doc
.data
.players
[playername
].entry_ids
, event
.index
336 if eids
~= nil and catsel
~= nil then
339 local formspec
= doc
.formspec_core(3)..doc
.formspec_entry(cid
, eid
)
340 minetest
.show_formspec(playername
, "doc:entry", formspec
)
341 doc
.mark_entry_as_viewed(playername
, cid
, eid
)
344 elseif(formname
== "doc:entry") then
345 if fields
["doc_button_goto_main"] then
346 local formspec
= doc
.formspec_core(1)..doc
.formspec_main()
347 minetest
.show_formspec(playername
, "doc:main", formspec
)
348 elseif fields
["doc_button_goto_category"] then
349 local formspec
= doc
.formspec_core(2)..doc
.formspec_category(doc
.data
.players
[playername
].category
, playername
)
350 minetest
.show_formspec(playername
, "doc:category", formspec
)
355 minetest
.register_on_player_receive_fields(doc
.process_form
)
357 minetest
.register_chatcommand("doc", {
359 description
= "Open documentation system.",
361 func
= function(playername
, param
)
362 doc
.show_doc(playername
)
367 minetest
.register_on_joinplayer(function(player
)
368 local playername
= player
:get_player_name()
369 doc
.data
.players
[playername
] = {}
370 -- Table for persistant data
371 doc
.data
.players
[playername
].stored_data
= {}
372 -- Contains viewed entries
373 doc
.data
.players
[playername
].stored_data
.viewed
= {}
374 -- Count viewed entries
375 doc
.data
.players
[playername
].stored_data
.viewed_count
= {}
378 minetest
.register_on_leaveplayer(function(player
)
379 doc
.data
.players
[player
:get_player_name()] = nil
382 ---[[ Add buttons for inventory mods ]]
384 if minetest
.get_modpath("unified_inventory") ~= nil then
385 unified_inventory
.register_button("doc", {
387 image
= "doc_button_icon_hires.png",
388 tooltip
= "Documentation System",
389 action
= function(player
)
390 doc
.show_doc(player
:get_player_name())