You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

core.lua 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. --
  2. -- formspeclib core - Better and easier formspecs for Minetest
  3. --
  4. -- © 2017 by luk3yx
  5. --
  6. -- This is only the core rendering process.
  7. formspeclib = {}
  8. local objects = {}
  9. -- formspeclib.version: The version of formspeclib.
  10. formspeclib.version = 0.1
  11. --
  12. -- formspeclib.render(): Renders a formspeclib object into a formspec.
  13. --
  14. -- Syntax: formspeclib.render(formspeclib_object, safe_mode, no_iterations)
  15. --
  16. -- formspeclib_object: The formspeclib object to render.
  17. -- safe_mode: Optional. If it is enabled, the renderer does safety
  18. -- checks so the server does not crash.
  19. -- no_iterations: Optional, not recommended. Only allows formspeclib
  20. -- objects that produce a direct formspec string.
  21. --
  22. formspeclib.render = function(formspec, safe_mode, no_iterations)
  23. if safe_mode and type(formspec) ~= 'table' then
  24. -- Don't throw an error, just don't render the formspec.
  25. return false
  26. end
  27. local compiled = ''
  28. local i
  29. local width
  30. local height
  31. if type(formspec.width) == 'number' then
  32. width = formspec.width
  33. else
  34. width = 0
  35. end
  36. if type(formspec.height) == 'number' then
  37. height = formspec.height
  38. else
  39. height = 0
  40. end
  41. if type(no_iterations) ~= 'number' and no_iterations then
  42. no_iterations = 1
  43. end
  44. for i = 1, #formspec do
  45. if safe_mode and type(formspec[i]) ~= 'table' then
  46. return false
  47. elseif not formspec[i].type then
  48. -- The formspec is defining the global width/height.
  49. if type(formspec[i].width) == 'number' then
  50. width = obj.width
  51. end
  52. if type(formspec[i].height) == 'number' then
  53. height = obj.height
  54. end
  55. elseif objects[formspec[i].type] then
  56. local a
  57. local o
  58. if safe_mode then
  59. a, o = pcall(objects[formspec[i].type], formspec[i], safe_mode)
  60. if not a then o = false end
  61. else
  62. o = objects[formspec[i].type](formspec[i], safe_mode)
  63. end
  64. if type(o) == 'string' then
  65. compiled = compiled .. o
  66. elseif type(o) == 'table' then
  67. if no_iterations and no_iterations < 1 then return false end
  68. local iter
  69. if no_iterations then
  70. iter = no_iterations - 1
  71. elseif safe_mode then
  72. iter = 3
  73. end
  74. o = formspeclib.render(o, safe_mode, iter)
  75. if not o then return false end
  76. compiled = compiled .. o
  77. else
  78. return false
  79. end
  80. else
  81. -- On unknown element
  82. return false
  83. end
  84. end
  85. if width > 0 and height > 0 then
  86. -- The below three lines are here to ensure compatibility with Minetest
  87. -- 0.4.X. When the variables are removed from minetest_game they will
  88. -- simply be ignored by the mod.
  89. if default and default.gui_bg and default.gui_bg_img and default.gui_slots then
  90. compiled = default.gui_bg .. default.gui_bg_img .. default.gui_slots .. compiled
  91. end
  92. compiled = 'size[' ..
  93. tostring(width) .. ',' .. tostring(height) ..
  94. ']' .. compiled
  95. end
  96. return compiled
  97. end
  98. --
  99. -- formspeclib.register_object(): Create a formspeclib object
  100. --
  101. -- Syntax: formspeclib.register_object(name, function)
  102. --
  103. -- name: The name of the object (set in 'type'). It is recommended to make this
  104. -- 'mod:object' unless you are overriding an object.
  105. -- func: The function to generate the object. This function gets sent the
  106. -- formspec chunk to generate, and will return a string or formspeclib
  107. -- formspec, otherwise false to indicate an error.
  108. --
  109. formspeclib.register_object = function(name, func)
  110. if type(func) ~= 'function' then
  111. return false
  112. end
  113. objects[name] = func
  114. return true
  115. end
  116. --
  117. -- formspeclib.escape(): Escape and stringify text.
  118. --
  119. -- This may seem useless, but it is actually quite useful.
  120. --
  121. formspeclib.escape = function(text)
  122. return minetest.formspec_escape(tostring(text))
  123. end