internal1.lua 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. --[[
  2. Tube Library 2
  3. ==============
  4. Copyright (C) 2018-2020 Joachim Stolberg
  5. LGPLv2.1+
  6. See LICENSE.txt for more information
  7. internal1.lua
  8. First level functions behind the API
  9. ]]--
  10. -- for lazy programmers
  11. local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
  12. local S2P = minetest.string_to_pos
  13. local M = minetest.get_meta
  14. -- Load support for I18n.
  15. local S = tubelib2.S
  16. local Tube = tubelib2.Tube
  17. local Turn180Deg = tubelib2.Turn180Deg
  18. local Dir6dToVector = tubelib2.Dir6dToVector
  19. local tValidNum = {[0] = true, true, true} -- 0..2 are valid
  20. local function get_pos(pos, dir)
  21. return vector.add(pos, Dir6dToVector[dir or 0])
  22. end
  23. local function fdir(self, player)
  24. local pitch = player:get_look_vertical()
  25. if pitch > 1.0 and self.valid_dirs[6] then -- up?
  26. return 6
  27. elseif pitch < -1.0 and self.valid_dirs[5] then -- down?
  28. return 5
  29. elseif not self.valid_dirs[1] then
  30. return 6
  31. else
  32. return minetest.dir_to_facedir(player:get_look_dir()) + 1
  33. end
  34. end
  35. local function get_player_data(self, placer, pointed_thing)
  36. if placer and pointed_thing and pointed_thing.type == "node" then
  37. if placer:get_player_control().sneak then
  38. return pointed_thing.under, fdir(self, placer)
  39. else
  40. return nil, fdir(self, placer)
  41. end
  42. end
  43. end
  44. -- Used to determine the node side to the tube connection.
  45. -- Function returns the first found dir value
  46. -- to a primary node.
  47. -- Only used by convert.set_pairing()
  48. function Tube:get_primary_dir(pos)
  49. -- Check all valid positions
  50. for dir = 1,6 do
  51. if self:is_primary_node(pos, dir) then
  52. return dir
  53. end
  54. end
  55. end
  56. -- pos/dir are the pos of the stable secondary node pointing to the head tube node.
  57. function Tube:del_from_cache(pos, dir)
  58. local key = P2S(pos)
  59. if self.connCache[key] and self.connCache[key][dir] then
  60. local pos2 = self.connCache[key][dir].pos2
  61. local dir2 = self.connCache[key][dir].dir2
  62. local key2 = P2S(pos2)
  63. if self.connCache[key2] and self.connCache[key2][dir2] then
  64. self.connCache[key2][dir2] = nil
  65. if self.debug_info then self.debug_info(pos2, "del") end
  66. end
  67. self.connCache[key][dir] = nil
  68. if self.debug_info then self.debug_info(pos, "del") end
  69. else
  70. if self.debug_info then self.debug_info(pos, "noc") end
  71. end
  72. end
  73. -- pos/dir are the pos of the secondary nodes pointing to the head tube nodes.
  74. function Tube:add_to_cache(pos1, dir1, pos2, dir2)
  75. local key = P2S(pos1)
  76. if not self.connCache[key] then
  77. self.connCache[key] = {}
  78. end
  79. self.connCache[key][dir1] = {pos2 = pos2, dir2 = dir2}
  80. if self.debug_info then self.debug_info(pos1, "add") end
  81. end
  82. -- pos/dir are the pos of the secondary nodes pointing to the head tube nodes.
  83. function Tube:update_secondary_node(pos1, dir1, pos2, dir2)
  84. local node,_ = self:get_secondary_node(pos1)
  85. if node then
  86. local ndef = minetest.registered_nodes[node.name] or {}
  87. -- New functions
  88. if ndef.tubelib2_on_update2 then
  89. ndef.tubelib2_on_update2(pos1, dir1, self, node)
  90. elseif self.clbk_update_secondary_node2 then
  91. self.clbk_update_secondary_node2(pos1, dir1, self, node)
  92. -- Legacy functions
  93. elseif ndef.tubelib2_on_update then
  94. ndef.tubelib2_on_update(node, pos1, dir1, pos2, Turn180Deg[dir2])
  95. elseif self.clbk_update_secondary_node then
  96. self.clbk_update_secondary_node(node, pos1, dir1, pos2, Turn180Deg[dir2])
  97. end
  98. end
  99. end
  100. function Tube:infotext(pos1, pos2)
  101. if self.show_infotext then
  102. if pos1 and pos2 then
  103. if vector.equals(pos1, pos2) then
  104. M(pos1):set_string("infotext", S("Not connected!"))
  105. else
  106. M(pos1):set_string("infotext", S("Connected to @1", P2S(pos2)))
  107. end
  108. end
  109. end
  110. end
  111. --------------------------------------------------------------------------------------
  112. -- pairing functions
  113. --------------------------------------------------------------------------------------
  114. -- Pairing helper function. NOT USED (see internal2.lua)!!!
  115. function Tube:store_teleport_data(pos, peer_pos)
  116. local meta = M(pos)
  117. meta:set_string("tele_pos", P2S(peer_pos))
  118. meta:set_string("channel", nil)
  119. meta:set_string("formspec", nil)
  120. meta:set_string("infotext", S("Paired with @1", P2S(peer_pos)))
  121. return meta:get_int("tube_dir")
  122. end
  123. -------------------------------------------------------------------------------
  124. -- update-after/get-dir functions
  125. -------------------------------------------------------------------------------
  126. function Tube:update_after_place_node(pos, dirs)
  127. -- Check all valid positions
  128. local lRes= {}
  129. dirs = dirs or self.dirs_to_check
  130. for _,dir in ipairs(dirs) do
  131. local npos, d1, d2, num = self:add_tube_dir(pos, dir)
  132. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and num < 2 then
  133. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num+1))
  134. lRes[#lRes+1] = dir
  135. end
  136. end
  137. return lRes
  138. end
  139. function Tube:update_after_dig_node(pos, dirs)
  140. -- Check all valid positions
  141. local lRes= {}
  142. dirs = dirs or self.dirs_to_check
  143. for _,dir in ipairs(dirs) do
  144. local npos, d1, d2, num = self:del_tube_dir(pos, dir)
  145. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num] then
  146. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
  147. lRes[#lRes+1] = dir
  148. end
  149. end
  150. return lRes
  151. end
  152. function Tube:update_after_place_tube(pos, placer, pointed_thing)
  153. local preferred_pos, fdir = get_player_data(self, placer, pointed_thing)
  154. local dir1, dir2, num_tubes = self:determine_tube_dirs(pos, preferred_pos, fdir)
  155. if dir1 == nil then
  156. return false
  157. end
  158. if self.valid_dirs[dir1] and self.valid_dirs[dir2] and tValidNum[num_tubes] then
  159. self.clbk_after_place_tube(self:get_tube_data(pos, dir1, dir2, num_tubes))
  160. end
  161. if num_tubes >= 1 then
  162. local npos, d1, d2, num = self:add_tube_dir(pos, dir1)
  163. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and num < 2 then
  164. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num+1))
  165. end
  166. end
  167. if num_tubes >= 2 then
  168. local npos, d1, d2, num = self:add_tube_dir(pos, dir2)
  169. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and num < 2 then
  170. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num+1))
  171. end
  172. end
  173. return true, dir1, dir2, num_tubes
  174. end
  175. function Tube:update_after_dig_tube(pos, param2)
  176. local dir1, dir2 = self:decode_param2(pos, param2)
  177. local npos, d1, d2, num = self:del_tube_dir(pos, dir1)
  178. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num] then
  179. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
  180. else
  181. dir1 = nil
  182. end
  183. npos, d1, d2, num = self:del_tube_dir(pos, dir2)
  184. if npos and self.valid_dirs[d1] and self.valid_dirs[d2] and tValidNum[num] then
  185. self.clbk_after_place_tube(self:get_tube_data(npos, d1, d2, num))
  186. else
  187. dir2 = nil
  188. end
  189. return dir1, dir2
  190. end
  191. -- Used by chat commands, when tubes are placed e.g. via WorldEdit
  192. function Tube:replace_nodes(pos1, pos2, dir1, dir2)
  193. self.clbk_after_place_tube(self:get_tube_data(pos1, dir1, dir2, 1))
  194. local pos = get_pos(pos1, dir1)
  195. while not vector.equals(pos, pos2) do
  196. self.clbk_after_place_tube(self:get_tube_data(pos, dir1, dir2, 2))
  197. pos = get_pos(pos, dir1)
  198. end
  199. self.clbk_after_place_tube(self:get_tube_data(pos2, dir1, dir2, 1))
  200. end
  201. function Tube:switch_nodes(pos, dir, state)
  202. pos = get_pos(pos, dir)
  203. local old_dir = dir
  204. while pos do
  205. local param2 = self:get_primary_node_param2(pos)
  206. if param2 then
  207. local dir1, dir2, num_conn = self:decode_param2(pos, param2)
  208. self.clbk_after_place_tube(self:get_tube_data(pos, dir1, dir2, num_conn, state))
  209. if dir1 == Turn180Deg[old_dir] then
  210. pos = get_pos(pos, dir2)
  211. old_dir = dir2
  212. else
  213. pos = get_pos(pos, dir1)
  214. old_dir = dir1
  215. end
  216. else
  217. break
  218. end
  219. end
  220. end