Initial commit
This commit is contained in:
commit
7e4a64c890
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
default?
|
|
@ -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
|
|
@ -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)
|
Reference in New Issue