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.

291 lines
7.5KB

  1. ----------------------
  2. -- Vector functions --
  3. ----------------------
  4. function pipeworks.vector_cross(a, b)
  5. return {
  6. x = a.y * b.z - a.z * b.y,
  7. y = a.z * b.x - a.x * b.z,
  8. z = a.x * b.y - a.y * b.x
  9. }
  10. end
  11. function pipeworks.vector_dot(a, b)
  12. return a.x * b.x + a.y * b.y + a.z * b.z
  13. end
  14. -----------------------
  15. -- Facedir functions --
  16. -----------------------
  17. function pipeworks.facedir_to_top_dir(facedir)
  18. return ({[0] = {x = 0, y = 1, z = 0},
  19. {x = 0, y = 0, z = 1},
  20. {x = 0, y = 0, z = -1},
  21. {x = 1, y = 0, z = 0},
  22. {x = -1, y = 0, z = 0},
  23. {x = 0, y = -1, z = 0}})
  24. [math.floor(facedir / 4)]
  25. end
  26. function pipeworks.facedir_to_right_dir(facedir)
  27. return pipeworks.vector_cross(
  28. pipeworks.facedir_to_top_dir(facedir),
  29. minetest.facedir_to_dir(facedir)
  30. )
  31. end
  32. local directions = {}
  33. pipeworks.directions = directions
  34. function directions.side_to_dir(side)
  35. return ({[0] = vector.new(),
  36. vector.new( 0, 1, 0),
  37. vector.new( 0, -1, 0),
  38. vector.new( 1, 0, 0),
  39. vector.new(-1, 0, 0),
  40. vector.new( 0, 0, 1),
  41. vector.new( 0, 0, -1)
  42. })[side]
  43. end
  44. function directions.dir_to_side(dir)
  45. local c = pipeworks.vector_dot(dir, vector.new(1, 2, 3)) + 4
  46. return ({6, 2, 4, 0, 3, 1, 5})[c]
  47. end
  48. ----------------------
  49. -- String functions --
  50. ----------------------
  51. --[[function pipeworks.string_split(str, sep)
  52. local fields = {}
  53. local index = 1
  54. local expr = "([^"..sep.."])+"
  55. string.gsub(str, expr, function(substring)
  56. fields[index] = substring
  57. index = index + 1
  58. end)
  59. return fields
  60. end]]
  61. function pipeworks.string_startswith(str, substr)
  62. return str:sub(1, substr:len()) == substr
  63. end
  64. ---------------------
  65. -- Table functions --
  66. ---------------------
  67. function pipeworks.table_contains(tbl, element)
  68. for _, elt in pairs(tbl) do
  69. if elt == element then
  70. return true
  71. end
  72. end
  73. return false
  74. end
  75. function pipeworks.table_extend(tbl, tbl2)
  76. local index = #tbl + 1
  77. for _, elt in ipairs(tbl2) do
  78. tbl[index] = elt
  79. index = index + 1
  80. end
  81. end
  82. function pipeworks.table_recursive_replace(tbl, pattern, replace_with)
  83. if type(tbl) == "table" then
  84. local tbl2 = {}
  85. for key, value in pairs(tbl) do
  86. tbl2[key] = pipeworks.table_recursive_replace(value, pattern, replace_with)
  87. end
  88. return tbl2
  89. elseif type(tbl) == "string" then
  90. return tbl:gsub(pattern, replace_with)
  91. else
  92. return tbl
  93. end
  94. end
  95. ------------------------
  96. -- Formspec functions --
  97. ------------------------
  98. local fs_helpers = {}
  99. pipeworks.fs_helpers = fs_helpers
  100. function fs_helpers.on_receive_fields(pos, fields)
  101. local meta = minetest.get_meta(pos)
  102. for field, value in pairs(fields) do
  103. if pipeworks.string_startswith(field, "fs_helpers_cycling:") then
  104. local l = field:split(":")
  105. local new_value = tonumber(l[2])
  106. local meta_name = l[3]
  107. meta:set_int(meta_name, new_value)
  108. end
  109. end
  110. end
  111. function fs_helpers.cycling_button(meta, base, meta_name, values)
  112. local current_value = meta:get_int(meta_name)
  113. local new_value = (current_value + 1) % (#values)
  114. local val = values[current_value + 1]
  115. local text
  116. local texture_name = nil
  117. local addopts = nil
  118. --when we get a table, we know the caller wants an image_button
  119. if type(val) == "table" then
  120. text = val["text"]
  121. texture_name = val["texture"]
  122. addopts = val["addopts"]
  123. else
  124. text = val
  125. end
  126. local field = "fs_helpers_cycling:"..new_value..":"..meta_name
  127. return base..";"..(texture_name and texture_name..";" or "")..field..";"..minetest.formspec_escape(text)..(addopts and ";"..addopts or "").."]"
  128. end
  129. ---------
  130. -- Env --
  131. ---------
  132. function pipeworks.load_position(pos)
  133. if pos.x < -30912 or pos.y < -30912 or pos.z < -30912 or
  134. pos.x > 30927 or pos.y > 30927 or pos.z > 30927 then return end
  135. if minetest.get_node_or_nil(pos) then
  136. return
  137. end
  138. local vm = minetest.get_voxel_manip()
  139. vm:read_from_map(pos, pos)
  140. end
  141. local function delay(...)
  142. local args = {...}
  143. return (function() return unpack(args) end)
  144. end
  145. local function get_set_wrap(name, is_dynamic)
  146. return (function(self)
  147. return self["_" .. name]
  148. end), (function(self, value)
  149. if is_dynamic then
  150. self["_" .. name] = type(value) == "table"
  151. and table.copy(value) or value
  152. end
  153. end)
  154. end
  155. function pipeworks.create_fake_player(def, is_dynamic)
  156. local wielded_item = ItemStack("")
  157. if def.inventory and def.wield_list then
  158. wielded_item = def.inventory:get_stack(def.wield_list, def.wield_index or 1)
  159. end
  160. local p = {
  161. get_player_name = delay(def.name),
  162. is_player = delay(true),
  163. is_fake_player = true,
  164. _formspec = def.formspec or default.gui_survival_form,
  165. _hp = def.hp or 20,
  166. _breath = 11,
  167. _pos = def.position and table.copy(def.position) or vector.new(),
  168. _properties = def.properties or { eye_height = def.eye_height or 1.47 },
  169. _inventory = def.inventory,
  170. _wield_index = def.wield_index or 1,
  171. _wielded_item = wielded_item,
  172. -- Model and view
  173. _eye_offset1 = vector.new(),
  174. _eye_offset3 = vector.new(),
  175. set_eye_offset = function(self, first, third)
  176. self._eye_offset1 = table.copy(first)
  177. self._eye_offset3 = table.copy(third)
  178. end,
  179. get_eye_offset = function(self)
  180. return self._eye_offset1, self._eye_offset3
  181. end,
  182. get_look_dir = delay(def.look_dir or {x=0, y=0, z=1}),
  183. get_look_pitch = delay(def.look_pitch or 0),
  184. get_look_yaw = delay(def.look_yaw or 0),
  185. get_look_horizontal = delay(def.look_yaw or 0),
  186. get_look_vertical = delay(-(def.look_pitch or 0)),
  187. set_animation = delay(),
  188. -- Controls
  189. get_player_control = delay({
  190. jump=false, right=false, left=false, LMB=false, RMB=false,
  191. sneak=def.sneak, aux1=false, down=false, up=false
  192. }),
  193. get_player_control_bits = delay(def.sneak and 64 or 0),
  194. -- Inventory and ItemStacks
  195. get_inventory = delay(def.inventory),
  196. set_wielded_item = function(self, item)
  197. if self._inventory and def.wield_list then
  198. return self._inventory:set_stack(def.wield_list,
  199. self._wield_index, item)
  200. end
  201. _wielded_item = ItemStack(item)
  202. end,
  203. get_wielded_item = function(self, item)
  204. if self._inventory and def.wield_list then
  205. return self._inventory:get_stack(def.wield_list,
  206. self._wield_index)
  207. end
  208. return ItemStack(self._wielded_item)
  209. end,
  210. get_wield_list = delay(def.wield_list),
  211. punch = delay(),
  212. remove = delay(),
  213. right_click = delay(),
  214. set_attach = delay(),
  215. set_detach = delay(),
  216. set_bone_position = delay(),
  217. hud_change = delay(),
  218. }
  219. local _trash
  220. -- Getter & setter functions
  221. p.get_inventory_formspec, p.set_inventory_formspec
  222. = get_set_wrap("formspec", is_dynamic)
  223. p.get_breath, p.set_breath = get_set_wrap("breath", is_dynamic)
  224. p.get_hp, p.set_hp = get_set_wrap("hp", is_dynamic)
  225. p.get_pos, p.set_pos = get_set_wrap("pos", is_dynamic)
  226. _trash, p.move_to = get_set_wrap("pos", is_dynamic)
  227. p.get_wield_index, p.set_wield_index = get_set_wrap("wield_index", true)
  228. p.get_properties, p.set_properties = get_set_wrap("properties", false)
  229. -- Backwards compatibilty
  230. p.getpos = p.get_pos
  231. p.setpos = p.set_pos
  232. p.moveto = p.move_to
  233. -- TODO "implement" all these
  234. -- set_armor_groups
  235. -- get_armor_groups
  236. -- get_animation
  237. -- get_bone_position
  238. -- get_player_velocity
  239. -- set_look_pitch
  240. -- set_look_yaw
  241. -- set_physics_override
  242. -- get_physics_override
  243. -- hud_add
  244. -- hud_remove
  245. -- hud_get
  246. -- hud_set_flags
  247. -- hud_get_flags
  248. -- hud_set_hotbar_itemcount
  249. -- hud_get_hotbar_itemcount
  250. -- hud_set_hotbar_image
  251. -- hud_get_hotbar_image
  252. -- hud_set_hotbar_selected_image
  253. -- hud_get_hotbar_selected_image
  254. -- hud_replace_builtin
  255. -- set_sky
  256. -- get_sky
  257. -- override_day_night_ratio
  258. -- get_day_night_ratio
  259. -- set_local_animation
  260. return p
  261. end