Initial working i3 version, no hidden support

master
ExeVirus 2021-10-13 22:53:01 -04:00
parent 311e4285b1
commit 02c7a35aa8
15 changed files with 436 additions and 73 deletions

12
LICENSE
View File

@ -1,3 +1,15 @@
The following textures are licensed under Apache License 2.0,
originally obtained from https://github.com/Remix-Design/remixicon
textures/game_doc_back_pressed.png
textures/game_doc_back.png
textures/game_doc_help_pressed.png
textures/game_doc_help.png
textures/game_doc_select_pressed.png
textures/game_doc_select.png
All other files in this mod are licensed as follows:
MIT License
Copyright (c) 2021 ExeVirus

View File

@ -61,10 +61,6 @@ end
-- markdown_file: file_path to markdown file to load
-- hidden: default false (based on settings), true will hide from players until
-- shown via hidden_modifications.lua functions >> optional
local x = game_doc.settings.edge_size
local y = game_doc.settings.edge_size + game_doc.settings.header_size
local w = game_doc.settings.width - game_doc.settings.edge_size * 2
local h = game_doc.settings.height - game_doc.settings.edge_size * 2 - game_doc.settings.header_size
game_doc.add_file_entry = function(category_name, entry_name, markdown_file, hidden)
--safety check
if category_name == nil or entry_name == nil or markdown_file == nil then
@ -72,26 +68,16 @@ game_doc.add_file_entry = function(category_name, entry_name, markdown_file, hid
return
end
local md2f_settings = {
background_color = "#222E",
font_color = "#FFF",
heading_1_color = "#AFA",
heading_2_color = "#FAA",
heading_3_color = "#AAF",
heading_4_color = "#FFA",
heading_5_color = "#AFF",
heading_6_color = "#FAF",
code_block_mono_color = "#6F6",
code_block_font_size = 14,
mono_color = "#6F6",
block_quote_color = "#FFA",
}
local x = game_doc.settings.edge_size
local y = game_doc.settings.edge_size * 2 + game_doc.settings.header_size + game_doc.settings.button_height
local w = game_doc.settings.width - game_doc.settings.edge_size * 2
local h = game_doc.settings.height - game_doc.settings.edge_size * 3 - game_doc.settings.header_size - game_doc.settings.button_height
--load hypertext via markdown2formspec
game_doc.add_direct_entry(
category_name,
entry_name,
md2f.md2ff(x,y,w,h,markdown_file,entry_name,md2f_settings),
md2f.md2ff(x,y,w,h,markdown_file,entry_name,game_doc.md2f_settings),
hidden
)
end

View File

@ -10,11 +10,16 @@
-- <> game_doc.entry_form() --
-- --
-- Use the above functions to show the stadard game_doc --
-- formspecs. --
-- formspecs. There is a fourth, private function which --
-- provides the help formspec found in the main form. --
-- --
-- This file also provides the functions for receiving and --
-- responding to the submission of these formspecs after --
-- these functions are defined. --
--------------------------------------------------------------
-- Common header for the three formspecs
local function header()
-- Common functions for the three formspecs
game_doc.header = function()
return table.concat(
{
"formspec_version[4]\n",
@ -24,6 +29,43 @@ local function header()
},"")
end
--Overridable button functions for i3 support
game_doc.help_button = function(x,y,w,h,i3)
if i3 then
return table.concat({
"image_button[",x,",",y,";",w,",",h,";game_doc_help.png;gmdc_help;;;false;game_doc_help_pressed.png]"
})
else
return table.concat({"button[",x,",",y,";",w,",",h,";gmdc_help;Help]\n"})
end
end
game_doc.back_button = function(x,y,w,h,i3)
if i3 then
return table.concat({"image_button[",x,",",y,";",w,",",h,";game_doc_back.png;gmdc_back;;;false;game_doc_back_pressed.png]"})
else
return table.concat({"button[",x,",",y,";",w,",",h,";gmdc_back;Back]\n"})
end
end
game_doc.select_button = function(x,y,w,h,i3)
if i3 then
return table.concat({"image_button[",x,",",y,";",w,",",h,";game_doc_select.png;gmdc_select;;;false;game_doc_select_pressed.png]"})
else
return table.concat({"button[",x,",",y,";",w,",",h,";gmdc_select;Select]\n"})
end
end
-- Function for hiding spaces to fix reorder issues
local function move_spaces(s)
local new_table = {}
for i=1,#s do
local _s = s[i]
new_table[i] = _s:match("%s*(.*)").._s:match("%s*")
end
return new_table
end
------------------------------
-- main_form
--
@ -57,19 +99,22 @@ game_doc.main_form = function(player_name)
local mname = game_doc.settings.main_name
local non_list_height = hsize+edge*2+button_h
-- Get list of categories
local category_list = {}
for k in pairs(game_doc.doc_data) do table.insert(category_list, k) end
table.sort(category_list)
category_list = table.concat(category_list, ",")
if game_doc.category_list == nil then
-- Get list of categories
local category_list = {}
for k in pairs(game_doc.doc_data) do table.insert(category_list, k) end
table.sort(category_list)
game_doc.category_list = category_list
game_doc.category_comma_list = table.concat(move_spaces(category_list), ",")
end
game_doc.ready_main_form = table.concat({
header(),
game_doc.header(),
"hypertext[0,0;",w,",",h,";;<style color=",hcolor," size=",hfsize,"><b><center>",mname,"</center></b></style>]\n",
"button[",edge,",",edge+hsize,";",button_w,",",button_h,";gdmc_help;Help]\n",
"button_exit[",(taw/2)-button_w/2,",",edge+hsize,";",button_w,",",button_h,";gdmc_quit;Quit]\n",
"button[",taw-button_w,",",edge+hsize,";",button_w,",",button_h,";gdmc_select;Select]\n",
"textlist[",edge,",",non_list_height,";",taw,",",h-non_list_height,";gmdc_list;",category_list,";1;false]\n",
game_doc.help_button(edge, edge+hsize, button_w, button_h, game_doc.i3),
game_doc.select_button(taw-button_w, edge+hsize, button_w, button_h, game_doc.i3),
"box[",edge,",",non_list_height,";",taw,",",h-non_list_height-edge,";#bababa25]\n",
"textlist[",edge,",",non_list_height,";",taw,",",h-non_list_height-edge,";gmdc_list;",game_doc.category_comma_list,";;true]\n",
},"")
end
return game_doc.ready_main_form
@ -109,26 +154,40 @@ game_doc.category_form = function(category_name, player_name)
local hfsize = game_doc.settings.main_font_size
local non_list_height = hsize+edge*2+button_h
-- Get list of categories
local entry_list = {}
for k in pairs(game_doc.doc_data[category_name].entries) do table.insert(entry_list, k) end
table.sort(entry_list)
entry_list = table.concat(entry_list, ",")
if game_doc.category_list == nil then
-- Get list of categories
local category_list = {}
for k in pairs(game_doc.doc_data) do table.insert(category_list, k) end
table.sort(category_list)
game_doc.category_list = category_list
game_doc.category_comma_list = table.concat(category_list, ",")
end
-- Get list of entries
if game_doc.entry_lists == nil then game_doc.entry_lists = {} end
if game_doc.entry_lists[category_name] == nil then
game_doc.entry_lists[category_name] = {}
local entry_list = {}
for k in pairs(game_doc.doc_data[category_name].entries) do table.insert(entry_list, k) end
table.sort(entry_list)
game_doc.entry_lists[category_name].entry_list = entry_list
game_doc.entry_lists[category_name].entry_comma_list = table.concat(move_spaces(entry_list), ",")
end
game_doc.ready_forms[category_name] = table.concat({
header(),
game_doc.header(),
"hypertext[0,0;",w,",",h,";;<style color=",hcolor," size=",hfsize,"><b><center>",category_name,"</center></b></style>]\n",
"button[",edge,",",edge+hsize,";",button_w,",",button_h,";gdmc_back;Back]\n",
"button_exit[",(taw/2)-button_w/2,",",edge+hsize,";",button_w,",",button_h,";gdmc_quit;Quit]\n",
"button[",taw-button_w,",",edge+hsize,";",button_w,",",button_h,";gdmc_select;Select]\n",
"textlist[",edge,",",non_list_height,";",taw,",",h-non_list_height,";gmdc_list;",entry_list,";1;false]\n",
game_doc.back_button(edge, edge+hsize, button_w, button_h, game_doc.i3),
game_doc.select_button(taw-button_w, edge+hsize, button_w, button_h, game_doc.i3),
"box[",edge,",",non_list_height,";",taw,",",h-non_list_height-edge,";#bababa25]\n",
"textlist[",edge,",",non_list_height,";",taw,",",h-non_list_height,";gmdc_list;",game_doc.entry_lists[category_name].entry_comma_list,";;true]\n",
},"")
end
return game_doc.ready_forms[category_name]
end
else --error
return table.concat({
header(),
game_doc.header(),
"label[0,0;Error: category: ", category_name, " does not exist.\n",
},"")
end
@ -149,7 +208,7 @@ game_doc.entry_form = function(category_name, entry_name, player_name)
else
return table.concat({
header(),
game_doc.header(),
"label[0,0;Error: player: ", player_name, " is unable to view this hidden entry.\n",
},"")
end
@ -162,18 +221,146 @@ game_doc.entry_form = function(category_name, entry_name, player_name)
local button_h = game_doc.settings.button_height
local taw = w - edge * 2 --text_area_width
local hsize = game_doc.settings.header_size
local hcolor = game_doc.settings.heading_color
local hfsize = game_doc.settings.main_font_size
return table.concat({
header(),
"button[",edge,",",edge,";",button_w,",",button_h,";gdmc_back;Back]\n",
"button_exit[",(taw/2)-button_w/2,",",edge,";",button_w,",",button_h,";gdmc_quit;Quit]\n",
game_doc.header(),
"hypertext[0,0;",w,",",h,";;<style color=",hcolor," size=",hfsize,"><b><center>",entry_name,"</center></b></style>]\n",
game_doc.back_button(edge, edge+hsize, button_w, button_h, game_doc.i3),
game_doc.doc_data[category_name].entries[entry_name].hypertext,
},"")
end
else --error
return table.concat({
header(),
game_doc.header(),
"label[0,0;Error: category: ", category_name, ", entry: ", entry_name," does not exist.\n",
},"")
end
end
end
------------------------------
-- help_form
--
-- Merely explains how to use this game_doc documentation
--
game_doc.help_form = function()
local x = game_doc.settings.edge_size
local y = game_doc.settings.edge_size + game_doc.settings.header_size
local w = game_doc.settings.width - game_doc.settings.edge_size * 2
local h = game_doc.settings.height - game_doc.settings.edge_size * 2 - game_doc.settings.header_size
local edge = game_doc.settings.edge_size
local button_w = game_doc.settings.button_width
local button_h = game_doc.settings.button_height
local hsize = game_doc.settings.header_size
return table.concat({
game_doc.header(),
game_doc.back_button(edge, edge+hsize, button_w, button_h, game_doc.i3),
md2f.md2f(x,y+edge+button_h,w,h-edge*2-button_h,
--begin markdown for help file
[[# **Game Guide Help**
This game guide is built to provide you with all the knowledge needed to enjoy every part of this game: from building, to mining, farming, fighting, flying, tinkering, and more.
#### Categories and Entries
The guide is broken into *Categories* and *Entires*. *Categories* are shown on the main
page, and once you **select** one or double click/tap that option in the list,
you will be greeted with that Category's page of *Entries*.
You then do the same on the entry page, and now you can read all about that exact topic.]]
--end markdown for help file
,"game_doc_help",
game_doc.md2f_settings),
},"")
end
------------------------------
-- on_recieve
--
-- Handles the above 4 formspec submissions
--
minetest.register_on_player_receive_fields(
function(player, formname, fields)
--Early fail for efficiency
if formname:sub(1,4) == "gmdc" then
local player_name = player:get_player_name()
minetest.log(dump(fields))
---------------Main Form---------------
if formname == "gmdc_main" then
--reused local function
local function show_category(player_name)
local index = game_doc.player_data[player_name].selected_category or nil
if index == nil then return end
if game_doc.settings.hidden_enable then
else
game_doc.player_data[player_name].selected_category = game_doc.category_list[index]
minetest.show_formspec(player_name,"gmdc_category",game_doc.category_form(game_doc.category_list[index], player_name))
end
end
--handle help
if fields.gmdc_help then
minetest.show_formspec(player_name,"gmdc_help", game_doc.help_form())
--handle select
elseif fields.gmdc_select then
show_category(player_name)
--handle text_list
elseif fields.gmdc_list then
local type, index = fields.gmdc_list:sub(1,3), tonumber(fields.gmdc_list:sub(5))
if type == "CHG" then
game_doc.player_data[player_name].selected_category = index
elseif type == "DCL" then
game_doc.player_data[player_name].selected_category = index
show_category(player_name)
end
end
---------------Category Form---------------
elseif formname == "gmdc_category" then
--reused local function
local function show_entry(player_name)
local index = game_doc.player_data[player_name].selected_entry or nil
if index == nil then return end
if game_doc.settings.hidden_enable then
else
local category = game_doc.player_data[player_name].selected_category
local entry = game_doc.entry_lists[category].entry_list[index]
minetest.show_formspec(player_name,"gmdc_entry",game_doc.entry_form(category, entry, player_name))
end
end
--handle back
if fields.gmdc_back then
game_doc.player_data[player_name].selected_category = nil
minetest.show_formspec(player_name,"gmdc_main", game_doc.main_form(player_name))
--handle select
elseif fields.gmdc_select then
show_entry(player_name)
--handle text_list
elseif fields.gmdc_list then
local type, index = fields.gmdc_list:sub(1,3), tonumber(fields.gmdc_list:sub(5))
if type == "CHG" then
game_doc.player_data[player_name].selected_entry = index
elseif type == "DCL" then
game_doc.player_data[player_name].selected_entry = index
show_entry(player_name)
end
end
---------------Entry Form---------------
elseif formname == "gmdc_entry" then
--handle back
if fields.gmdc_back then
game_doc.player_data[player_name].selected_entry = nil
minetest.show_formspec(player_name,"gmdc_category", game_doc.category_form(game_doc.player_data[player_name].selected_category,player_name))
end
---------------Help Form---------------
elseif formname == "gmdc_help" then
if fields.gmdc_help_back then
game_doc.player_data[player_name].selected_category = nil
minetest.show_formspec(player_name,"gmdc_main", game_doc.main_form(player_name))
end
end
end
end)

View File

@ -7,20 +7,176 @@
-- formspec. --
--------------------------------------------------------------
-- Chat Command Integration
if game_doc.settings.enable_chat_command then
-- Chat Command Integration (disabled if i3 is present)
if game_doc.settings.enable_chat_command and not rawget(_G, "i3") then
minetest.register_chatcommand("doc", {
privs = {
interact = true,
},
func = function(player_name, _)
minetest.show_formspec(
player_name,
"game_doc_main",
game_doc.main_form(player_name)
)
--game_doc.player_data[player_name].selected_category = 1
minetest.show_formspec(player_name,"gmdc_main",game_doc.main_form(player_name))
end,
})
end
-- i3 Integration
-- The following is essentially a bunch of overrides on the default guide formspecs
-- so that it fits very nicely into i3's world
if rawget(_G, "i3") then
game_doc.i3 = true
-- Override the header and other values, as everything will flow through i3
game_doc.header = function() return "" end
game_doc.settings.edge_size = 0.1
game_doc.settings.width = 10.23
game_doc.settings.height = 12
game_doc.settings.button_width = 0.6
game_doc.settings.button_height = 0.6
game_doc.settings.header_size = 0
game_doc.settings.main_font_size = 26
game_doc.settings.heading_color = "#FFF"
game_doc.current_form = "main"
game_doc.md2f_settings.background_color = "#bababa25"
--Register our new "Game Guide" Tab
i3.new_tab {
name = "guide",
description = "Game Guide",
-- Determine if the tab is visible by a player, `false` or `nil` hide the tab
access = function() return true end,
formspec = function(player, data, fs) end,
-----------------------
-- fields()
--
-- player: player objectRef
-- data: internal i3 data
-- fields: fields received by i3
--
-- This function is where all the magical integration happens
-- Long story short, the tab.formspec function gets called
-- with set_fs, which is the final bit of this function.
-- In order to support multiple pages, we have to override that
-- formspec function to write out the correct player formspec
--
-- The correct formspec can be the help page, main page,
-- category page, or entry page. What page is shown depends
-- on what fields are received.
--
-- The flow of the function is as follows
-- 1. Handle Fields
-- 2. Override tab[our_index].formspec
-- 3. Show/Update formspec
fields = function(player, data, fields)
local player_name = player:get_player_name()
-----------------Handle Main Form Fields------------------
if game_doc.player_data[player_name].current_form == "main" then
--Parse and process actual fields
if fields.gmdc_help then
game_doc.player_data[player_name].current_form = "help"
elseif fields.gmdc_select then
game_doc.player_data[player_name].current_form = "category"
elseif fields.gmdc_list then
local type, index = fields.gmdc_list:sub(1,3), tonumber(fields.gmdc_list:sub(5))
if type == "CHG" then
game_doc.player_data[player_name].category_index = index
elseif type == "DCL" then
game_doc.player_data[player_name].category_index = index
game_doc.player_data[player_name].current_form = "category"
end
end
-----------------Handle Category Form Fields------------------
elseif game_doc.player_data[player_name].current_form == "category" then
if fields.gmdc_back then
game_doc.player_data[player_name].category_index = nil
game_doc.player_data[player_name].current_form = "main"
elseif fields.gmdc_select then
game_doc.player_data[player_name].current_form = "entry"
elseif fields.gmdc_list then
local type, index = fields.gmdc_list:sub(1,3), tonumber(fields.gmdc_list:sub(5))
if type == "CHG" then
game_doc.player_data[player_name].selected_entry = index
elseif type == "DCL" then
game_doc.player_data[player_name].selected_entry = index
game_doc.player_data[player_name].current_form = "entry"
end
end
-----------------Handle Entry Form Fields------------------
elseif game_doc.player_data[player_name].current_form == "entry" then
if fields.gmdc_back then
game_doc.player_data[player_name].selected_entry = nil
game_doc.player_data[player_name].current_form = "category"
end
-----------------Handle Help Form Fields------------------
elseif game_doc.player_data[player_name].current_form == "help" then
if fields.gmdc_back then
game_doc.player_data[player_name].category_index = nil
game_doc.player_data[player_name].current_form = "main"
end
else --hasn't been set yet
game_doc.player_data[player_name].current_form = "main"
end
-----Override Formspec for tab-----
local tabs = i3.get_tabs()
local index = nil
for i=1,#tabs,1 do
if tabs[i].name == "guide" then
index = i
end
end
if index ~= nil then
-------------Handle displaying correct formspec-------------
local _fs = "" --variable to store the formspec to be shown
if game_doc.player_data[player_name].current_form == "help" then
_fs = game_doc.help_form(player_name)
elseif game_doc.player_data[player_name].current_form == "category" then
-- Get the selected category name
local index = game_doc.player_data[player_name].category_index or nil
if index == nil then
_fs = game_doc.main_form(player_name)
game_doc.player_data[player_name].current_form = "main"
else
if game_doc.settings.hidden_enable then
else
game_doc.player_data[player_name].selected_category = game_doc.category_list[index]
_fs = game_doc.category_form(game_doc.player_data[player_name].selected_category, player_name)
end
end
elseif game_doc.player_data[player_name].current_form == "entry" then
-- Get the selected entry name
local index = game_doc.player_data[player_name].selected_entry or nil
if index == nil then
_fs = game_doc.category_form(game_doc.player_data[player_name].selected_category, player_name)
game_doc.player_data[player_name].current_form = "category"
else
if game_doc.settings.hidden_enable then
else
local category = game_doc.player_data[player_name].selected_category
local entry = game_doc.entry_lists[category].entry_list[index]
_fs = game_doc.entry_form(category, entry, player_name)
end
end
else --main
_fs = game_doc.main_form(player_name)
end
tabs[index].formspec = function(player, data, fs)
fs(_fs)
end
else
tabs[index].formspec = function(player, data, fs)
fs("label[1,1,game_doc error in integration.lua]")
end
end
-----Display Formspec-----
i3.set_fs(player)
end,
}
end

View File

@ -25,6 +25,14 @@
-- returned, the old player value will be remembered. --
--------------------------------------------------------------
--All hidden data for each player is stored here
game_doc.player_data = {}
--------------------------
--
-- on_joinplayer
--
-- handles creating and loading a player's stored data
--
minetest.register_on_joinplayer(
function(player, last_login)
local player_name = player:get_player_name()
game_doc.player_data[player_name] = {}
end)

View File

@ -77,7 +77,7 @@ handleStandardVariable("game_doc_button_height", "button_height", 1.6)
handleStandardVariable("game_doc_bgcolor", "bgcolor", "#111E")
-- Formspec heading Color
handleStandardVariable("game_doc_heading_color", "heading_color", "#AFA")
handleStandardVariable("game_doc_heading_color", "heading_color", "#FFF")
--Text Specific--
@ -85,4 +85,20 @@ handleStandardVariable("game_doc_heading_color", "heading_color", "#AFA")
handleStandardVariable("game_doc_main_name", "main_name", "Game Guide")
-- Main Formspec Heading Font-Size
handleStandardVariable("game_doc_main_font_size", "main_font_size", 32)
handleStandardVariable("game_doc_main_font_size", "main_font_size", 32)
-- Markdown2Formspec
game_doc.md2f_settings = {
background_color = "#bababa25",
font_color = "#FFF",
heading_1_color = "#AFA",
heading_2_color = "#FAA",
heading_3_color = "#AAF",
heading_4_color = "#FFA",
heading_5_color = "#AFF",
heading_6_color = "#FAF",
code_block_mono_color = "#6F6",
code_block_font_size = 14,
mono_color = "#6F6",
block_quote_color = "#FFA",
}

View File

@ -48,6 +48,7 @@ game_doc = {}
game_doc.name = "game_doc"
game_doc.path = minetest.get_modpath(game_doc.name)
game_doc.doc_data = {} -- the actual entries
game_doc.player_data = {} -- for storing current selected entries/categories, and hidden values
game_doc.ready_forms = {} -- for storing ready made category formspecs- if hidden system is disabled
game_doc.mods_loaded = false
@ -55,14 +56,10 @@ game_doc.mods_loaded = false
dofile(game_doc.path .. "/code/settings.lua")
dofile(game_doc.path .. "/code/add_entries.lua")
dofile(game_doc.path .. "/code/direct_access.lua")
dofile(game_doc.path .. "/code/player_management.lua")
dofile(game_doc.path .. "/code/hidden_modifications.lua")
dofile(game_doc.path .. "/code/formspecs.lua")
dofile(game_doc.path .. "/code/integration.lua")
-- These are only used if the hidden system is enabled
if game_doc.hidden_enable then
dofile(game_doc.path .. "/code/player_management.lua")
dofile(game_doc.path .. "/code/hidden_modifications.lua")
end
-- Done, let 'em know
minetest.log("info","'game_doc' loaded successfully")

View File

@ -2,4 +2,5 @@ name=game_doc
description=A Flexible In-Game Documentation System
title=game_doc
depends=markdown2formspec
optional_depends=i3
author=Just_Visiting

View File

@ -13,7 +13,7 @@ game_doc_enable_chat_command (Enable chat command access) enum Enabled Enabled,D
#------------Graphical Settings------------#
--Dimensions--
# --Dimensions--
# Full Width of all game_doc formspecs
game_doc_width (Formspec Width) float 20.0
@ -33,15 +33,15 @@ game_doc_button_width (Button Width) float 5.0
# The button heights
game_doc_button_height (Button Height) float 1.6
--Colors--
# --Colors--
# Formspec Background Color
game_doc_bgcolor (Background Color) string #111E
game_doc_bgcolor (Background Color) string #bababa25
# Formspec heading Color
game_doc_heading_color (Heading Color) string #AFA
game_doc_heading_color (Heading Color) string #FFF
--Text Specific--
# --Text Specific--
# Main Formspec Name
game_doc_main_name (Main Formspec Heading) string Game Guide

BIN
textures/game_doc_back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

BIN
textures/game_doc_help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B