init.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. --[[
  2. Mod for Minetest that adds bridges (only one node wide!), slim handrails and a self-building-one-node-wide bridge.
  3. Copyright (C) 2013 Sokomine
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. --]]
  15. -- to make life a bit easier
  16. bild_pfad = "default_wood.png"; --"forniture_wood.png";
  17. bild_pfad_s1 = bild_pfad; --"forniture_wood_s1.png";
  18. bild_pfad_s2 = bild_pfad; --"forniture_wood_s2.png";
  19. --bild_pfad_s1 = "default_wood.png"; --"forniture_wood_s1.png";
  20. --bild_pfad_s2 = "default_wood.png"; --"forniture_wood_s2.png";
  21. leg_front_left = {-0.5,-0.5,-0.5, -0.4,0.5,-0.4};
  22. leg_front_right = { 0.4,-0.5,-0.5, 0.5,0.5,-0.4};
  23. leg_back_left = {-0.5,-0.5, 0.4, -0.4,0.5, 0.5};
  24. leg_back_right = { 0.4,-0.5, 0.4, 0.5,0.5, 0.5};
  25. bar_left = {-0.5, 0.35,-0.4,-0.4, 0.4, 0.4};
  26. bar_right = { 0.4, 0.35,-0.4, 0.5, 0.4, 0.4};
  27. bar_back = { 0.4, 0.35, 0.4,-0.5, 0.4, 0.5};
  28. bar_front = { 0.5, 0.35,-0.5,-0.5, 0.4,-0.4};
  29. bar_left_long = {-0.4, 0.35,-0.5,-0.5, 0.4, 0.5};
  30. bar_right_long = { 0.4, 0.35,-0.5, 0.5, 0.4, 0.5};
  31. groundplate_small = {-0.4,-0.45,-0.5, 0.4,-0.4,0.5};
  32. groundplate_corner = {-0.5,-0.45,-0.5, 0.5,-0.4,0.5}; -- slightly larger
  33. local STICK = "group:stick";
  34. local WOOD = "stairs:slab_wood";
  35. local BASIS = "bridges:bridge_basis";
  36. local RAIL = "bridges:handrail_middle";
  37. -- people who do not have vines have to replace "vines:vines" with something they do have and which they think might fit
  38. local VINES = "vines:vines"; -- useful for ropes
  39. local ALT = "group:leaves"; -- alternative for vines
  40. if( minetest.get_modpath( 'moon' ) or minetest.get_modpath( 'moonrealm') or minetest.get_modpath( 'moontest') ) then
  41. STICK = "group:stick";
  42. WOOD = "default:steel_ingot";
  43. VINES = "group:stone";
  44. ALT = "group:leaves"; -- alternative for vines
  45. bild_pfad = "default_steel_block.png"; --"forniture_wood.png";
  46. bild_pfad_s1 = bild_pfad; --"forniture_wood_s1.png";
  47. bild_pfad_s2 = bild_pfad; --"forniture_wood_s2.png";
  48. -- only if no moontest is installed
  49. elseif( minetest.get_modpath( 'moreblocks' )) then
  50. WOOD = 'moreblocks:slab_wood';
  51. end
  52. local MAX_BRIDGE_LENGTH = 27; -- this is how far the automatic bridge can extend
  53. local BRIDGE_PARTS = {
  54. -- name, description, node definition, crafting receipe, additional information for yield of receipe
  55. -- the groundplate - essential for bridge building
  56. { "bridge_basis", "groundplate of a bridge", {
  57. groundplate_small, },
  58. { { VINES, VINES, VINES },
  59. { VINES, WOOD, VINES },
  60. { VINES, VINES, VINES }
  61. }, " 2"}, -- yields 2 groundplates
  62. -- the handrail is a basic part out of which bridges and handrails for staircases can be constructed
  63. { "handrail_middle", "handrail for bridges and staircases", {
  64. bar_front },
  65. { { "", "", "" },
  66. { "", BASIS, "" },
  67. { "", "", "" }
  68. }, " 4"}, -- one groundplate yiels 4 handrails
  69. -- bridges
  70. { "bridge_small", "small bridge", { -- TODO: slim legs?
  71. leg_front_left,
  72. leg_front_right,
  73. leg_back_left,
  74. leg_back_right,
  75. bar_right,
  76. bar_left,
  77. groundplate_small, },
  78. { { STICK, "", STICK },
  79. { RAIL, BASIS, RAIL },
  80. { STICK, "", STICK }
  81. }, "" },
  82. { "bridge_middle", "middle of a bridge", {
  83. bar_right_long,
  84. bar_left_long,
  85. groundplate_small, },
  86. { { "", "", "" },
  87. { RAIL, BASIS, RAIL },
  88. { "", "", "" }
  89. }, "" },
  90. { "bridge_corner", "corner of a bridge", {
  91. leg_front_left,
  92. leg_front_right,
  93. leg_back_left,
  94. leg_back_right,
  95. bar_right,
  96. bar_back,
  97. groundplate_corner, },
  98. { { STICK, RAIL, STICK },
  99. { "", BASIS, RAIL },
  100. { STICK, "", STICK }
  101. }, "" },
  102. { "bridge_t", "T junction of a bridge", {
  103. leg_front_left,
  104. leg_front_right,
  105. leg_back_left,
  106. leg_back_right,
  107. bar_back,
  108. groundplate_corner, },
  109. { { STICK, RAIL, STICK },
  110. { "", BASIS, "" },
  111. { STICK, "", STICK }
  112. }, "" },
  113. { "bridge_end", "end of a bridge", {
  114. leg_front_left,
  115. leg_front_right,
  116. leg_back_left,
  117. leg_back_right,
  118. bar_left,
  119. bar_right,
  120. bar_back,
  121. groundplate_corner, },
  122. { { STICK, RAIL, STICK },
  123. { RAIL, BASIS, RAIL },
  124. { STICK, "", STICK }
  125. }, "" },
  126. -- handrails for the top of starcaises so that people won't fall down
  127. { "handrail_top", "handrail for staircases, one side closed", {
  128. leg_front_left,
  129. leg_front_right,
  130. bar_front, },
  131. { { "", "", "" },
  132. { "", "", "" },
  133. { STICK, RAIL, STICK }
  134. }, "" },
  135. { "handrail_corner", "handrail for staircases, two sides closed", {
  136. leg_front_left,
  137. leg_front_right,
  138. bar_front,
  139. bar_left },
  140. { { STICK, "", "" },
  141. { RAIL, "", "" },
  142. { STICK, RAIL, STICK }
  143. }, "" },
  144. { "handrail_closed", "handrail for staircases, three sides closed", {
  145. leg_front_left,
  146. leg_front_right,
  147. bar_front,
  148. bar_right,
  149. bar_left },
  150. { { STICK, RAIL, STICK },
  151. { RAIL, "", "" },
  152. { STICK, RAIL, STICK }
  153. }, "" },
  154. }
  155. for i in ipairs( BRIDGE_PARTS ) do
  156. minetest.register_node("bridges:"..BRIDGE_PARTS[i][1],
  157. {
  158. description = BRIDGE_PARTS[i][2],
  159. tiles = {
  160. bild_pfad,
  161. bild_pfad,
  162. bild_pfad_s1,
  163. bild_pfad_s1,
  164. bild_pfad_s2,
  165. bild_pfad_s2,
  166. },
  167. drawtype = "nodebox",
  168. sunlight_propagates = true,
  169. paramtype = 'light',
  170. paramtype2 = "facedir",
  171. node_box = {
  172. type = "fixed",
  173. fixed = BRIDGE_PARTS[i][3],
  174. },
  175. selection_box = {
  176. type = "fixed",
  177. fixed = {-0.5,-0.5,-0.5, 0.5, 0.5, 0.5},
  178. },
  179. -- flammable so that it can be burned if no longer needed
  180. groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
  181. });
  182. minetest.register_craft({
  183. output = "bridges:"..BRIDGE_PARTS[i][1]..BRIDGE_PARTS[i][5],
  184. recipe = BRIDGE_PARTS[i][4],
  185. });
  186. end
  187. -- alternate receipe for the bridge basis
  188. minetest.register_craft({
  189. output = "bridges:bridge_basis 2",
  190. recipe = { { ALT, ALT, ALT },
  191. { ALT, WOOD, ALT },
  192. { ALT, ALT, ALT },
  193. },
  194. });
  195. -- a bridge with covers 3 nodes in size
  196. minetest.register_node("bridges:bridge_large",
  197. { description = 'large bridge',
  198. tiles = {
  199. bild_pfad,
  200. bild_pfad,
  201. bild_pfad_s1,
  202. bild_pfad_s1,
  203. bild_pfad_s2,
  204. bild_pfad_s2,
  205. },
  206. drawtype = "nodebox",
  207. sunlight_propagates = true,
  208. paramtype = 'light',
  209. paramtype2 = "facedir",
  210. node_box = {
  211. type = "fixed",
  212. fixed = {
  213. -- the large bridge covers 3 nodes
  214. {-0.5,-0.5,-0.7, -0.4,0.5,-0.6},
  215. { 0.4,-0.5,-0.7, 0.5,0.5,-0.6},
  216. {-0.5, 0.35,-1.5, -0.4,0.4, 1.5},
  217. {-0.5,-0.5, 0.6, -0.4,0.5, 0.7},
  218. { 0.4,-0.5, 0.6, 0.5,0.5, 0.7},
  219. { 0.4, 0.35,-1.5, 0.5,0.4, 1.5},
  220. {-0.4,-0.45,-1.5, 0.4,-0.4,1.5},
  221. }
  222. },
  223. selection_box = {
  224. type = "fixed",
  225. fixed = {-0.5,-0.5,-1.5, 0.5,0.5, 1.5},
  226. },
  227. groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=2}
  228. })
  229. minetest.register_craft({
  230. output = "bridges:bridge_large",
  231. recipe = { { "", "bridges:bridge_middle", "" },
  232. { "", "bridges:bridge_small", "" },
  233. { "", "bridges:bridge_middle", "" },
  234. } });
  235. -- special: self-building automatic bridge
  236. minetest.register_node("bridges:bridge_auto", {
  237. description = "self building bridge",
  238. tiles = { "default_chest_top.png" }, -- looks from all sides like the top of a chest
  239. drawtype = "cube",
  240. is_ground_content = true,
  241. groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
  242. drop = "", -- all leftover parts are in the "chest"
  243. on_construct = function(pos)
  244. local meta = minetest.env:get_meta(pos);
  245. meta:set_string("formspec",
  246. "invsize[8,9;]"..
  247. "list[current_name;main;0,0;8,4;]"..
  248. "list[current_player;main;0,5;8,4;]")
  249. meta:set_string("infotext", "Automatic bridge building set - leftover parts")
  250. local inv = meta:get_inventory();
  251. inv:set_size("main", 8*4);
  252. end,
  253. can_dig = function(pos,player)
  254. local meta = minetest.env:get_meta(pos);
  255. local inv = meta:get_inventory();
  256. return inv:is_empty("main");
  257. end,
  258. after_place_node = function(pos, placer)
  259. local n;
  260. local x_dir;
  261. local z_dir;
  262. local p;
  263. local n;
  264. -- the bridge ought to unfold in the direction the player is looking
  265. local dir = placer:get_look_dir();
  266. local fdir = minetest.dir_to_facedir(dir);
  267. -- the player is looking more in x- than in z-direction
  268. if( math.abs( dir.x ) > math.abs( dir.z )) then
  269. z_dir = 0;
  270. if( dir.x > 0 ) then
  271. x_dir = 1;
  272. else
  273. x_dir = -1;
  274. end
  275. else
  276. x_dir = 0;
  277. if( dir.z > 0 ) then
  278. z_dir = 1;
  279. else
  280. z_dir = -1;
  281. end
  282. end
  283. -- print ("x_dir: "..tostring( x_dir ).." z_dir: "..tostring( z_dir ));
  284. -- we have determined the direction in which the bridge may extend - now lets look how far it can go
  285. local i=1;
  286. -- how many parts of the bridge remain?
  287. local rem_small = math.floor(MAX_BRIDGE_LENGTH/3);
  288. local rem_middle = MAX_BRIDGE_LENGTH-rem_small;
  289. -- extend max. MAX_BRIDGE_LENGTH nodes wide and only if the node needs a bridge (i.e. consists of air)
  290. while( i < MAX_BRIDGE_LENGTH ) do
  291. -- is there space for a bridge?
  292. p = {x=pos.x+(x_dir*i), y=pos.y, z=pos.z+(z_dir*i)};
  293. n = minetest.env:get_node(p);
  294. if( n == nil or (n.name ~= "air" and n.name ~= 'moonrealm:vacuum' and n.name ~= 'moonrealm:air' and n.name ~= 'moontest:vacuum' and n.name ~= 'moontest:air')) then
  295. i = MAX_BRIDGE_LENGTH+1; -- end
  296. -- print("At length "..tostring(i)..": node at target position not air; no place for bridge: "..tostring(n.name));
  297. else
  298. -- one small bridge is followed by two middle parts
  299. if( i%3 == 1 ) then
  300. minetest.env:add_node(p, {name="bridges:bridge_small", param1=0, param2=fdir});
  301. rem_small = rem_small - 1; -- one small bridge used
  302. -- print("Placing small bridge at dist "..tostring(i));
  303. else
  304. minetest.env:add_node(p, {name="bridges:bridge_middle", param1=0, param2=fdir});
  305. rem_middle = rem_middle -1; -- one middle part used
  306. -- print("Placing middle bridge at dist "..tostring(i));
  307. end
  308. i = i+1;
  309. end
  310. end
  311. -- do we have to give any leftover parts back?
  312. local meta = minetest.env:get_meta(pos);
  313. local inv = meta:get_inventory();
  314. if( rem_small > 0 ) then
  315. inv:add_item( "main", "bridges:bridge_small "..tostring( rem_small ));
  316. end
  317. if( rem_middle > 0 ) then
  318. inv:add_item( "main", "bridges:bridge_middle "..tostring( rem_middle ));
  319. end
  320. end,
  321. })
  322. minetest.register_craft({
  323. output = "bridges:bridge_auto",
  324. recipe = { { "bridges:bridge_large", "bridges:bridge_large", "bridges:bridge_large" },
  325. { "bridges:bridge_large", "bridges:bridge_large", "bridges:bridge_large" },
  326. { "bridges:bridge_large", "bridges:bridge_large", "bridges:bridge_large" },
  327. } });