Initial commit

This commit is contained in:
luk3yx 2018-03-24 10:56:56 +13:00
commit 7e4a64c890
7 changed files with 415 additions and 0 deletions

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
# MIT License
*Copyright © 2018 by luk3yx*
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

23
Progress Normal file
View File

@ -0,0 +1,23 @@
http://dev.minetest.net/formspec
size: Done!
list: Incomplete
image: image
field: textbox
pwdfield: textbox
textarea: textbox
label: text
vertlabel: text
button: button
image_button: button
item_image_button: button
button_exit: button
image_button_exit: button
listcolors: formspeclib:raw_formspec
bgcolor: formspeclib:raw_formspec
background: formspeclib:raw_formspec
textlist: combobox
dropdown: combobox
Incomplete:
list

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# formspeclib
A formspec renderer for Minetest.

117
core.lua Normal file
View File

@ -0,0 +1,117 @@
--
-- formspeclib core - Better and easier formspecs for Minetest
--
-- © 2017 by luk3yx
--
-- This is only the core rendering process.
formspeclib = {}
local objects = {}
-- formspeclib.version: The version of formspeclib.
formspeclib.version = 0.1
--
-- formspeclib.render(): Renders a formspeclib object into a formspec.
--
-- Syntax: formspeclib.render(formspeclib_object, safe_mode, no_iterations)
--
-- formspeclib_object: The formspeclib object to render.
-- safe_mode: Optional. If it is enabled, the renderer does safety
-- checks so the server does not crash.
-- no_iterations: Optional, not recommended. Only allows formspeclib
-- objects that produce a direct formspec string.
--
formspeclib.render = function(formspec, safe_mode, no_iterations)
if safe_mode and type(formspec) ~= 'table' then
-- Don't throw an error, just don't render the formspec.
return false
end
local compiled = ''
local i
local width
local height
if type(formspec.width) == 'number' then
width = formspec.width
else
width = 0
end
if type(formspec.height) == 'number' then
height = formspec.height
else
height = 0
end
for i = 1, #formspec do
if safe_mode and type(formspec[i]) ~= 'table' then
return false
elseif not formspec[i].type then
-- The formspec is defining the global width/height.
if type(formspec[i].width) == 'number' then
width = obj.width
end
if type(formspec[i].height) == 'number' then
height = obj.height
end
elseif objects[formspec[i].type] then
local a
local o
if safe_mode then
a, o = pcall(objects[formspec[i].type], formspec[i], safe_mode)
if not a then o = false end
else
o = objects[formspec[i].type](formspec[i], safe_mode)
end
if type(o) == 'string' then
compiled = compiled .. o
elseif type(o) == 'table' and not no_iterations then
o = formspeclib.render(o, safe_mode, safe_mode or no_iterations)
if not o then return false end
compiled = compiled .. o
else
return false
end
else
-- On unknown element
return false
end
end
if width > 0 and height > 0 then
if default and default.gui_bg and default.gui_bg_img and default.gui_slots then
compiled = default.gui_bg .. default.gui_bg_img .. default.gui_slots .. compiled
end
compiled = 'size[' ..
tostring(width) .. ',' .. tostring(height) ..
']' .. compiled
end
return compiled
end
--
-- formspeclib.register_object(): Create a formspeclib object
--
-- Syntax: formspeclib.register_object(name, function)
--
-- name: The name of the object (set in 'type'). It is recommended to make this
-- 'mod:object' unless you are overriding an object.
-- func: The function to generate the object. This function gets sent the
-- formspec chunk to generate, and will return a string or formspeclib
-- formspec, otherwise false to indicate an error.
--
formspeclib.register_object = function(name, func)
if type(func) ~= 'function' then
return false
end
objects[name] = func
return true
end
--
-- formspeclib.escape(): Escape and stringify text.
--
-- This may seem useless, but it is actually quite useful.
--
formspeclib.escape = function(text)
return minetest.formspec_escape(tostring(text))
end

1
depends.txt Normal file
View File

@ -0,0 +1 @@
default?

10
init.lua Normal file
View File

@ -0,0 +1,10 @@
--
-- formspeclib - Better and easier formspecs for Minetest
-- Version 0.1
--
-- © 2017 by luk3yx
--
local path = minetest.get_modpath('formspeclib')
dofile(path .. '/core.lua') -- formspeclib core
dofile(path .. '/objects.lua') -- Default formspeclib objects

240
objects.lua Normal file
View File

@ -0,0 +1,240 @@
--
-- formspeclib default objects
--
-- These are unprefixed, however if you create a mod that registers objects,
-- it is recommended to prefix them with your mod name to prevent conflicts.
--
--
-- Raw formspec data
--
-- Parameters: data
--
-- Example 'bgcolor[#fff;true;]':
-- {
-- type = 'formspeclib:raw_formspec',
-- data = 'bgcolor[#fff;true;]',
-- }
--
-- Using this is not recommended, and it is disabled in safe mode as it can be
-- used to crash MT clients, effectively kicking an unsuspecting victim.
--
formspeclib.register_object('formspeclib:raw_formspec', function(obj, safe_mode)
if safe_mode or type(obj.data) ~= 'string' then
return false
else
return obj.data
end
end)
--
-- A label
--
-- Parameters: x, y, align(?), text
--
-- Example 'label[1,1;Hello world!]':
-- {
-- type = 'text',
-- x = 1,
-- y = 1,
-- align = 'left',
-- text = 'Hello world!'
-- }
--
-- align can be one of 'left', 'centre'/'center', or 'vertical'. If align is
-- set to 'centre'/'center', you can also set width and height.
--
formspeclib.register_object('text', function(obj, safe_mode)
if not obj.text or not obj.x or not obj.y then return false end
if not obj.align then obj.align = 'left' end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local text = formspeclib.escape(obj.text)
if obj.align == 'left' then
return 'label[' .. x .. ',' .. y .. ';' .. text .. ']'
elseif obj.align == 'centre' or obj.align == 'center' then
-- This magical hack lets you centre/center text in formspecs.
-- Make sure your formspec ignores 'formspeclib:ignore'.
local width = formspeclib.escape(obj.width or 8)
local height = formspeclib.escape(obj.height or 0.5)
return 'image_button[' .. x .. ',' .. y .. ';' .. width .. ',' ..
height .. ';' .. formspeclib.escape('default_dirt.png^[colorize:#343434') .. ';formspeclib:ignore;' ..
text .. ']'
elseif obj.align == 'vertical' then
return 'vertlabel[' .. x .. ',' .. y .. ';' .. text .. ']'
else
return false
end
end)
--
-- An image
--
-- Parameters: x, y, width(?), height(?), image
--
-- Example 'image[1,1;1,1;default_dirt.png]':
-- {
-- type = 'image',
-- x = 1,
-- y = 1,
-- width = 1,
-- height = 1,
-- image = 'default_dirt.png'
-- }
formspeclib.register_object('image', function(obj, safe_mode)
if not obj.image or not obj.x or not obj.y then return false end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local width = formspeclib.escape(obj.width or obj.height or 1)
local height = formspeclib.escape(obj.height or obj.width or 1)
local image = formspeclib.escape(obj.image)
return 'image[' .. x .. ',' .. y .. ';' .. width .. ',' .. height .. ';' .. image .. ']'
end)
--
-- A button
--
-- Parameters: x, y, width, height(?), name, text, quit(?), image(?)
--
-- Example 'image_button_exit[1,1;3,1;button_cancel.png;cancel;Cancel]':
-- {
-- type = 'button',
-- x = 1,
-- y = 1,
-- width = 3,
-- height = 1,
-- name = 'cancel',
-- text = 'Cancel',
-- quit = true,
-- image = 'button_cancel.png',
-- }
--
formspeclib.register_object('button', function(obj, safe_mode)
if not obj.text or not obj.x or not obj.y or not obj.width or not obj.name then
return false
end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local w = formspeclib.escape(obj.width)
local h = formspeclib.escape(obj.height or 2)
local name = formspeclib.escape(obj.name)
local text = formspeclib.escape(obj.text)
local t = 'button'
local img = ''
if obj.quit then
t = t .. '_exit'
end
if obj.image then
t = 'image_' .. t
img = ';' .. formspeclib.escape(obj.image)
if not obj.quit and not string.find(img, '.') then
t = 'item_' .. t
end
end
return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. img .. ';' .. name .. ';' .. text .. ']'
end)
--
-- A text box
--
-- Parameters: x, y, width, height(?), name, label(?), default(?), password(?)
--
-- Example 'textarea[1,1;2,3;message;Yay]':
-- {
-- type = 'textbox',
-- x = 1,
-- y = 1,
-- width = 2,
-- height = 3,
-- default = 'Yay',
-- name = 'message',
-- }
formspeclib.register_object('textbox', function(obj, safe_mode)
if obj.x or not obj.y or not obj.width or not obj.name then
return false
end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local w = formspeclib.escape(obj.width)
local name = formspeclib.escape(obj.name)
local l = formspeclib.escape(obj.label or '')
local def = formspeclib.escape(obj.default or '')
local t = 'field'
local img = ''
def = ';' .. def
local h
if obj.height then
h = formspeclib.escape(obj.height)
t = 'textarea'
else
h = 2
end
if obj.password then
if obj.default or obj.height then
return false
else
t = 'pwd' .. t
def = ''
end
end
return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. ';' .. name .. ';' .. l .. def .. ']'
end)
--
-- A combo box
--
-- Parameters: x, y, width, height(?), name, label(?), default(?), password(?)
--
formspeclib.register_object('combobox', function(obj, safe_mode)
if not obj.x or not obj.y or not obj.width or not obj.name or not obj.items then
return false
end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local w = formspeclib.escape(obj.width)
local name = formspeclib.escape(obj.name)
local l = formspeclib.escape(obj.label or '')
local def = formspeclib.escape(obj.default or '')
local img = ''
def = ';' .. def
local h
local t
local i
local items
for i = 1, #obj.items do
if i ~= 1 then i = i .. ';' end
items = items .. obj.items[i]
end
if obj.height then
h = formspeclib.escape(obj.height)
t = 'textlist'
else
h = 2
t = 'dropdown'
end
return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. ';' .. name .. ';' .. l .. def .. ']'
end)
--
-- An inventory list
--
-- Parameters: location(?), name(?), x, y, width, height, start_at(?)
--
formspeclib.register_object('inventory', function(obj, safe_mode)
if not obj.x or not obj.y or not obj.width or not obj.height then
return false
end
local x = formspeclib.escape(obj.x)
local y = formspeclib.escape(obj.y)
local w = formspeclib.escape(obj.width)
local h = formspeclib.escape(obj.height)
local location = formspeclib.escape(obj.location or 'current_player')
local name = formspeclib.escape(obj.name or 'main')
local start = formspeclib.escape(obj.start_at or '')
if safe_mode and location ~= 'current_player' and location ~= 'context' then
-- You are not allowed to use other locations in safe mode.
return false
end
return 'list[' .. location .. ';' .. name .. ';' .. x .. ',' .. y .. ';' ..
w .. ',' .. h .. ';' .. start .. ']'
end)