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.

objects.lua 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. --
  2. -- formspeclib default objects
  3. --
  4. -- These are unprefixed, however if you create a mod that registers objects,
  5. -- it is recommended to prefix them with your mod name to prevent conflicts.
  6. --
  7. --
  8. -- Raw formspec data
  9. --
  10. -- Parameters: data
  11. --
  12. -- Example 'bgcolor[#fff;true;]':
  13. -- {
  14. -- type = 'formspeclib:raw_formspec',
  15. -- data = 'bgcolor[#fff;true;]',
  16. -- }
  17. --
  18. -- Using this is not recommended, and it is disabled in safe mode as it can be
  19. -- used to crash MT clients, effectively kicking an unsuspecting victim.
  20. --
  21. formspeclib.register_object('formspeclib:raw_formspec', function(obj, safe_mode)
  22. if safe_mode or type(obj.data) ~= 'string' then
  23. return false
  24. else
  25. return obj.data
  26. end
  27. end)
  28. --
  29. -- A label
  30. --
  31. -- Parameters: x, y, align(?), text
  32. --
  33. -- Example 'label[1,1;Hello world!]':
  34. -- {
  35. -- type = 'text',
  36. -- x = 1,
  37. -- y = 1,
  38. -- align = 'left',
  39. -- text = 'Hello world!'
  40. -- }
  41. --
  42. -- align can be one of 'left', 'centre'/'center', or 'vertical'. If align is
  43. -- set to 'centre'/'center', you can also set width and height.
  44. --
  45. formspeclib.register_object('text', function(obj, safe_mode)
  46. if not obj.text or not obj.x or not obj.y then return false end
  47. if not obj.align then obj.align = 'left' end
  48. local x = formspeclib.escape(obj.x)
  49. local y = formspeclib.escape(obj.y)
  50. local text = formspeclib.escape(obj.text)
  51. if obj.align == 'left' then
  52. return 'label[' .. x .. ',' .. y .. ';' .. text .. ']'
  53. elseif obj.align == 'centre' or obj.align == 'center' then
  54. -- This magical hack lets you centre/center text in formspecs.
  55. -- Make sure your formspec ignores 'formspeclib:ignore'.
  56. local width = formspeclib.escape(obj.width or 8)
  57. local height = formspeclib.escape(obj.height or 0.5)
  58. return 'image_button[' .. x .. ',' .. y .. ';' .. width .. ',' ..
  59. height .. ';' ..
  60. formspeclib.escape('default_dirt.png^[colorize:#343434') ..
  61. ';formspeclib:ignore;' .. text .. ']'
  62. elseif obj.align == 'vertical' then
  63. return 'vertlabel[' .. x .. ',' .. y .. ';' .. text .. ']'
  64. else
  65. return false
  66. end
  67. end)
  68. --
  69. -- An image
  70. --
  71. -- Parameters: x, y, width(?), height(?), image
  72. --
  73. -- Example 'image[1,1;1,1;default_dirt.png]':
  74. -- {
  75. -- type = 'image',
  76. -- x = 1,
  77. -- y = 1,
  78. -- width = 1,
  79. -- height = 1,
  80. -- image = 'default_dirt.png'
  81. -- }
  82. formspeclib.register_object('image', function(obj, safe_mode)
  83. if not obj.image or not obj.x or not obj.y then return false end
  84. local x = formspeclib.escape(obj.x)
  85. local y = formspeclib.escape(obj.y)
  86. local width = formspeclib.escape(obj.width or obj.height or 1)
  87. local height = formspeclib.escape(obj.height or obj.width or 1)
  88. local image = formspeclib.escape(obj.image)
  89. return 'image[' .. x .. ',' .. y .. ';' .. width .. ',' .. height .. ';' ..
  90. image .. ']'
  91. end)
  92. --
  93. -- A button
  94. --
  95. -- Parameters: x, y, width, height(?), name, text, quit(?), image(?)
  96. --
  97. -- Example 'image_button_exit[1,1;3,1;button_cancel.png;cancel;Cancel]':
  98. -- {
  99. -- type = 'button',
  100. -- x = 1,
  101. -- y = 1,
  102. -- width = 3,
  103. -- height = 1,
  104. -- name = 'cancel',
  105. -- text = 'Cancel',
  106. -- quit = true,
  107. -- image = 'button_cancel.png',
  108. -- }
  109. --
  110. formspeclib.register_object('button', function(obj, safe_mode)
  111. if not obj.text or not obj.x or not obj.y or not obj.width or not obj.name then
  112. return false
  113. end
  114. local x = formspeclib.escape(obj.x)
  115. local y = formspeclib.escape(obj.y)
  116. local w = formspeclib.escape(obj.width)
  117. local h = formspeclib.escape(obj.height or 2)
  118. local name = formspeclib.escape(obj.name)
  119. local text = formspeclib.escape(obj.text)
  120. local t = 'button'
  121. local img = ''
  122. if obj.quit then
  123. t = t .. '_exit'
  124. end
  125. if obj.image then
  126. t = 'image_' .. t
  127. img = ';' .. formspeclib.escape(obj.image)
  128. if not obj.quit and not string.find(img, '.') then
  129. t = 'item_' .. t
  130. end
  131. end
  132. return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. img .. ';' ..
  133. name .. ';' .. text .. ']'
  134. end)
  135. --
  136. -- A text box
  137. --
  138. -- Parameters: x, y, width, height(?), name, label(?), default(?), password(?)
  139. --
  140. -- Example 'textarea[1,1;2,3;message;Yay]':
  141. -- {
  142. -- type = 'textbox',
  143. -- x = 1,
  144. -- y = 1,
  145. -- width = 2,
  146. -- height = 3,
  147. -- default = 'Yay',
  148. -- name = 'message',
  149. -- }
  150. formspeclib.register_object('textbox', function(obj, safe_mode)
  151. if not obj.x or not obj.y or not obj.width or not obj.name then
  152. return false
  153. end
  154. local x = formspeclib.escape(obj.x)
  155. local y = formspeclib.escape(obj.y)
  156. local w = formspeclib.escape(obj.width)
  157. local name = formspeclib.escape(obj.name)
  158. local l = formspeclib.escape(obj.label or '')
  159. local def = formspeclib.escape(obj.default or '')
  160. local t = 'field'
  161. local img = ''
  162. def = ';' .. def
  163. local h
  164. if obj.height then
  165. h = formspeclib.escape(obj.height)
  166. t = 'textarea'
  167. else
  168. h = 2
  169. end
  170. if obj.password then
  171. if obj.default or obj.height then
  172. return false
  173. else
  174. t = 'pwd' .. t
  175. def = ''
  176. end
  177. end
  178. if not obj.close_on_enter and obj.close_on_enter ~= nil then
  179. if t == 'field' then
  180. def = def .. ']field_close_on_enter[' .. name .. ';false'
  181. end
  182. end
  183. return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. ';' .. name ..
  184. ';' .. l .. def .. ']'
  185. end)
  186. --
  187. -- A combo box
  188. --
  189. -- Parameters: x, y, width, height(?), name, items, label(?), default(?)
  190. --
  191. formspeclib.register_object('combobox', function(obj, safe_mode)
  192. if not obj.x or not obj.y or not obj.width or not obj.name or not obj.items then
  193. return false
  194. end
  195. local x = formspeclib.escape(obj.x)
  196. local y = formspeclib.escape(obj.y)
  197. local w = formspeclib.escape(obj.width)
  198. local name = formspeclib.escape(obj.name)
  199. local l = formspeclib.escape(obj.label or '')
  200. local def = formspeclib.escape(obj.default or '')
  201. local img = ''
  202. def = ';' .. def
  203. local h
  204. local t
  205. local i
  206. local items
  207. for i = 1, #obj.items do
  208. if i ~= 1 then i = i .. ';' end
  209. items = items .. obj.items[i]
  210. end
  211. if obj.height then
  212. h = formspeclib.escape(obj.height)
  213. t = 'textlist'
  214. else
  215. h = 2
  216. t = 'dropdown'
  217. end
  218. return t .. '[' .. x .. ',' .. y .. ';' .. w .. ',' .. h .. ';' .. name ..
  219. ';' .. l .. def .. ']'
  220. end)
  221. --
  222. -- An inventory list
  223. --
  224. -- Parameters: location(?), name(?), x, y, width, height, start_at(?), shift_click(?)
  225. --
  226. formspeclib.register_object('inventory', function(obj, safe_mode)
  227. if not obj.x or not obj.y or not obj.width or not obj.height then
  228. return false
  229. end
  230. local x = formspeclib.escape(obj.x)
  231. local y = formspeclib.escape(obj.y)
  232. local w = formspeclib.escape(obj.width)
  233. local h = formspeclib.escape(obj.height)
  234. local location = formspeclib.escape(obj.location or 'current_player')
  235. local name = formspeclib.escape(obj.name or 'main')
  236. local start = formspeclib.escape(obj.start_at or '')
  237. if safe_mode and location ~= 'current_player' and location ~= 'context' then
  238. -- You are not allowed to use other locations in safe mode.
  239. return false
  240. end
  241. local extra = ''
  242. if obj.shift_click then
  243. extra = 'listring[' .. location .. ';' .. name .. ']'
  244. end
  245. return 'list[' .. location .. ';' .. name .. ';' .. x .. ',' .. y .. ';' ..
  246. w .. ',' .. h .. ';' .. start .. ']' .. extra
  247. end)
  248. --
  249. -- A semitransparent box
  250. --
  251. -- Parameters: x, y, width, height, colour/color
  252. --
  253. -- Example 'box[1,1;1,1;black]':
  254. -- {
  255. -- type = 'image',
  256. -- x = 1,
  257. -- y = 1,
  258. -- width = 1,
  259. -- height = 1,
  260. -- colour = 'black'
  261. -- }
  262. formspeclib.register_object('box', function(obj, safe_mode)
  263. if (not obj.colour and not obj.color) or not obj.x or not obj.y then
  264. return false
  265. end
  266. local x = formspeclib.escape(obj.x)
  267. local y = formspeclib.escape(obj.y)
  268. local width = formspeclib.escape(obj.width or obj.height or 4)
  269. local height = formspeclib.escape(obj.height or obj.width or 4)
  270. local colour = formspeclib.escape(obj.colour or obj.color)
  271. return 'box[' .. x .. ',' .. y .. ';' .. width .. ',' .. height .. ';' ..
  272. colour .. ']'
  273. end)
  274. --
  275. -- A container
  276. --
  277. -- Parameters: x, y, children
  278. --
  279. -- Each element inside the container is offset by the x and y
  280. --
  281. formspeclib.register_object('container', function(obj, safe_mode)
  282. local t = {
  283. {
  284. type = 'formspeclib:container_start',
  285. x = formspeclib.escape(obj.x or 0),
  286. y = formspeclib.escape(obj.y or 0),
  287. },
  288. (table.unpack or unpack)(obj)
  289. }
  290. table.insert(t, {type = 'formspeclib:container_end'})
  291. return t
  292. end)
  293. formspeclib.register_object('formspeclib:container_start', function(obj, safe_mode)
  294. if not obj.x or not obj.y then
  295. return false
  296. end
  297. local x = formspeclib.escape(obj.x)
  298. local y = formspeclib.escape(obj.y)
  299. obj.x = nil
  300. obj.y = nil
  301. return 'container[' .. x .. ',' .. y .. ']'
  302. end)
  303. formspeclib.register_object('formspeclib:container_end', function(obj, safe_mode)
  304. return 'container_end[]'
  305. end)